Fix v-if with v-for
This commit is contained in:
parent
57aef1001e
commit
4865bf77be
|
@ -24,7 +24,6 @@ module.exports = {
|
||||||
],
|
],
|
||||||
rules: {
|
rules: {
|
||||||
'vue/no-v-html': 'off', // TODO: tackle this properly
|
'vue/no-v-html': 'off', // TODO: tackle this properly
|
||||||
'vue/no-use-v-if-with-v-for': 'off',
|
|
||||||
|
|
||||||
// NOTE: Handled by typescript
|
// NOTE: Handled by typescript
|
||||||
'no-undef': 'off',
|
'no-undef': 'off',
|
||||||
|
@ -42,6 +41,9 @@ module.exports = {
|
||||||
|
|
||||||
// TODO (wvffle): Migration to pinia
|
// TODO (wvffle): Migration to pinia
|
||||||
// Vuex 3 store does not have types defined, hence we use `any`
|
// Vuex 3 store does not have types defined, hence we use `any`
|
||||||
'@typescript-eslint/no-explicit-any': 'off'
|
'@typescript-eslint/no-explicit-any': 'off',
|
||||||
|
|
||||||
|
// TODO (wvffle): Migrate to <script setup>
|
||||||
|
'vue/require-explicit-emits': 'off'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,75 +72,74 @@
|
||||||
</translate>
|
</translate>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<template
|
<template v-if="plugin.conf?.length > 0">
|
||||||
v-for="(field, key) in plugin.conf"
|
<template v-for="(field, key) in plugin.conf">
|
||||||
v-if="plugin.conf && plugin.conf.length > 0"
|
<div
|
||||||
>
|
v-if="field.type === 'text'"
|
||||||
<div
|
:key="key"
|
||||||
v-if="field.type === 'text'"
|
class="field"
|
||||||
:key="key"
|
|
||||||
class="field"
|
|
||||||
>
|
|
||||||
<label :for="`plugin-${field.name}`">{{ field.label || field.name }}</label>
|
|
||||||
<input
|
|
||||||
:id="`plugin-${field.name}`"
|
|
||||||
v-model="values[field.name]"
|
|
||||||
type="text"
|
|
||||||
>
|
>
|
||||||
|
<label :for="`plugin-${field.name}`">{{ field.label || field.name }}</label>
|
||||||
|
<input
|
||||||
|
:id="`plugin-${field.name}`"
|
||||||
|
v-model="values[field.name]"
|
||||||
|
type="text"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-if="field.help"
|
||||||
|
v-html="markdown.makeHtml(field.help)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<div
|
<div
|
||||||
v-if="field.help"
|
v-if="field.type === 'long_text'"
|
||||||
v-html="markdown.makeHtml(field.help)"
|
:key="key"
|
||||||
/>
|
class="field"
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
v-if="field.type === 'long_text'"
|
|
||||||
:key="key"
|
|
||||||
class="field"
|
|
||||||
>
|
|
||||||
<label :for="`plugin-${field.name}`">{{ field.label || field.name }}</label>
|
|
||||||
<textarea
|
|
||||||
:id="`plugin-${field.name}`"
|
|
||||||
v-model="values[field.name]"
|
|
||||||
type="text"
|
|
||||||
rows="5"
|
|
||||||
/>
|
|
||||||
<div
|
|
||||||
v-if="field.help"
|
|
||||||
v-html="markdown.makeHtml(field.help)"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
v-if="field.type === 'url'"
|
|
||||||
:key="key"
|
|
||||||
class="field"
|
|
||||||
>
|
|
||||||
<label :for="`plugin-${field.name}`">{{ field.label || field.name }}</label>
|
|
||||||
<input
|
|
||||||
:id="`plugin-${field.name}`"
|
|
||||||
v-model="values[field.name]"
|
|
||||||
type="url"
|
|
||||||
>
|
>
|
||||||
|
<label :for="`plugin-${field.name}`">{{ field.label || field.name }}</label>
|
||||||
|
<textarea
|
||||||
|
:id="`plugin-${field.name}`"
|
||||||
|
v-model="values[field.name]"
|
||||||
|
type="text"
|
||||||
|
rows="5"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
v-if="field.help"
|
||||||
|
v-html="markdown.makeHtml(field.help)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<div
|
<div
|
||||||
v-if="field.help"
|
v-if="field.type === 'url'"
|
||||||
v-html="markdown.makeHtml(field.help)"
|
:key="key"
|
||||||
/>
|
class="field"
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
v-if="field.type === 'password'"
|
|
||||||
:key="key"
|
|
||||||
class="field"
|
|
||||||
>
|
|
||||||
<label :for="`plugin-${field.name}`">{{ field.label || field.name }}</label>
|
|
||||||
<input
|
|
||||||
:id="`plugin-${field.name}`"
|
|
||||||
v-model="values[field.name]"
|
|
||||||
type="password"
|
|
||||||
>
|
>
|
||||||
|
<label :for="`plugin-${field.name}`">{{ field.label || field.name }}</label>
|
||||||
|
<input
|
||||||
|
:id="`plugin-${field.name}`"
|
||||||
|
v-model="values[field.name]"
|
||||||
|
type="url"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-if="field.help"
|
||||||
|
v-html="markdown.makeHtml(field.help)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<div
|
<div
|
||||||
v-if="field.help"
|
v-if="field.type === 'password'"
|
||||||
v-html="markdown.makeHtml(field.help)"
|
:key="key"
|
||||||
/>
|
class="field"
|
||||||
</div>
|
>
|
||||||
|
<label :for="`plugin-${field.name}`">{{ field.label || field.name }}</label>
|
||||||
|
<input
|
||||||
|
:id="`plugin-${field.name}`"
|
||||||
|
v-model="values[field.name]"
|
||||||
|
type="password"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-if="field.help"
|
||||||
|
v-html="markdown.makeHtml(field.help)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
</template>
|
</template>
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
|
|
|
@ -97,8 +97,7 @@
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<span
|
<span
|
||||||
v-for="(part, key) in field.diff"
|
v-for="(part, key) in field.diff.filter(p => !p.added)"
|
||||||
v-if="!part.added"
|
|
||||||
:key="key"
|
:key="key"
|
||||||
:class="['diff', {removed: part.removed}]"
|
:class="['diff', {removed: part.removed}]"
|
||||||
>
|
>
|
||||||
|
@ -125,8 +124,7 @@
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<span
|
<span
|
||||||
v-for="(part, key) in field.diff"
|
v-for="(part, key) in field.diff.filter(p => !p.removed)"
|
||||||
v-if="!part.removed"
|
|
||||||
:key="key"
|
:key="key"
|
||||||
:class="['diff', {added: part.added}]"
|
:class="['diff', {added: part.added}]"
|
||||||
>
|
>
|
||||||
|
|
|
@ -95,108 +95,109 @@
|
||||||
You don't have the permission to edit this object, but you can suggest changes. Once submitted, suggestions will be reviewed before approval.
|
You don't have the permission to edit this object, but you can suggest changes. Once submitted, suggestions will be reviewed before approval.
|
||||||
</translate>
|
</translate>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<template v-if="values">
|
||||||
v-for="fieldConfig in config.fields"
|
<div
|
||||||
v-if="values"
|
v-for="fieldConfig in config.fields"
|
||||||
:key="fieldConfig.id"
|
:key="fieldConfig.id"
|
||||||
class="ui field"
|
class="ui field"
|
||||||
>
|
>
|
||||||
<template v-if="fieldConfig.type === 'text'">
|
<template v-if="fieldConfig.type === 'text'">
|
||||||
<label :for="fieldConfig.id">{{ fieldConfig.label }}</label>
|
<label :for="fieldConfig.id">{{ fieldConfig.label }}</label>
|
||||||
<input
|
<input
|
||||||
:id="fieldConfig.id"
|
:id="fieldConfig.id"
|
||||||
v-model="values[fieldConfig.id]"
|
v-model="values[fieldConfig.id]"
|
||||||
:type="fieldConfig.inputType || 'text'"
|
:type="fieldConfig.inputType || 'text'"
|
||||||
:required="fieldConfig.required"
|
:required="fieldConfig.required"
|
||||||
:name="fieldConfig.id"
|
:name="fieldConfig.id"
|
||||||
>
|
|
||||||
</template>
|
|
||||||
<template v-else-if="fieldConfig.type === 'license'">
|
|
||||||
<label :for="fieldConfig.id">{{ fieldConfig.label }}</label>
|
|
||||||
|
|
||||||
<select
|
|
||||||
:id="fieldConfig.id"
|
|
||||||
ref="license"
|
|
||||||
v-model="values[fieldConfig.id]"
|
|
||||||
:required="fieldConfig.required"
|
|
||||||
class="ui fluid search dropdown"
|
|
||||||
>
|
|
||||||
<option :value="null">
|
|
||||||
<translate translate-context="*/*/*">
|
|
||||||
N/A
|
|
||||||
</translate>
|
|
||||||
</option>
|
|
||||||
<option
|
|
||||||
v-for="license in licenses"
|
|
||||||
:key="license.code"
|
|
||||||
:value="license.code"
|
|
||||||
>
|
>
|
||||||
{{ license.name }}
|
</template>
|
||||||
</option>
|
<template v-else-if="fieldConfig.type === 'license'">
|
||||||
</select>
|
<label :for="fieldConfig.id">{{ fieldConfig.label }}</label>
|
||||||
<button
|
|
||||||
class="ui tiny basic left floated button"
|
<select
|
||||||
form="noop"
|
:id="fieldConfig.id"
|
||||||
@click.prevent="values[fieldConfig.id] = null"
|
ref="license"
|
||||||
>
|
v-model="values[fieldConfig.id]"
|
||||||
<i class="x icon" />
|
:required="fieldConfig.required"
|
||||||
<translate translate-context="Content/Library/Button.Label">
|
class="ui fluid search dropdown"
|
||||||
Clear
|
>
|
||||||
</translate>
|
<option :value="null">
|
||||||
</button>
|
<translate translate-context="*/*/*">
|
||||||
</template>
|
N/A
|
||||||
<template v-else-if="fieldConfig.type === 'content'">
|
</translate>
|
||||||
<label :for="fieldConfig.id">{{ fieldConfig.label }}</label>
|
</option>
|
||||||
<content-form
|
<option
|
||||||
v-model="values[fieldConfig.id].text"
|
v-for="license in licenses"
|
||||||
:field-id="fieldConfig.id"
|
:key="license.code"
|
||||||
:rows="3"
|
:value="license.code"
|
||||||
/>
|
>
|
||||||
</template>
|
{{ license.name }}
|
||||||
<template v-else-if="fieldConfig.type === 'attachment'">
|
</option>
|
||||||
<attachment-input
|
</select>
|
||||||
:id="fieldConfig.id"
|
<button
|
||||||
v-model="values[fieldConfig.id]"
|
class="ui tiny basic left floated button"
|
||||||
:initial-value="initialValues[fieldConfig.id]"
|
form="noop"
|
||||||
:required="fieldConfig.required"
|
@click.prevent="values[fieldConfig.id] = null"
|
||||||
:name="fieldConfig.id"
|
>
|
||||||
@delete="values[fieldConfig.id] = initialValues[fieldConfig.id]"
|
<i class="x icon" />
|
||||||
>
|
<translate translate-context="Content/Library/Button.Label">
|
||||||
<span>{{ fieldConfig.label }}</span>
|
Clear
|
||||||
</attachment-input>
|
</translate>
|
||||||
</template>
|
</button>
|
||||||
<template v-else-if="fieldConfig.type === 'tags'">
|
</template>
|
||||||
<label :for="fieldConfig.id">{{ fieldConfig.label }}</label>
|
<template v-else-if="fieldConfig.type === 'content'">
|
||||||
<tags-selector
|
<label :for="fieldConfig.id">{{ fieldConfig.label }}</label>
|
||||||
:id="fieldConfig.id"
|
<content-form
|
||||||
ref="tags"
|
v-model="values[fieldConfig.id].text"
|
||||||
v-model="values[fieldConfig.id]"
|
:field-id="fieldConfig.id"
|
||||||
required="fieldConfig.required"
|
:rows="3"
|
||||||
/>
|
/>
|
||||||
<button
|
</template>
|
||||||
class="ui tiny basic left floated button"
|
<template v-else-if="fieldConfig.type === 'attachment'">
|
||||||
form="noop"
|
<attachment-input
|
||||||
@click.prevent="values[fieldConfig.id] = []"
|
:id="fieldConfig.id"
|
||||||
>
|
v-model="values[fieldConfig.id]"
|
||||||
<i class="x icon" />
|
:initial-value="initialValues[fieldConfig.id]"
|
||||||
<translate translate-context="Content/Library/Button.Label">
|
:required="fieldConfig.required"
|
||||||
Clear
|
:name="fieldConfig.id"
|
||||||
</translate>
|
@delete="values[fieldConfig.id] = initialValues[fieldConfig.id]"
|
||||||
</button>
|
>
|
||||||
</template>
|
<span>{{ fieldConfig.label }}</span>
|
||||||
<div v-if="fieldValuesChanged(fieldConfig.id)">
|
</attachment-input>
|
||||||
<button
|
</template>
|
||||||
class="ui tiny basic right floated reset button"
|
<template v-else-if="fieldConfig.type === 'tags'">
|
||||||
form="noop"
|
<label :for="fieldConfig.id">{{ fieldConfig.label }}</label>
|
||||||
@click.prevent="resetField(fieldConfig.id)"
|
<tags-selector
|
||||||
>
|
:id="fieldConfig.id"
|
||||||
<i class="undo icon" />
|
ref="tags"
|
||||||
<translate translate-context="Content/Library/Button.Label">
|
v-model="values[fieldConfig.id]"
|
||||||
Reset to initial value
|
required="fieldConfig.required"
|
||||||
</translate>
|
/>
|
||||||
</button>
|
<button
|
||||||
|
class="ui tiny basic left floated button"
|
||||||
|
form="noop"
|
||||||
|
@click.prevent="values[fieldConfig.id] = []"
|
||||||
|
>
|
||||||
|
<i class="x icon" />
|
||||||
|
<translate translate-context="Content/Library/Button.Label">
|
||||||
|
Clear
|
||||||
|
</translate>
|
||||||
|
</button>
|
||||||
|
</template>
|
||||||
|
<div v-if="fieldValuesChanged(fieldConfig.id)">
|
||||||
|
<button
|
||||||
|
class="ui tiny basic right floated reset button"
|
||||||
|
form="noop"
|
||||||
|
@click.prevent="resetField(fieldConfig.id)"
|
||||||
|
>
|
||||||
|
<i class="undo icon" />
|
||||||
|
<translate translate-context="Content/Library/Button.Label">
|
||||||
|
Reset to initial value
|
||||||
|
</translate>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</template>
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label for="summary"><translate translate-context="*/*/*">Summary (optional)</translate></label>
|
<label for="summary"><translate translate-context="*/*/*">Summary (optional)</translate></label>
|
||||||
<textarea
|
<textarea
|
||||||
|
|
|
@ -189,8 +189,7 @@
|
||||||
<table class="queue">
|
<table class="queue">
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr
|
<tr
|
||||||
v-for="(track, index) in tracks"
|
v-for="(track, index) in filteredTracks"
|
||||||
v-if="track.sources.length > 0"
|
|
||||||
:id="'queue-item-' + index"
|
:id="'queue-item-' + index"
|
||||||
:key="index"
|
:key="index"
|
||||||
role="button"
|
role="button"
|
||||||
|
@ -249,6 +248,7 @@ import axios from 'axios'
|
||||||
import Logo from '~/components/Logo.vue'
|
import Logo from '~/components/Logo.vue'
|
||||||
import updateQueryString from '~/composables/updateQueryString'
|
import updateQueryString from '~/composables/updateQueryString'
|
||||||
import time from '~/utils/time'
|
import time from '~/utils/time'
|
||||||
|
import { reactive, computed } from 'vue'
|
||||||
|
|
||||||
function getURLParams () {
|
function getURLParams () {
|
||||||
let match
|
let match
|
||||||
|
@ -265,6 +265,12 @@ function getURLParams () {
|
||||||
export default {
|
export default {
|
||||||
name: 'App',
|
name: 'App',
|
||||||
components: { Logo },
|
components: { Logo },
|
||||||
|
setup () {
|
||||||
|
const tracks = reactive([])
|
||||||
|
const filteredTracks = computed(() => tracks.filter(track => track.sources.length > 0))
|
||||||
|
|
||||||
|
return { tracks, filteredTracks }
|
||||||
|
},
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
time,
|
time,
|
||||||
|
@ -273,7 +279,6 @@ export default {
|
||||||
error: null,
|
error: null,
|
||||||
type: null,
|
type: null,
|
||||||
id: null,
|
id: null,
|
||||||
tracks: [],
|
|
||||||
autoplay: false,
|
autoplay: false,
|
||||||
url: null,
|
url: null,
|
||||||
isLoading: true,
|
isLoading: true,
|
||||||
|
@ -404,26 +409,25 @@ export default {
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
fetchTrack (id) {
|
fetchTrack (id) {
|
||||||
const self = this
|
|
||||||
const url = `${this.baseUrl}/api/v1/tracks/${id}/`
|
const url = `${this.baseUrl}/api/v1/tracks/${id}/`
|
||||||
axios.get(url).then(response => {
|
axios.get(url).then(() => {
|
||||||
self.tracks = self.parseTracks([response.data])
|
this.tracks = this.parseTracks([response.data])
|
||||||
self.isLoading = false
|
this.isLoading = false
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
if (error.response) {
|
if (error.response) {
|
||||||
if (error.response.status === 404) {
|
if (error.response.status === 404) {
|
||||||
self.error = 'server_not_found'
|
this.error = 'server_not_found'
|
||||||
} else if (error.response.status === 403) {
|
} else if (error.response.status === 403) {
|
||||||
self.error = 'server_requires_auth'
|
this.error = 'server_requires_auth'
|
||||||
} else if (error.response.status === 500) {
|
} else if (error.response.status === 500) {
|
||||||
self.error = 'server_error'
|
this.error = 'server_error'
|
||||||
} else {
|
} else {
|
||||||
self.error = 'server_unknown_error'
|
this.error = 'server_unknown_error'
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.error = 'server_unknown_error'
|
this.error = 'server_unknown_error'
|
||||||
}
|
}
|
||||||
self.isLoading = false
|
this.isLoading = false
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
fetchTracks (filters, path) {
|
fetchTracks (filters, path) {
|
||||||
|
|
Loading…
Reference in New Issue