work on page form; add image selector

This commit is contained in:
bkfox
2024-03-16 06:00:15 +01:00
parent c74ec6fb16
commit eb5bdcf167
29 changed files with 611 additions and 174 deletions

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

View File

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

View File

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