pi-rfid-jukebox/static/library.js

162 lines
3.9 KiB
JavaScript

(function() {
var appData = {
tracks: [],
tags: [],
highlightedTag: null,
};
const MediaTrack = {
props: [
'track',
'tags',
'highlightedTag',
],
data: function() {
return {
editing: false,
saving: false,
trackForReset: {},
}
},
computed: {
patch_url: function() {
return '/api/tracks/' + this.track.uuid;
},
},
methods: {
edit: function() {
if (this.editing) {
return;
}
this.trackForReset = Object.assign({}, this.track);
this.saving = false;
this.editing = true;
},
cancel: function() {
this.track = Object.assign({}, this.trackForReset);
this.editing = false;
},
save: function() {
this.saving = true;
var request = new Request(this.patch_url, {
method: "PATCH",
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
tag: this.track.tag,
label: this.track.label,
})
});
fetch(request)
.then(response => {
return response.json();
})
.then(response => {
this.editing = false;
this.track.label = response.label;
this.track.tag = response.tag;
})
.catch(error => {
console.error(error)
});
},
highlightTag: function() {
this.$root.highlightedTag = this.track.tag;
},
highlightNone: function() {
this.$root.highlightedTag = null;
},
},
template: `
<div class="media-track"
:class="{ 'media-track-highlighted': track.tag === highlightedTag, 'media-track-tagless': track.tag === '' }"
@click="edit()"
@mouseover="highlightTag()"
@mouseout="highlightNone()">
<template v-if="editing">
<form method="patch" :action="patch_url" @keyup.27="cancel">
<select v-model="track.tag" :disabled="saving">
<option value=""></option>
<option :class="{unused: tag.tag_count == 0}" v-for="tag in tags">
{{ tag.tag }}
</option>
</select>
<input type="text" v-model="track.label" :disabled="saving">
<input type="submit" value="Save" @click.prevent.stop.once="save()" :disabled="saving">
</form>
</template>
<template v-else>{{ track.label }}</template>
</div>
`
};
const MediaLibrary = {
props: ['tracks', 'tags', 'highlightedTag'],
components: {
'media-track': MediaTrack,
},
template: `
<div class="media-library">
<media-track v-for="track in tracks"
:key="track.uuid"
:track="track"
:tags="tags"
:highlightedTag="highlightedTag"
></media-track>
</div>
`,
};
const UploadBox = {
template: `
<div class="upload-box">
<h2>Upload File</h2>
<form method="post" action="/api/tracks" enctype="multipart/form-data">
<input name="track" type="file">
<input type="submit" value="Upload">
</form>
</div>
`
};
var app = new Vue({
el: '#app',
data: appData,
components: {
'media-library': MediaLibrary,
'upload-box': UploadBox,
},
});
var request = new Request('/api/tags');
fetch(request)
.then(response => {
return response.json();
})
.then(response => {
appData.tags = response;
})
.catch(error => {
console.error(error);
});
var request = new Request('/api/tracks');
fetch(request)
.then(response => {
return response.json();
})
.then(response => {
appData.tracks = response;
})
.catch(error => {
console.error(error);
});
})();
// vim:ts=2 sw=2 et: