Ignore:
Timestamp:
2021-11-30T14:06:55+13:00 (2 years ago)
Author:
cstephen
Message:

Improve modal dialogs

Location:
main/trunk/model-interfaces-dev/atea
Files:
5 edited

Legend:

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

    r35743 r35762  
    99    <main-page class="content" />
    1010</div>
     11
     12<modal-dialog ref="modalDialog" />
    1113</template>
    1214
     
    5759import { mapState } from "vuex";
    5860import MainPage from "./components/MainPage.vue"
     61import ModalDialog, { ModalController } from "./components/ModalDialog.vue"
    5962
    6063export default {
    6164    name: "App",
    6265    components: {
    63         MainPage
     66        MainPage,
     67        ModalDialog
    6468    },
    6569    computed: {
     
    6771            translations: state => state.translations
    6872        })
     73    },
     74    mounted() {
     75        ModalController.setModal(this.$refs.modalDialog);
    6976    }
    7077}
  • main/trunk/model-interfaces-dev/atea/ocr/src/components/EditPage.vue

    r35751 r35762  
    22<div class="edit-page-root">
    33    <div class="control-panel">
    4         <edit-action :description="translations.get('EditPage_Discard')" @action="$emit('closeAndDiscard')" icon="cancel" />
    5         <edit-action :description="translations.get('EditPage_InvertColour')" @action="invert = !invert" icon="invert_colors" />
     4        <edit-action :description="translations.get('EditPage_Discard')" @action="closeAndDiscard" icon="cancel" />
     5        <edit-action :description="translations.get('EditPage_InvertColour')" @action="invertColours" icon="invert_colors" />
    66        <edit-action :description="translations.get('EditPage_Rotate')" v-model="rotateMode" icon="crop_rotate" toggleMode />
    77        <edit-action :description="translations.get('EditPage_Save')" @action="closeAndSave" icon="save" />
     
    165165import { mapState } from "vuex";
    166166import EditAction from "./EditAction.vue"
     167import { ModalController } from "./ModalDialog.vue"
    167168
    168169export default {
     
    181182            rotation: 0,
    182183            rotateMode: false,
    183             allowRotation: false
     184            allowRotation: false,
     185            edited: false
    184186        }
    185187    },
     
    205207    },
    206208    methods: {
     209        closeAndDiscard(force) {
     210            if (force || !this.edited) {
     211                this.$emit("closeAndDiscard");
     212                return;
     213            }
     214
     215            const that = this;
     216
     217            ModalController.open(
     218                this.translations.get("DiscardEditsModal_Title"),
     219                this.translations.get("DiscardEditsModal_Description"),
     220                [
     221                    this.translations.get("DiscardEditsModal_ButtonContinue"),
     222                    this.translations.get("DiscardEditsModal_ButtonCancel")
     223                ],
     224                async function(buttonName) {
     225                    if (buttonName === that.translations.get("DiscardEditsModal_ButtonContinue")) {
     226                        that.closeAndDiscard(true);
     227                    }
     228                }
     229            );
     230        },
    207231        async closeAndSave() {
    208232            const Jimp = await import("jimp/es");
     
    225249
    226250            this.$emit("closeAndSave", modifiedBuffer, Jimp.MIME_PNG);
     251        },
     252
     253        invertColours() {
     254            this.invert = !this.invert;
     255            this.edited = true;
    227256        },
    228257
     
    263292                this.rotation -= 360;
    264293            }
     294
     295            this.edited = true;
    265296        },
    266297        onDocumentMouseUp() {
  • main/trunk/model-interfaces-dev/atea/ocr/src/components/MainPage.vue

    r35759 r35762  
    11<template>
    22<div class="main-page-root">
    3     <modal-dialog v-if="modal.show" :title="modal.title" :description="modal.description" :buttons="modal.buttons" @close="onModalClose" />
    43    <edit-page v-if="showEditor" class="image-editor" :src="imageUrl" :imageBuffer="imageBuffer"
    54        @closeAndDiscard="onEditorCloseRequested" @closeAndSave="onEditorSave" />
     
    4241
    4342            <textarea class="text-container" v-model="ocrResult" :placeholder="translations.get('MainPage_OCRHint')"
    44                 @input="modalChecks.ocrTextEdited = true" :disabled="!isValidOcrResult" />
     43                @input="ocrTextEdited = true" :disabled="!isValidOcrResult || ocrInProgress" />
    4544        </div>
    4645    </div>
     
    144143import { mapState } from "vuex";
    145144import EditPage from "./EditPage.vue";
    146 import ModalDialog from "./ModalDialog.vue"
     145import { ModalController } from "./ModalDialog.vue"
    147146import OcrService, { OcrOptions } from "../js/OcrService"
    148147import { log } from "../js/Util";
     
    153152    name: "MainPage",
    154153    components: {
    155         EditPage,
    156         ModalDialog
     154        EditPage
    157155    },
    158156    data() {
     
    165163            ocrResult: null,
    166164            showEditor: false,
    167             modal: {
    168                 show: false,
    169                 title: "",
    170                 description: "",
    171                 buttons: []
    172             },
    173             modalChecks: {
    174                 ocrTextEdited: false,
    175                 pendingReset: false
    176             }
     165            ocrTextEdited: false
    177166        }
    178167    },
     
    216205
    217206        async doOcr() {
    218             if (this.modalChecks.ocrTextEdited) {
    219                 this.modal.title = this.translations.get("OCREditedModal_Title");
    220                 this.modal.description = this.translations.get("OCREditedModal_Description");
    221                 this.modal.buttons = [
    222                     this.translations.get("OCREditedModal_ButtonContinue"),
    223                     this.translations.get("OCREditedModal_ButtonCancel")
    224                 ];
    225                 this.modal.show = true;
    226 
    227                 return;
    228             }
    229 
    230207            try {
     208                if (this.ocrTextEdited) {
     209                    this.confirmOcr();
     210                    return;
     211                }
     212
    231213                this.ocrInProgress = true;
    232214
     
    243225
    244226                this.ocrResult = result[0].text;
    245                 this.modalChecks.ocrTextEdited = false;
     227                this.ocrTextEdited = false;
    246228            }
    247229            catch (ex) {
     
    253235                this.ocrInProgress = false;
    254236            }
     237        },
     238        confirmOcr() {
     239            const that = this;
     240
     241            ModalController.open(
     242                this.translations.get("OCREditedModal_Title"),
     243                this.translations.get("OCREditedModal_Description"),
     244                [
     245                    this.translations.get("OCREditedModal_ButtonContinue"),
     246                    this.translations.get("OCREditedModal_ButtonCancel")
     247                ],
     248                async function(buttonName) {
     249                    if (buttonName === that.translations.get("OCREditedModal_ButtonContinue")) {
     250                        that.ocrTextEdited = false;
     251                        await that.doOcr();
     252                    }
     253                }
     254            );
    255255        },
    256256
     
    272272        reset(hard) {
    273273            if (!hard) {
    274                 this.modalChecks.pendingReset = true;
    275 
    276                 this.modal.title = this.translations.get("NewImageModal_Title");
    277                 this.modal.description = this.translations.get("NewImageModal_Description");
    278                 this.modal.buttons = [
    279                     this.translations.get("NewImageModal_ButtonContinue"),
    280                     this.translations.get("NewImageModal_ButtonCancel")
    281                 ];
    282                 this.modal.show = true;
     274                const that = this;
     275
     276                ModalController.open(
     277                    this.translations.get("NewImageModal_Title"),
     278                    this.translations.get("NewImageModal_Description"),
     279                    [
     280                        this.translations.get("NewImageModal_ButtonContinue"),
     281                        this.translations.get("NewImageModal_ButtonCancel")
     282                    ],
     283                    function(buttonName) {
     284                        if (buttonName === that.translations.get("NewImageModal_ButtonContinue")) {
     285                            that.reset(true);
     286                        }
     287                    }
     288                );
    283289
    284290                return;
     
    290296            this.ocrResult = null;
    291297            this.showEditor = false;
     298            this.ocrTextEdited = false;
    292299            this.$refs.fileInput.value = "";
    293         },
    294 
    295         async onModalClose(button) {
    296             this.modal.show = false;
    297 
    298             if (this.modalChecks.pendingReset) {
    299                 console.log("reset is indeed pending");
    300                 if (button === "Continue") {
    301                     this.reset(true);
    302                 }
    303 
    304                 this.modalChecks.pendingReset = false;
    305             }
    306             else if (this.modalChecks.ocrTextEdited) {
    307                 if (button === "Continue") {
    308                     this.modalChecks.ocrTextEdited = false;
    309                     await this.doOcr();
    310                 }
    311             }
    312300        },
    313301
  • main/trunk/model-interfaces-dev/atea/ocr/src/components/ModalDialog.vue

    r35752 r35762  
    11<template>
    2 <div class="background-cover">
     2<div class="background-cover" :class="{ 'hidden': !isShowing }">
    33    <div class="paper modal">
    44        <span class="heading3">{{ title }}</span>
     
    88
    99        <div class="buttons">
    10             <button v-for="name in buttons" :key="name" class="btn-primary" @click="$emit('close', name)">{{ name }}</button>
     10            <button v-for="name in buttons" :key="name" class="btn-primary" @click="close(name)">{{ name }}</button>
    1111        </div>
    1212    </div>
     
    1919    height: 100%;
    2020    width: 100%;
     21    top: 0;
     22    left: 0;
    2123
    2224    display: flex;
     
    3941}
    4042
     43.hidden {
     44    display: none;
     45}
     46
    4147hr {
    4248    margin: 0.5em 0;
     
    4854export default {
    4955    name: "ModalDialog",
    50     props: {
    51         title: String,
    52         description: String,
    53         buttons: Array
     56    data() {
     57        return {
     58            id: null,
     59            title: null,
     60            description: null,
     61            buttons: null,
     62            callback: null,
     63            isShowing: false
     64        }
    5465    },
    55     emits: [ "close" ]
     66    methods: {
     67        show(title, description, buttons, callback, id) {
     68            this.id = id;
     69            this.title = title;
     70            this.description = description;
     71            this.buttons = buttons;
     72            this.callback = callback;
     73
     74            this.isShowing = true;
     75        },
     76        close(buttonName) {
     77            this.isShowing = false;
     78            this.callback(buttonName, this.id);
     79        }
     80    }
     81}
     82
     83export class ModalController {
     84    static modal = null;
     85    static queue = [];
     86    static waitingOnClose = false;
     87
     88    static setModal(modal) {
     89        this.modal = modal;
     90    }
     91
     92    static open(title, description, buttons, callback, id) {
     93        this.queue.push({
     94            title: title,
     95            description: description,
     96            buttons: buttons,
     97            callback: callback,
     98            id: id
     99        });
     100
     101        this.showModals();
     102    }
     103
     104    static showModals() {
     105        if (this.waitingOnClose || this.queue.length === 0) {
     106            return;
     107        }
     108
     109        this.waitingOnClose = true;
     110        const item = this.queue.shift();
     111        const that = this;
     112
     113        this.modal.show(
     114            item.title,
     115            item.description,
     116            item.buttons,
     117            function(buttonName, id) {
     118                that.waitingOnClose = false;
     119                that.showModals();
     120                item.callback(buttonName, id);
     121            },
     122            item.id
     123        );
     124    }
    56125}
    57126</script>
  • main/trunk/model-interfaces-dev/atea/resources/interface_atea.properties

    r35761 r35762  
    6868atea.ocr.OCREditedModal_Description=It looks like you've edited the OCR result, and running it again will remove these edits.
    6969atea.ocr.OCREditedModal_Title=Are you sure?
     70
     71atea.ocr.DiscardEditsModal_ButtonCancel=Cancel
     72atea.ocr.DiscardEditsModal_ButtonContinue=Continue
     73atea.ocr.DiscardEditsModal_Description=You have edited the image. Are you sure you want to discard your changes?
     74atea.ocr.DiscardEditsModal_Title=Discard Changes?
Note: See TracChangeset for help on using the changeset viewer.