See #432: UI to suggest tags on tracks, albums and artists

environments/review-front-arti-0habim/deployments/2230
Eliot Berriot 2019-07-16 12:26:17 +02:00
rodzic 9336fec430
commit d2b7db2cac
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: DD6965E2476E5C27
5 zmienionych plików z 155 dodań i 27 usunięć

Wyświetl plik

@ -49,7 +49,7 @@
</tr>
</thead>
<tbody>
<tr v-for="field in getUpdatedFields(obj.payload, previousState)" :key="field.id">
<tr v-for="field in updatedFields" :key="field.id">
<td>{{ field.id }}</td>
<td v-if="field.diff">
@ -61,12 +61,12 @@
<translate translate-context="*/*/*">N/A</translate>
</td>
<td v-if="field.diff">
<td v-if="field.diff" :title="field.newRepr">
<span v-if="!part.removed" v-for="part in field.diff" :class="['diff', {added: part.added}]">
{{ part.value }}
</span>
</td>
<td v-else>{{ field.new }}</td>
<td v-else :title="field.newRepr">{{ field.newRepr }}</td>
</tr>
</tbody>
</table>
@ -126,6 +126,7 @@ export default {
}
},
computed: {
configs: edits.getConfigs,
canApprove: edits.getCanApprove,
canDelete: edits.getCanDelete,
previousState () {
@ -154,6 +155,32 @@ export default {
namespace = 'library.artists.edit.detail'
}
return this.$router.resolve({name: namespace, params: {id, editId: this.obj.uuid}}).href
},
updatedFields () {
let payload = this.obj.payload
let previousState = this.previousState
let fields = Object.keys(payload)
let self = this
return fields.map((f) => {
let fieldConfig = edits.getFieldConfig(self.configs, this.obj.target.type, f)
let dummyRepr = (v) => { return v }
let getValueRepr = fieldConfig.getValueRepr || dummyRepr
let d = {
id: f,
}
if (previousState && previousState[f]) {
d.old = previousState[f]
d.oldRepr = castValue(getValueRepr(d.old.value))
}
d.new = payload[f]
d.newRepr = castValue(getValueRepr(d.new))
if (d.old) {
// we compute the diffs between the old and new values
d.diff = diffWordsWithSpace(d.oldRepr, d.newRepr)
}
return d
})
}
},
methods: {
@ -184,26 +211,6 @@ export default {
self.isLoading = false
})
},
getUpdatedFields (payload, previousState) {
let fields = Object.keys(payload)
return fields.map((f) => {
let d = {
id: f,
}
if (previousState && previousState[f]) {
d.old = previousState[f]
}
d.new = payload[f]
if (d.old) {
// we compute the diffs between the old and new values
let oldValue = castValue(d.old.value)
let newValue = castValue(d.new)
d.diff = diffWordsWithSpace(oldValue, newValue)
}
return d
})
}
}
}
</script>

Wyświetl plik

