Changeset 35723 for main/trunk/model-interfaces-dev/atea/macron-restoration/src/components/FileInput.vue
- Timestamp:
- 2021-11-08T15:51:51+13:00 (2 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
main/trunk/model-interfaces-dev/atea/macron-restoration/src/components/FileInput.vue
r35716 r35723 1 1 <template> 2 <div class="card"> 3 <!-- Header containing info and actions for the transcription --> 4 <div class="transcription__header"> 5 <button class="btn-fab" v-on:click="toggleAudio" type="button" :title="translations.get('TranscriptionItem_PlayButtonTooltip')"> 6 <span class="material-icons mdi-l play-button" v-if="!isPlaying">play_arrow</span> 7 <span class="material-icons mdi-l play-button" v-if="isPlaying">pause</span> 8 </button> 2 <file-upload /> 9 3 10 <span>{{ translations.get("TranscriptionItem_FileName") }}: {{ transcription.fileName }}</span> 4 <div class="file-info-list"> 5 <div v-for="(fileInfo, index) in fileInfos" :key="fileInfo.id"> 6 <div class="info-container"> 7 <span class="material-icons mdi-override" v-if="fileInfo.fileType === '.txt'">description</span> 8 <img class="icon-l" src="resources/word_icon.ico" v-if="fileInfo.fileType === '.docx'" /> 11 9 12 <div style="position: relative;"> 13 <button class="btn-primary" @mouseover="showDownloadOptions = true" @mouseout="showDownloadOptions = false" type="button"> 14 <span class="material-icons">download</span> 15 <span>{{ translations.get("TranscriptionItem_Download") }}</span> 16 </button> 10 {{ fileInfo.fileName }} 17 11 18 <div class="download-popup card" :class="{ 'download-popup-show': showDownloadOptions }" 19 @mouseover="showDownloadOptions = true" @mouseout="showDownloadOptions = false"> 20 <button @click="downloadAsText" type="button" class="btn-primary theme-flat"> 21 <span class="material-icons">text_snippet</span> 22 <span>{{ translations.get("TranscriptionItem_DownloadAsText") }}</span> 23 </button> 24 25 <button @click="downloadAsJson" type="button" class="btn-primary theme-flat"> 26 <span class="material-icons">integration_instructions</span> 27 <span>{{ translations.get("TranscriptionItem_DownloadAsJson") }}</span> 28 </button> 29 30 <button @click="downloadAsWebvtt" type="button" class="btn-primary theme-flat"> 31 <span class="material-icons">subtitles</span> 32 <span>{{ translations.get("TranscriptionItem_DownloadAsWebvtt") }}</span> 33 </button> 34 </div> 35 </div> 36 37 <button class="btn-primary theme-error" @click="remove" type="button"> 38 <span class="material-icons">delete</span> 39 <span>{{ translations.get("TranscriptionItem_Remove") }}</span> 12 <button @click="download(fileInfo)" type="button" class="btn-primary theme-flat"> 13 <span class="material-icons">download</span> 14 <span>{{ translations.get("FileInput_Download") }}</span> 40 15 </button> 41 16 </div> 42 17 43 < div class="editor-controls">44 <audio-time-bar v-model.number="currentPlaybackTime" :audio-length="audioLength" :isDisabled="playbackState.id != transcription.id" />45 18 <hr class="divider-s" v-if="index !== fileInfos.length - 1" /> 19 </div> 20 </div> 46 21 47 <hr /> 22 <form ref="formDownload" method="post" target="_blank"> 23 <input ref="inputFilePath" type="hidden" name="filepath" /> 24 <input ref="inputFileName" type="hidden" name="filename" /> 25 </form> 48 26 49 <div class="editor-controls">50 <TranscriptionItemEditor ref="editor" :transcription="transcription" style="margin-bottom: 1em" :enableEditing="enableEditing" />51 <toggle-button v-model="enableEditing" :title="translations.get('TranscriptionItemEditor_ToggleEditTooltip')">52 <span class="material-icons">edit</span>53 </toggle-button>54 </div>55 </div>56 27 </template> 57 28 58 29 <style scoped lang="scss"> 59 . transcription__header {30 .info-container { 60 31 display: grid; 61 gap: 0.5em 0.5em; 62 grid-template-columns: auto 1fr auto auto; 32 grid-template-columns: auto 1fr auto; 63 33 align-items: center; 34 35 gap: 0.5em; 36 padding: 0.5em; 37 transition-duration: var(--transition-duration); 38 39 &:hover { 40 background-color: #DDD; 41 } 64 42 } 65 43 66 .download-popup { 67 display: flex; 68 flex-direction: column; 69 align-items: stretch; 70 71 position: absolute; 72 top: 97%; 73 z-index: 2; 74 75 padding: 2px; 76 margin: 0; 77 width: 14em; 78 79 transition-duration: var(--transition-duration); 80 visibility: hidden; 81 opacity: 0; 44 .file-info-list { 45 border: 1px solid #BBB; 46 margin-top: 1em; 82 47 } 83 48 84 .download-popup-show { 85 visibility: visible; 86 opacity: 1; 49 .mdi-override { 50 @extend .mdi-l; 51 52 color: var(--bg-color); 87 53 } 88 54 89 .editor-controls { 90 display: grid; 91 align-items: flex-start; 92 grid-template-columns: 1fr auto; 93 margin: 0.5em 0 0.3em 0; 94 gap: 1em; 95 } 96 97 .rotate-180 { 98 transform: rotate(180deg); 55 .icon-l { 56 height: 36px; 99 57 } 100 58 </style> … … 102 60 <script> 103 61 import { mapState } from "vuex"; 104 import { saveAs } from "file-saver" 105 import { TranscriptionViewModel } from "../main"; 106 import AudioPlayback from "../js/AudioPlaybackModule" 107 import Util from "../js/Util" 108 import AudioTimeBar from "./AudioTimeBar.vue" 109 import TranscriptionItemEditor from "./TranscriptionItemEditor.vue" 62 import MacronRestorationService from "../js/MacronRestorationModule" 63 import FileUpload from "./FileUpload.vue" 64 65 const macronRestorer = new MacronRestorationService(); 110 66 111 67 export default { 112 name: " TranscriptionItem",68 name: "FileInput", 113 69 components: { 114 AudioTimeBar, 115 TranscriptionItemEditor 116 }, 117 props: { 118 transcription: TranscriptionViewModel 119 }, 120 data() { 121 return { 122 enableEditing: false, 123 showDownloadOptions: false 124 } 70 FileUpload 125 71 }, 126 72 computed: { 127 currentPlaybackTime: {128 get() {129 return this.$store.getters.transcriptionPlaybackTime(this.transcription.id);130 },131 set(value) {132 this.$store.commit("playbackStateSetTime", { id: this.transcription.id, time: value });133 }134 },135 audioLength() {136 return this.$store.getters.transcriptionPlaybackLength(this.transcription.id);137 },138 isPlaying() {139 return this.playbackState.isPlaying && this.playbackState.id === this.transcription.id;140 },141 73 ...mapState({ 142 74 translations: state => state.translations, 143 playbackState: state => state.playbackState75 fileInfos: state => state.macronisedFileInfos 144 76 }) 145 77 }, 146 78 methods: { 147 async toggleAudio() { 148 this.isPlaying ? AudioPlayback.pause() : await AudioPlayback.play(this.transcription.id, -1); 149 }, 150 remove() { 151 this.$store.commit("rawTranscriptionRemove", this.transcription.id); 152 }, 153 downloadAsText() { 154 const fileName = buildDownloadableFileName(this.transcription.fileName, "txt"); 155 156 const blob = new Blob([ this.$refs.editor.words.map(w => w.word).join(" ") ], { type: "text/plain;charset=utf-8" }); 157 saveAs(blob, fileName); 158 }, 159 downloadAsJson() { 160 const fileName = buildDownloadableFileName(this.transcription.fileName, "json"); 161 const toDownload = (({ fileName, transcription }) => ({ fileName, transcription }))(this.transcription); 162 toDownload.words = this.$refs.editor.words.map(w => (({ word, startTime, endTime }) => ({ word, startTime, endTime }))(w)); 163 164 const blob = new Blob([ JSON.stringify(toDownload, null, 4) ], { type: "application/json;charset=utf-8" }); 165 saveAs(blob, fileName); 166 }, 167 downloadAsWebvtt() { 168 const fileName = buildDownloadableFileName(this.transcription.fileName, "vtt"); 169 const toDownload = buildWebvttFileContents(this.transcription, this.$refs.editor); 170 171 const blob = new Blob([ toDownload ], { type: "text/vtt;charset=utf-8" }); 172 saveAs(blob, fileName); 79 download(fileInfo) { 80 this.$refs.inputFilePath.value = fileInfo.filePath; 81 this.$refs.inputFileName.value = fileInfo.fileName; 82 this.$refs.formDownload.submit(); 173 83 } 84 }, 85 mounted() { 86 this.$refs.formDownload.setAttribute("action", macronRestorer.queryUrl + "Download"); 174 87 } 175 88 } 176 177 /**178 * Builds a file name for a download.179 * @param {String} transcriptionFileName The name of the transcription that will be downloaded.180 * @param {String} extension The file extension of the download. Do not include a period.181 * @returns {String} The file name.182 */183 function buildDownloadableFileName(transcriptionFileName, extension) {184 const extensionIndex = transcriptionFileName.lastIndexOf(".");185 let fileName = transcriptionFileName.slice(0, extensionIndex);186 fileName += "_transcription." + extension;187 188 return fileName;189 }190 191 /**192 * Builds a WebVTT file of the given transcription193 * @param {TranscriptionViewModel} transcription The transcription.194 * @returns {String} The WebVTT content.195 */196 function buildWebvttFileContents(transcription, editor) {197 let contents = "WEBVTT Transcription of " + transcription.fileName + "\n\n";198 199 for (const word of editor.words) {200 const startTime = Util.formatSecondsTimeString(word.startTime, true);201 const endTime = Util.formatSecondsTimeString(word.endTime, true);202 203 contents += startTime + " --> " + endTime + "\n";204 contents += "- " + word.word + "\n\n";205 }206 207 return contents;208 }209 89 </script>
Note:
See TracChangeset
for help on using the changeset viewer.