Changeset 35785


Ignore:
Timestamp:
2021-12-09T16:18:13+13:00 (2 years ago)
Author:
cstephen
Message:

Add snackbar warning when the OCR process takes longer than 10s

Location:
main/trunk/model-interfaces-dev/atea/ocr/src
Files:
1 added
2 edited

Legend:

Unmodified
Added
Removed
  • main/trunk/model-interfaces-dev/atea/ocr/src/App.vue

    r35762 r35785  
     1<script>
     2import { mapState } from "vuex";
     3import MainPage from "./components/MainPage.vue"
     4import ModalDialog, { ModalController } from "./components/ModalDialog.vue"
     5import Snackbar, { SnackController } from "./components/Snackbar.vue"
     6
     7export default {
     8    name: "App",
     9    components: {
     10        MainPage,
     11        ModalDialog,
     12        Snackbar
     13    },
     14    computed: {
     15        ...mapState({
     16            translations: state => state.translations
     17        })
     18    },
     19    mounted() {
     20        ModalController.setModal(this.$refs.modalDialog);
     21        SnackController.setBar(this.$refs.snackBar);
     22    }
     23}
     24</script>
     25
    126<template>
    227<div class="root">
    3     <!-- <div class="app-bar theme-primary">
    4         <div class="app-bar-content">
    5             <span class="heading1">{{ translations.get("Title") }}</span>
    6         </div>
    7     </div> -->
    8 
    928    <main-page class="content" />
    1029</div>
    1130
     31<snackbar ref="snackBar" />
    1232<modal-dialog ref="modalDialog" />
    1333</template>
     
    2545}
    2646
    27 .app-bar {
    28     display: flex;
    29     flex-direction: column;
    30     gap: 1em;
    31 
    32     background-color: var(--bg-color);
    33     color: var(--fg-color);
    34     box-shadow: 0px 0px 4px 3px #6d6d6d;
    35 
    36     padding: 1em;
    37     margin-bottom: 1em;
    38 }
    39 
    40 .app-bar-content {
    41     display: flex;
    42     align-items: center;
    43     gap: 1em;
    44 
    45     width: 100%;
    46 
    47     & :first-child {
    48         flex-grow: 1;
    49     }
    50 }
    51 
    5247.content {
    5348    padding: 1em;
     
    5550}
    5651</style>
    57 
    58 <script>
    59 import { mapState } from "vuex";
    60 import MainPage from "./components/MainPage.vue"
    61 import ModalDialog, { ModalController } from "./components/ModalDialog.vue"
    62 
    63 export default {
    64     name: "App",
    65     components: {
    66         MainPage,
    67         ModalDialog
    68     },
    69     computed: {
    70         ...mapState({
    71             translations: state => state.translations
    72         })
    73     },
    74     mounted() {
    75         ModalController.setModal(this.$refs.modalDialog);
    76     }
    77 }
    78 </script>
  • main/trunk/model-interfaces-dev/atea/ocr/src/components/MainPage.vue

    r35775 r35785  
    1 <template>
    2 <div class="main-page-root">
    3     <edit-page v-if="showEditor" class="image-editor" :src="imageUrl" :imageBuffer="imageBuffer"
    4         @closeAndDiscard="onEditorCloseRequested" @closeAndSave="onEditorSave" />
    5 
    6     <div class="paper root-container" :class="{ 'root-container-image-state': imageUrl !== null }">
    7         <div v-if="imageUrl === null" class="upload-area" @click="uploadFile">
    8             <span class="heading1">{{ translations.get("Title") }}</span>
    9             <span class="material-icons mdi-xl">upload_file</span>
    10             <span>{{ translations.get("MainPage_Upload") }}</span>
    11         </div>
    12 
    13         <div v-if="imageUrl !== null" class="main-area">
    14             <div class="controls">
    15                 <button class="btn-primary" @click="showEditor = true" :disabled="ocrInProgress">
    16                     <span class="material-icons">edit</span>
    17                     <span>{{ translations.get("MainPage_EditImage") }}</span>
    18                 </button>
    19 
    20                 <button class="btn-primary" @click="doOcr" :disabled="ocrInProgress">
    21                     <span class="material-icons">play_arrow</span>
    22                     <span>{{ translations.get("MainPage_PerformOCR") }}</span>
    23                 </button>
    24 
    25                 <button class="btn-primary" @click="download" :disabled="!isValidOcrResult">
    26                     <span class="material-icons">download</span>
    27                     <span>{{ translations.get("MainPage_Download") }}</span>
    28                 </button>
    29 
    30                 <button class="btn-primary" @click="reset(false)" :disabled="ocrInProgress">
    31                     <span class="material-icons">restart_alt</span>
    32                     <span>{{ translations.get("MainPage_NewImage") }}</span>
    33                 </button>
    34             </div>
    35 
    36             <div class="progress-bar-container ocr-progress">
    37                 <div v-if="ocrInProgress" class="progress-bar-value progress-bar-indeterminate" />
    38             </div>
    39 
    40             <ocr-image-display :imageUrl="imageUrl" :thresholdedImageUrl="thresholdedImageUrl" />
    41 
    42             <textarea class="text-container" v-model="ocrResult" :placeholder="translations.get('MainPage_OCRHint')"
    43                 @input="ocrTextEdited = true" :disabled="!isValidOcrResult || ocrInProgress" />
    44         </div>
    45     </div>
    46 
    47     <input ref="fileInput" type="file" @input="onFilesChanged" class="hidden"
    48         accept="image/png,image/jpeg,image/gif,image/bmp,image/tiff,image/webp,application/pdf" />
    49 </div>
    50 
    51 </template>
    52 
    53 <style lang="scss" scoped>
    54 .main-page-root {
    55     display: flex;
    56     align-items: center;
    57     justify-content: center;
    58 }
    59 
    60 .root-container {
    61     padding: 1em;
    62     transition-duration: var(--transition-duration);
    63 }
    64 
    65 .root-container-image-state {
    66     width: calc(100% - 3em);
    67     height: calc(100vh - 3em);
    68     max-height: calc(100vh - 3em);
    69 }
    70 
    71 .upload-area {
    72     display: grid;
    73     grid-template-columns: auto auto;
    74     grid-template-rows: auto 1fr;
    75     align-items: center;
    76     justify-items: center;
    77 
    78     padding: 2em;
    79     gap: 1em;
    80 
    81     font-size: 2rem;
    82     cursor: pointer;
    83     border: 3px dashed var(--bg-color);
    84     border-radius: var(--border-radius);
    85 
    86     .heading1 {
    87         grid-column-start: span 2;
    88         color: #666;
    89     }
    90 }
    91 
    92 .hidden {
    93     display: none;
    94 }
    95 
    96 .image-editor {
    97     position: absolute;
    98     height: 100%;
    99     width: 100%;
    100     top: 0;
    101     left: 0;
    102     z-index: 9;
    103 }
    104 
    105 .main-area {
    106     display: grid;
    107     grid-template-columns: 1fr 1fr;
    108     grid-template-rows: auto auto 1fr;
    109     height: 100%;
    110 
    111     gap: 1rem;
    112     align-items: center;
    113     justify-items: center;
    114 
    115     position: relative;
    116     overflow: hidden;
    117 
    118     .text-container {
    119         height: 100%;
    120         width: 100%;
    121     }
    122 }
    123 
    124 .controls {
    125     display: flex;
    126     gap: 1em;
    127     grid-column-start: span 2;
    128 }
    129 
    130 .ocr-progress {
    131     grid-column-start: span 2;
    132 }
    133 </style>
    134 
    1351<script>
    1362import { mapState } from "vuex";
     
    1384import OcrImageDisplay from "./OcrImageDisplay.vue"
    1395import { ModalController } from "./ModalDialog.vue"
     6import { SnackController } from "./Snackbar.vue"
    1407import OcrService, { OcrOptions } from "../js/OcrService"
    1418import { log } from "../js/Util";
     
    21380
    21481                this.ocrInProgress = true;
     82                const longTimeout = setTimeout(function() {
     83                    SnackController.addSnack("This is taking longer than expected! Please, sit tight.", 8000);
     84                }, 10000);
    21585
    21686                const arrayView = new Uint8Array(this.imageBuffer);
     
    22595                ]);
    22696
     97                clearTimeout(longTimeout);
    22798                this.ocrResult = result[0].text;
    22899                this.ocrTextEdited = false;
     
    328199}
    329200</script>
     201
     202<template>
     203<div class="main-page-root">
     204    <edit-page v-if="showEditor" class="image-editor" :src="imageUrl" :imageBuffer="imageBuffer"
     205        @closeAndDiscard="onEditorCloseRequested" @closeAndSave="onEditorSave" />
     206
     207    <div class="paper root-container" :class="{ 'root-container-image-state': imageUrl !== null }">
     208        <div v-if="imageUrl === null" class="upload-area" @click="uploadFile">
     209            <span class="heading1">{{ translations.get("Title") }}</span>
     210            <span class="material-icons mdi-xl">upload_file</span>
     211            <span>{{ translations.get("MainPage_Upload") }}</span>
     212        </div>
     213
     214        <div v-if="imageUrl !== null" class="main-area">
     215            <div class="controls">
     216                <button class="btn-primary" @click="showEditor = true" :disabled="ocrInProgress">
     217                    <span class="material-icons">edit</span>
     218                    <span>{{ translations.get("MainPage_EditImage") }}</span>
     219                </button>
     220
     221                <button class="btn-primary" @click="doOcr" :disabled="ocrInProgress">
     222                    <span class="material-icons">play_arrow</span>
     223                    <span>{{ translations.get("MainPage_PerformOCR") }}</span>
     224                </button>
     225
     226                <button class="btn-primary" @click="download" :disabled="!isValidOcrResult">
     227                    <span class="material-icons">download</span>
     228                    <span>{{ translations.get("MainPage_Download") }}</span>
     229                </button>
     230
     231                <button class="btn-primary" @click="reset(false)" :disabled="ocrInProgress">
     232                    <span class="material-icons">restart_alt</span>
     233                    <span>{{ translations.get("MainPage_NewImage") }}</span>
     234                </button>
     235            </div>
     236
     237            <div class="progress-bar-container ocr-progress">
     238                <div v-if="ocrInProgress" class="progress-bar-value progress-bar-indeterminate" />
     239            </div>
     240
     241            <ocr-image-display :imageUrl="imageUrl" :thresholdedImageUrl="thresholdedImageUrl" />
     242
     243            <textarea class="text-container" v-model="ocrResult" :placeholder="translations.get('MainPage_OCRHint')"
     244                @input="ocrTextEdited = true" :disabled="!isValidOcrResult || ocrInProgress" />
     245        </div>
     246    </div>
     247
     248    <input ref="fileInput" type="file" @input="onFilesChanged" class="hidden"
     249        accept="image/png,image/jpeg,image/gif,image/bmp,image/tiff,image/webp,application/pdf" />
     250</div>
     251
     252</template>
     253
     254<style lang="scss" scoped>
     255.main-page-root {
     256    display: flex;
     257    align-items: center;
     258    justify-content: center;
     259}
     260
     261.root-container {
     262    padding: 1em;
     263    transition-duration: var(--transition-duration);
     264}
     265
     266.root-container-image-state {
     267    width: calc(100% - 3em);
     268    height: calc(100vh - 3em);
     269    max-height: calc(100vh - 3em);
     270}
     271
     272.upload-area {
     273    display: grid;
     274    grid-template-columns: auto auto;
     275    grid-template-rows: auto 1fr;
     276    align-items: center;
     277    justify-items: center;
     278
     279    padding: 2em;
     280    gap: 1em;
     281
     282    font-size: 2rem;
     283    cursor: pointer;
     284    border: 3px dashed var(--bg-color);
     285    border-radius: var(--border-radius);
     286
     287    .heading1 {
     288        grid-column-start: span 2;
     289        color: #666;
     290    }
     291}
     292
     293.hidden {
     294    display: none;
     295}
     296
     297.image-editor {
     298    position: absolute;
     299    height: 100%;
     300    width: 100%;
     301    top: 0;
     302    left: 0;
     303    z-index: 9;
     304}
     305
     306.main-area {
     307    display: grid;
     308    grid-template-columns: 1fr 1fr;
     309    grid-template-rows: auto auto 1fr;
     310    height: 100%;
     311
     312    gap: 1rem;
     313    align-items: center;
     314    justify-items: center;
     315
     316    position: relative;
     317    overflow: hidden;
     318
     319    .text-container {
     320        height: 100%;
     321        width: 100%;
     322    }
     323}
     324
     325.controls {
     326    display: flex;
     327    gap: 1em;
     328    grid-column-start: span 2;
     329}
     330
     331.ocr-progress {
     332    grid-column-start: span 2;
     333}
     334</style>
Note: See TracChangeset for help on using the changeset viewer.