Fix v-if with v-for

environments/review-front-deve-otr6gc/deployments/13419
Kasper Seweryn 2022-05-01 16:35:58 +02:00 zatwierdzone przez Georg Krause
rodzic 57aef1001e
commit 4865bf77be
5 zmienionych plików z 186 dodań i 182 usunięć

Wyświetl plik

@ -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'
} }
} }

Wyświetl plik

@ -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"

Wyświetl plik

@ -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}]"
> >

Wyświetl plik

@ -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

Wyświetl plik

@ -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) {