source: main/trunk/model-interfaces-dev/atea/macron-restoration/src/components/FileUpload.vue@ 35726

Last change on this file since 35726 was 35726, checked in by cstephen, 2 years ago

Allow PowerPoint files to be submitted

File size: 5.8 KB
Line 
1<template>
2 <div class="audio-file-picker">
3 <div class="input-bar">
4 <div class="text-input-sl" style="cursor: pointer;" @click="openFilePicker">
5 <span class="text-placeholder material-icons" v-if="!anyFiles">attach_file</span>
6 <span class="text-placeholder" v-if="!anyFiles">{{ translations.get("FileUpload_SelectFiles") }}</span>
7 <span v-if="anyFiles">{{ getFileNameList }}</span>
8 </div>
9
10 <input ref="fileInput" type="file" @input="onFilesChanged"
11 accept="application/vnd.openxmlformats-officedocument.wordprocessingml.document,application/vnd.oasis.opendocument.text,text/plain,application/vnd.openxmlformats-officedocument.presentationml.presentation"
12 multiple :disabled="isMacronising" />
13
14 <button class="btn-primary" type="submit" :disabled="!anyFiles || isMacronising" @click="doMacronisation">
15 <span class="material-icons">history_edu</span>
16 <span>{{ translations.get("FileUpload_MacroniseFiles") }}</span>
17 </button>
18 </div>
19
20 <div v-if="isMacronising" class="progress-bar-container">
21 <div class="progress-bar-value progress-bar-indeterminate" />
22 </div>
23
24 <ul class="list-view" v-if="failures.size > 0">
25 <li v-for="[id, failure] in failures" :key="failure.id" class="list-view__item transcription-error-container">
26 <div>
27 {{ translations.get("FileUpload_MacronisationFailed-Message") }} <i v-if="failure.fileName">{{ failure.fileName }}</i><br />
28 <span v-if="failure.message">{{ translations.get("FileUpload_MacronisationFailed-Reason") }}: {{ failure.message }}</span>
29 </div>
30
31 <button class="btn-fab theme-flat" @click="dismissFailure(id)">
32 <span class="material-icons">clear</span>
33 </button>
34 </li>
35 </ul>
36 </div>
37</template>
38
39<style scoped lang="scss">
40.audio-file-picker {
41 display: flex;
42 gap: 0.5em;
43 flex-direction: column;
44
45 input {
46 display: none;
47 }
48
49 .text-container {
50 cursor: pointer;
51 }
52}
53
54.input-bar {
55 display: grid;
56 align-items: stretch;
57 gap: 0.5em;
58 grid-template-columns: 1fr auto;
59}
60
61.transcription-error-container {
62 display: grid;
63 gap: 0.5em;
64 grid-template-columns: 1fr auto;
65 align-items: center;
66
67 border-left: 3px solid red;
68}
69</style>
70
71<script>
72import { mapState } from "vuex";
73import MacronRestorationService from "../js/MacronRestorationModule";
74import Util, { log } from "../js/Util";
75
76class MacronisationViewFailure {
77 /**
78 * @param {String} fileName The name of the file for which this failure occured.
79 * @param {String} message The reason for this failure.
80 */
81 constructor(fileName, message) {
82 /** @type {String} The UUID of this failure. */
83 this.id = Util.generateUuid();
84
85 /** @type {String | null} The name of the file for which this failure occured. */
86 this.fileName = fileName;
87
88 /** @type {String} The reason for the failure. */
89 this.message = message;
90 }
91}
92
93const macronService = new MacronRestorationService();
94
95export default {
96 name: "FileUpload",
97 data() {
98 return {
99 /** @type {File[]} */
100 files: [],
101 preserveExistingMacrons: true,
102 /** @type {Map<String, MacronisationViewFailure>} */
103 failures: new Map(),
104 isMacronising: false
105 }
106 },
107 computed: mapState({
108 translations: state => state.translations,
109 anyFiles() {
110 return this.files?.length > 0;
111 },
112 getFileNameList() {
113 let fileNameList = "";
114
115 for (const file of this.files) {
116 fileNameList += file.name + ", ";
117 }
118
119 return fileNameList.slice(0, fileNameList.length - 2);
120 }
121 }),
122 emits: [ "fileMacronised" ],
123 methods: {
124 openFilePicker() {
125 this.$refs.fileInput.click();
126 },
127 onFilesChanged() {
128 this.files = [];
129 const files = this.$refs.fileInput.files;
130
131 if (files?.length !== undefined && files?.length > 0) {
132 for (const file of files) {
133 this.files.push(file);
134 }
135 }
136 },
137
138 async doMacronisation() {
139 await this.macronise(this.files);
140 },
141 /**
142 * Attempts to macronise each submitted file.
143 * @param {File[]} files The files to macronise.
144 */
145 async macronise(files) {
146 this.isMacronising = true;
147
148 for (const file of files) {
149 try {
150 const fileInfo = await macronService.fileMacronisation(file, this.preserveExistingMacrons);
151 this.$store.commit("pushFileInfo", fileInfo);
152 }
153 catch (ex) {
154 log("Failed to macronise file", "error");
155 log(ex);
156
157 this.createFailure(ex.fileName, ex.message);
158 }
159 }
160
161 this.isMacronising = false;
162 this.files = [];
163 },
164
165 /**
166 * Creates a new UI entry indicating that a file failed to be macronised.
167 * @param {String} fileName The name of the file that couldn't be macronised.
168 * @param {String} reason The reason that the file couldn't be macronised.
169 */
170 createFailure(fileName, reason) {
171 const failure = new MacronisationViewFailure(fileName, reason);
172 this.failures.set(failure.id, failure);
173 },
174 /**
175 * Dismisses a failure
176 * @param {String} id The UUID of the failure.
177 */
178 dismissFailure(id) {
179 this.failures.delete(id);
180 }
181 }
182}
183</script>
Note: See TracBrowser for help on using the repository browser.