work on page form; add image selector
This commit is contained in:
124
assets/src/components/ASelectFile.vue
Normal file
124
assets/src/components/ASelectFile.vue
Normal file
@@ -0,0 +1,124 @@
|
||||
<template>
|
||||
<div class="a-select-file">
|
||||
<div class="a-select-file-list" ref="list">
|
||||
<div class="flex-column file-preview">
|
||||
<div class="field flex-grow-1" v-if="!uploadFile">
|
||||
<label class="label">{{ uploadLabel }}</label>
|
||||
<input type="file" @change="previewFile"/>
|
||||
</div>
|
||||
<slot name="upload-preview" :item="uploadFile"></slot>
|
||||
<div v-if="uploadFile">
|
||||
<button class="button secondary" @click="removeUpload">
|
||||
<span class="icon">
|
||||
<i class="fa fa-trash"></i>
|
||||
</span>
|
||||
</button>
|
||||
<button class="button float-right" @click="doUpload">
|
||||
<span class="icon">
|
||||
<i class="fa fa-upload"></i>
|
||||
</span>
|
||||
Upload
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="prevUrl">
|
||||
<a href="#" @click="load(prevUrl)">
|
||||
{{ prevLabel }}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<template v-for="item in items" v-bind:key="item.id">
|
||||
<div :class="['file-preview', this.item && item.id == this.item.id && 'active']" @click="select(item)">
|
||||
<slot :item="item"></slot>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div v-if="nextUrl">
|
||||
<a href="#" @click="load(nextUrl)">
|
||||
{{ nextLabel }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="a-select-footer">
|
||||
<slot name="footer" :item="item" :items="items"></slot>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import {getCsrf} from "../model"
|
||||
|
||||
export default {
|
||||
props: {
|
||||
name: { type: String },
|
||||
prevLabel: { type: String, default: "Prev" },
|
||||
nextLabel: { type: String, default: "Next" },
|
||||
listUrl: { type: String },
|
||||
uploadLabel: { type: String, default: "Upload a file" },
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
item: null,
|
||||
items: [],
|
||||
uploadFile: null,
|
||||
uploadUrl: null,
|
||||
uploadFieldName: null,
|
||||
uploadCSRF: null,
|
||||
nextUrl: "",
|
||||
prevUrl: "",
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
previewFile(event) {
|
||||
const [file] = event.target.files
|
||||
this.uploadFile = file && {
|
||||
file: file,
|
||||
src: URL.createObjectURL(file)
|
||||
}
|
||||
},
|
||||
|
||||
removeUpload() {
|
||||
this.uploadFile = null;
|
||||
},
|
||||
|
||||
doUpload() {
|
||||
const formData = new FormData();
|
||||
formData.append('file', this.uploadFile.file)
|
||||
formData.append('original_filename', this.uploadFile.file.name)
|
||||
formData.append('csrfmiddlewaretoken', getCsrf())
|
||||
fetch(this.listUrl, {
|
||||
method: "POST",
|
||||
body: formData
|
||||
}).then(
|
||||
() => {
|
||||
this.uploadFile = null;
|
||||
this.load()
|
||||
}
|
||||
)
|
||||
},
|
||||
|
||||
load(url) {
|
||||
fetch(url || this.listUrl).then(
|
||||
response => response.ok ? response.json() : Promise.reject(response)
|
||||
).then(data => {
|
||||
this.nextUrl = data.next
|
||||
this.prevUrl = data.previous
|
||||
this.items = data.results
|
||||
|
||||
this.$forceUpdate()
|
||||
this.$refs.list.scroll(0, 0)
|
||||
})
|
||||
},
|
||||
|
||||
select(item) {
|
||||
this.item = item;
|
||||
},
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.load()
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@@ -1,5 +1,6 @@
|
||||
<template>
|
||||
<button :title="ariaLabel"
|
||||
type="button"
|
||||
:aria-label="ariaLabel || label" :aria-description="ariaDescription"
|
||||
@click="toggle" :class="buttonClass">
|
||||
<slot name="default" :active="active">
|
||||
@@ -49,17 +50,21 @@ export default {
|
||||
},
|
||||
|
||||
set(active) {
|
||||
const el = document.querySelector(this.el)
|
||||
if(active)
|
||||
el.classList.add(this.activeClass)
|
||||
else
|
||||
el.classList.remove(this.activeClass)
|
||||
if(this.el) {
|
||||
const el = document.querySelector(this.el)
|
||||
if(active)
|
||||
el.classList.add(this.activeClass)
|
||||
else
|
||||
el.classList.remove(this.activeClass)
|
||||
}
|
||||
this.active = active
|
||||
if(active)
|
||||
this.resetGroup()
|
||||
},
|
||||
|
||||
resetGroup() {
|
||||
if(!this.groupClass)
|
||||
return
|
||||
const els = document.querySelectorAll("." + this.groupClass)
|
||||
for(var el of els)
|
||||
if(el != this.$el)
|
||||
|
||||
@@ -12,13 +12,15 @@ import ASoundItem from './ASoundItem.vue'
|
||||
import ASwitch from './ASwitch.vue'
|
||||
import AStatistics from './AStatistics.vue'
|
||||
import AStreamer from './AStreamer.vue'
|
||||
import ASelectFile from "./ASelectFile.vue"
|
||||
|
||||
/**
|
||||
* Core components
|
||||
*/
|
||||
export const base = {
|
||||
AAutocomplete, ACarousel, ADropdown, AEpisode, AList, APage, APlayer, APlaylist,
|
||||
AProgress, ASoundItem, ASwitch
|
||||
AProgress, ASoundItem, ASwitch,
|
||||
ASelectFile,
|
||||
}
|
||||
|
||||
export default base
|
||||
|
||||
Reference in New Issue
Block a user