source: main/trunk/model-interfaces-dev/atea/ocr/src/components/DirectInput.vue@ 35734

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

Add OCR interface

File size: 5.8 KB
Line 
1<template>
2<div class="root">
3 <textarea class="text-input input-area" @input="onTextInput"
4 v-model="input" :placeholder="translations.get('DirectInput_InputPlaceholder')" />
5
6 <div class="text-container">
7 <span v-if="errorState" class="material-icons mdi-m error-text">error</span>
8 <span v-if="errorState" class="error-text">Something went wrong! Please try modifying your input text.</span>
9
10 <span class="preserveWhitespace" v-html="formattedRestored" />
11 </div>
12
13 <div class="flex">
14 <input type="checkbox" id="i-preserve-existing-macrons" v-model="preserveExistingMacrons" @input="startMacronisationWait" />
15 <label for="i-preserve-existing-macrons">{{ translations.get('DirectInput_PreserveExistingMacrons') }}</label>
16 </div>
17
18 <div class="flex">
19 <input type="checkbox" id="i-show-macronised-words" v-model="showMacronisedWords" :disabled="restored.length === 0" />
20 <label for="i-show-macronised-words">{{ translations.get('DirectInput_ShowMacronisedWords') }}</label>
21 </div>
22
23 <div class="flex right-column">
24 <input type="checkbox" id="i-show-macronised-words" v-model="normaliseLinebreaks" :disabled="restored.length === 0" />
25 <label for="i-show-macronised-words">{{ translations.get('DirectInput_NormaliseLinebreaks') }}</label>
26 </div>
27
28 <button class="btn-primary right-column" :disabled="!canDownload" @click="downloadAsText">
29 {{ translations.get('DirectInput_Download') }}
30 </button>
31</div>
32</template>
33
34<style scoped lang="scss">
35.root {
36 display: grid;
37 grid-template-columns: 1fr 1fr;
38 gap: 1em;
39}
40
41.preserveWhitespace {
42 white-space: pre-line;
43}
44
45.input-area {
46 resize: vertical;
47 min-height: 4em;
48}
49
50.flex {
51 display: flex;
52 align-items: center;
53 gap: 0.5em;
54}
55
56.right-column {
57 grid-column: 2;
58}
59
60.highlight {
61 background-color: var(--highlighted-word-bg);
62}
63
64.error-text {
65 color: rgb(185, 3, 3);
66}
67</style>
68
69<script>
70import { mapState } from "vuex";
71import { saveAs } from "file-saver"
72import { log } from "../js/Util"
73import MacronRestorationModule from "../js/OcrService"
74
75const macroniser = new MacronRestorationModule();
76
77export default {
78 name: "DirectInput",
79 data() {
80 return {
81 preserveExistingMacrons: true,
82 showMacronisedWords: false,
83 macroniseWaitTimeout: null,
84 waitingToMacronise: false,
85 errorState: false,
86 normaliseLinebreaks: false
87 }
88 },
89 computed: {
90 canDownload() {
91 return this.restored.length > 0 && !this.waitingToMacronise;
92 },
93 input: {
94 get() {
95 return this.$store.state.directInput;
96 },
97 set(newValue) {
98 this.$store.commit("setDirectInput", newValue);
99 this.startMacronisationWait();
100 }
101 },
102 restored: {
103 get() {
104 return this.$store.state.directOutput;
105 },
106 set(newValue) {
107 this.$store.commit("setDirectOutput", newValue);
108 }
109 },
110 formattedRestored() {
111 let restored = "";
112
113 for (const word of this.restored) {
114 if (word.w) {
115 if (word[0] !== "-") {
116 restored += " ";
117 }
118
119 if (word.macronised && this.showMacronisedWords) {
120 restored += `<mark class="highlight">${word.w}</mark>`;
121 }
122 else {
123 restored += word.w;
124 }
125 }
126
127 if (word.linebreak) {
128 restored += this.normaliseLinebreak(word.linebreak);
129 }
130 }
131
132 return restored;
133 },
134 ...mapState({
135 translations: state => state.translations
136 })
137 },
138 methods: {
139 /**
140 * Handles input on an element, and grows its height so that the text is always visible.
141 * @param {InputEvent} event The input event.
142 */
143 onTextInput(event) {
144 event.target.height = "auto";
145 event.target.height = event.target.scrollHeight;
146 },
147 startMacronisationWait() {
148 if (this.input === null || this.input === "") {
149 return;
150 }
151
152 this.waitingToMacronise = true;
153
154 if (this.macroniseWaitTimeout !== null) {
155 clearTimeout(this.macroniseWaitTimeout);
156 }
157
158 this.macroniseWaitTimeout = setTimeout(this.updateMacronisedText, 1000);
159 },
160 async updateMacronisedText() {
161 this.errorState = false;
162
163 try {
164 this.restored = await macroniser.directMacronisation(this.input, this.preserveExistingMacrons);
165 this.waitingToMacronise = false;
166 }
167 catch (ex) {
168 this.errorState = true;
169 log(ex, "warn");
170 }
171 },
172 downloadAsText() {
173 const blob = new Blob([ this.restored ], { type: "text/plain;charset=utf-8" });
174 saveAs(blob, "restored.txt");
175 },
176 /**
177 * Normalises a linebreak.
178 * @param {String} linebreak The linebreak sequence.
179 */
180 normaliseLinebreak(linebreak) {
181 if (!this.normaliseLinebreaks) {
182 return linebreak;
183 }
184
185 const rCount = linebreak.split("\r").length - 1;
186 const nCount = linebreak.split("\n").length - 1;
187
188 if (rCount > 1) {
189 if (nCount > 0) {
190 return "\r\n\r\n";
191 }
192
193 return "\r\r";
194 }
195 else if (nCount > 1) {
196 return "\n\n";
197 }
198
199 return linebreak;
200 }
201 }
202}
203</script>
Note: See TracBrowser for help on using the repository browser.