@ -77,10 +77,22 @@
</button>
</template>
<template v-else-if="fieldConfig.type === 'tags'">
<label :for="fieldConfig.id">{{ fieldConfig.label }}</label>
<tags-selector
ref="tags"
v-model="values[fieldConfig.id]"
:id="fieldConfig.id"
required="fieldConfig.required"></tags-selector>
<button class="ui tiny basic left floated button" form="noop" @click.prevent="values[fieldConfig.id] = []">
<i class="x icon"></i>
<translate translate-context="Content/Library/Button.Label">Clear</translate>
</button>
</template>
<div v-if="values[fieldConfig.id] != initialValues[fieldConfig.id]">
<button class="ui tiny basic right floated reset button" form="noop" @click.prevent="values[fieldConfig.id] = initialValues[fieldConfig.id]">
<i class="undo icon"></i>
<translate translate-context="Content/Library/Button.Label" :translate-params="{value: initialValues[fieldConfig.id] || ''}">Reset to initial value: %{ value }</translate>
<translate translate-context="Content/Library/Button.Label">Reset to initial value</translate>
</button>
</div>
</div>
@ -110,13 +122,17 @@ import _ from '@/lodash'
import axios from "axios"
import EditList from '@/components/library/EditList'
import EditCard from '@/components/library/EditCard'
import TagsSelector from '@/components/library/TagsSelector'
import edits from '@/edits'
import lodash from '@/lodash'
export default {
props: ["objectType", "object", "licenses"],
components: {
EditList,
EditCard
EditCard,
TagsSelector
},
data() {
return {
@ -159,7 +175,7 @@ export default {
mutationPayload () {
let self = this
let changedFields = this.config.fields.filter(f => {
return self.values[f.id] != self.initialValues[f.id]
return !lodash.isEqual(self.values[f.id], self.initialValues[f.id])
})
if (changedFields.length === 0) {
return null

Wyświetl plik

@ -0,0 +1,68 @@
<template>
<div ref="dropdown" class="ui multiple search selection dropdown">
<input type="hidden">
<i class="dropdown icon"></i>
<input type="text" class="search">
<div class="default text">
<translate translate-context="*/Dropdown/Placeholder/Verb">Search for existing tags</translate>
</div>
</div>
</template>
<script>
import $ from 'jquery'
import lodash from '@/lodash'
export default {
props: ['value'],
mounted () {
this.$nextTick(() => {
this.initDropdown()
})
},
methods: {
initDropdown () {
let self = this
let handleUpdate = () => {
let value = $(self.$refs.dropdown).dropdown('get value').split(',')
self.$emit('input', value)
return value
}
let settings = {
saveRemoteData: false,
filterRemoteData: true,
apiSettings: {
url: this.$store.getters['instance/absoluteUrl']('/api/v1/tags/?name__startswith={query}&ordering=length&page_size=5'),
beforeXHR: function (xhrObject) {
xhrObject.setRequestHeader('Authorization', self.$store.getters['auth/header'])
return xhrObject
},
},
fields: {
remoteValues: 'results',
value: 'name'
},
allowAdditions: true,
minCharacters: 1,
onAdd: handleUpdate,
onRemove: handleUpdate,
onLabelRemove: handleUpdate,
onChange: handleUpdate,
}
$(this.$refs.dropdown).dropdown(settings)
$(this.$refs.dropdown).dropdown('set exactly', this.value)
}
},
watch: {
value: {
handler (v) {
let current = $(this.$refs.dropdown).dropdown('get value').split(',').sort()
if (!lodash.isEqual([...v].sort(), current)) {
$(this.$refs.dropdown).dropdown('set exactly', v)
}
},
deep: true
}
}
}
</script>

Wyświetl plik

@ -1,3 +1,10 @@
function getTagsValueRepr (val) {
if (!val) {
return ''
}
return val.slice().sort().join('\n')
}
export default {
getConfigs () {
return {
@ -10,6 +17,14 @@ export default {
label: this.$pgettext('*/*/*/Noun', 'Name'),
getValue: (obj) => { return obj.name }
},
{
id: 'tags',
type: 'tags',
required: true,
label: this.$pgettext('*/*/*/Noun', 'Tags'),
getValue: (obj) => { return obj.tags },
getValueRepr: getTagsValueRepr
}
]
},
album: {
@ -28,6 +43,14 @@ export default {
label: this.$pgettext('Content/*/*/Noun', 'Release date'),
getValue: (obj) => { return obj.release_date }
},
{
id: 'tags',
type: 'tags',
required: true,
label: this.$pgettext('*/*/*/Noun', 'Tags'),
getValue: (obj) => { return obj.tags },
getValueRepr: getTagsValueRepr
}
]
},
track: {
@ -61,6 +84,14 @@ export default {
label: this.$pgettext('Content/*/*/Noun', 'License'),
getValue: (obj) => { return obj.license },
},
{
id: 'tags',
type: 'tags',
required: true,
label: this.$pgettext('*/*/*/Noun', 'Tags'),
getValue: (obj) => { return obj.tags },
getValueRepr: getTagsValueRepr
}
]
}
}
@ -69,7 +100,12 @@ export default {
getConfig () {
return this.configs[this.objectType]
},
getFieldConfig (configs, type, fieldId) {
let c = configs[type]
return c.fields.filter((f) => {
return f.id == fieldId
})[0]
},
getCurrentState () {
let self = this
let s = {}

Wyświetl plik

@ -12,4 +12,5 @@ export default {
uniq: require('lodash/uniq'),
remove: require('lodash/remove'),
reverse: require('lodash/reverse'),
isEqual: require('lodash/isEqual'),
}