Commit 21d1ad5c by Jonathan Thomas

Refactored preview data to live in Vuex. Made clip seconds label react different…

Refactored preview data to live in Vuex. Made clip seconds label react different when it's too small. Added drop-shadow style to context menu buttons. Added editClip action, but not connected yet.
parent f9452bb5
<template> <template>
<div class="row mb-3 p-2 scrolling-container"> <div class="row mb-3 gx-2 p-2 scrolling-container">
<h3>Clips</h3> <h3>Clips <button v-if="clips" type="button" class="btn btn-danger export-btn">Export</button></h3>
<div class="col-12"> <div class="col-12">
<div class="row gy-2 gx-2 mb-2" v-for="clip in thumbnailedClips" :key="clip.id"> <div class="row gy-2 gx-2 mb-2" v-for="(clip, index) in thumbnailedClips" :key="clip.id">
<div class="col-12 text-center img-parent"> <div class="col-12 text-center img-parent">
<span class="clip-badge badge">{{ index + 1 }}</span>
<div class="btn-group dropstart context-menu"> <div class="btn-group dropstart context-menu">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="dropdown-toggle bi bi-three-dots-vertical" data-bs-toggle="dropdown" aria-expanded="false" viewBox="0 0 16 16"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="dropdown-toggle bi bi-three-dots-vertical" data-bs-toggle="dropdown" aria-expanded="false" viewBox="0 0 16 16">
<path d="M9.5 13a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z"/> <path d="M9.5 13a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z"/>
...@@ -18,7 +20,7 @@ ...@@ -18,7 +20,7 @@
</ul> </ul>
</div> </div>
<div class="clip-label"> <div ref="clip" class="clip-label">
{{ (clip.end - clip.start).toFixed(1) }} Seconds {{ (clip.end - clip.start).toFixed(1) }} Seconds
</div> </div>
...@@ -45,14 +47,14 @@ export default { ...@@ -45,14 +47,14 @@ export default {
this.deleteClip(clip_id) this.deleteClip(clip_id)
}, },
toggleSelection(clipObj) { toggleSelection(clipObj) {
if (clipObj.fileObj != this.previewFile) { if (clipObj.fileObj != this.preview.file) {
this.setPreviewFile(clipObj.fileObj) this.setPreviewFile(clipObj.fileObj)
} else { } else {
this.setPreviewFile(null) this.setPreviewFile(null)
} }
}, },
getSelectedClass(clipObj) { getSelectedClass(clipObj) {
if (this.previewFile && clipObj.fileObj.id == this.previewFile.id) { if (this.preview.file && clipObj.fileObj.id == this.preview.file.id) {
return 'selected' return 'selected'
} else { } else {
return '' return ''
...@@ -65,10 +67,10 @@ export default { ...@@ -65,10 +67,10 @@ export default {
thumbnailedClips() { thumbnailedClips() {
return this.clips.filter(clip => clip.thumbnail) return this.clips.filter(clip => clip.thumbnail)
}, },
...mapState(['clips', 'previewFile', 'latestClip']) ...mapState(['clips', 'preview', 'scrollToClip'])
}, },
watch: { watch: {
latestClip() { scrollToClip() {
this.$nextTick(() => { this.$nextTick(() => {
this.$refs.bottom.scrollIntoView({behavior: 'smooth', block: 'end'}) this.$refs.bottom.scrollIntoView({behavior: 'smooth', block: 'end'})
}) })
...@@ -116,9 +118,28 @@ export default { ...@@ -116,9 +118,28 @@ export default {
.clip-label { .clip-label {
color: #ffffff; color: #ffffff;
position: absolute; position: absolute;
top: 88%; bottom: 5%;
z-index: 999; z-index: 999;
right: 5%; right: 5%;
font-size: .8em; font-size: .8em;
background-color: #000000;
border-radius: 4px;
padding: 3px;
opacity: 75%;
}
.export-btn {
float: right;
}
.dropdown-toggle {
filter: drop-shadow(0px 0px 2px #000000);
}
.clip-badge {
position: absolute;
bottom: 5%;
left: 5%;
padding: 8px;
opacity: 75%;
background-color: #000000;
border-radius: 4px;
} }
</style> </style>
\ No newline at end of file
<template> <template>
<div class="row mb-3 gy-2 gx-2 p-2 scrolling-container"> <div class="row mb-3 gx-2 p-2 scrolling-container">
<h3>Files <button type="button" class="btn btn-primary upload-btn" @click="chooseFiles">Upload</button></h3> <h3>Files <button type="button" class="btn btn-primary upload-btn" @click="chooseFiles">Upload</button></h3>
<div class="col-sm-12"> <div class="col-sm-12">
<div class="form-floating mb-3"> <div class="form-floating mb-3">
...@@ -75,14 +75,14 @@ export default { ...@@ -75,14 +75,14 @@ export default {
await this.deleteFile(file.id) await this.deleteFile(file.id)
}, },
toggleSelection(fileObject) { toggleSelection(fileObject) {
if (fileObject != this.previewFile) { if (fileObject != this.preview.file) {
this.setPreviewFile(fileObject) this.setPreviewFile(fileObject)
} else { } else {
this.setPreviewFile(null) this.setPreviewFile(null)
} }
}, },
getSelectedClass(fileObject) { getSelectedClass(fileObject) {
if (this.previewFile && fileObject.id == this.previewFile.id) { if (this.preview.file && fileObject.id == this.preview.file.id) {
return 'selected' return 'selected'
} else { } else {
return '' return ''
...@@ -103,7 +103,7 @@ export default { ...@@ -103,7 +103,7 @@ export default {
searchedFiles() { searchedFiles() {
return this.files.filter(file => path.basename(file.media).toLowerCase().includes(this.search.toLowerCase()) && file.thumbnail) return this.files.filter(file => path.basename(file.media).toLowerCase().includes(this.search.toLowerCase()) && file.thumbnail)
}, },
...mapState(['files', 'previewFile', 'uploads']) ...mapState(['files', 'preview', 'uploads'])
}, },
mounted() { mounted() {
this.setFiles([]) this.setFiles([])
...@@ -145,4 +145,7 @@ export default { ...@@ -145,4 +145,7 @@ export default {
min-width: 5em; min-width: 5em;
opacity: 80%; opacity: 80%;
} }
.dropdown-toggle {
filter: drop-shadow(0px 0px 2px #000000);
}
</style> </style>
\ No newline at end of file
...@@ -12,8 +12,14 @@ export default createStore({ ...@@ -12,8 +12,14 @@ export default createStore({
uploads: [], uploads: [],
project: null, project: null,
user: null, user: null,
previewFile: null, preview: {
latestClip: null, file: null,
clip: null,
start: 0.0,
end: 1.0,
position: 0.0
},
scrollToClip: null,
}, },
mutations: { mutations: {
...@@ -69,9 +75,15 @@ export default createStore({ ...@@ -69,9 +75,15 @@ export default createStore({
state.clips = clips state.clips = clips
if (!clips) { if (!clips) {
// clear latest clip if no clips // clear latest clip if no clips
state.latestClip = null state.scrollToClip = null
} }
}, },
setClip(state, clipObj) {
state.clips = [
...state.clips = state.clips.filter(clip => clip.id != clipObj.id),
clipObj
]
},
deleteClip(state, clip_id) { deleteClip(state, clip_id) {
state.clips = state.clips.filter(clip => clip.id != clip_id) state.clips = state.clips.filter(clip => clip.id != clip_id)
}, },
...@@ -82,12 +94,27 @@ export default createStore({ ...@@ -82,12 +94,27 @@ export default createStore({
payload.obj payload.obj
] ]
if (payload.latest) { if (payload.latest) {
state.latestClip = payload.obj state.scrollToClip = payload.obj
} }
} }
}, },
setPreview(state, payload) {
state.preview.start = payload.start
state.preview.end = payload.end
},
setPreviewPosition(state, position) {
state.preview.position = position
},
setPreviewFile(state, file) { setPreviewFile(state, file) {
state.previewFile = file state.preview.file = file
state.preview.start = 0.0
state.preview.end = 1.0
},
setPreviewClip(state, clipObj) {
state.preview.clip = clipObj
state.preview.start = clipObj.start
state.preview.end = clipObj.end
state.preview.position = clipObj.start
}, },
addUpload(state, upload) { addUpload(state, upload) {
state.uploads.push(upload) state.uploads.push(upload)
...@@ -203,6 +230,21 @@ export default createStore({ ...@@ -203,6 +230,21 @@ export default createStore({
commit('addError', err.response.data) commit('addError', err.response.data)
} }
}, },
async editClip({dispatch, commit}, payload) {
try {
const response = await instance.post(`${payload.project_url}clips/`, payload.data)
let clipObj = response.data
const file_response = await instance.get(clipObj.file)
clipObj.fileObj = file_response.data
commit('addClip', clipObj)
let fps = clipObj.json.reader.fps.num / clipObj.json.reader.fps.den
let thumbnail_payload = { obj: clipObj, frame: clipObj.start * fps, latest: true }
dispatch('attachThumbnail', thumbnail_payload)
} catch(err) {
commit('addError', err.response.data)
}
},
async deleteClip({commit}, clip_id) { async deleteClip({commit}, clip_id) {
try { try {
await instance.delete(`clips/${clip_id}/`) await instance.delete(`clips/${clip_id}/`)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment