Changeset 35305 for main/trunk


Ignore:
Timestamp:
2021-08-17T16:40:17+12:00 (3 years ago)
Author:
davidb
Message:

Add word editing.

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

Legend:

Unmodified
Added
Removed
  • main/trunk/model-interfaces-dev/atea/js/asr/asr-controller.js

    r35304 r35305  
    66import { TranscribeService, TranscriptionError, TranscriptionModel, TranscriptionMetadata } from "./TranscribeModule.js";
    77
    8 class TranscriptionViewModel {
     8class TranscriptionViewModel
     9{
    910    /**
    1011     * Initialises a new instance of the {@link TranscriptionViewModel} class.
     
    4041}
    4142
     43class TranscriptionViewFailure
     44{
     45    /**
     46     *
     47     * @param {String} fileName The name of the file for which this failure occured.
     48     * @param {String} message The reason for this failure.
     49     */
     50    constructor(fileName, message) {
     51        /** @type {String} The UUID of this failure. */
     52        this.id = UUID.generate();
     53
     54        /** @type {String | null} The name of the file for which this failure occured. */
     55        this.fileName = fileName;
     56
     57        /** @type {String} The reason for the failure. */
     58        this.message = message;
     59
     60        /** @type {Boolean} Gets or sets a value indicating if this transcription view has been deleted. */
     61        this.isDeleted = false;
     62    }
     63}
     64
    4265/** @type {HTMLAudioElement} */
    4366var EL_AUDIO_TRANSCRIPTION_AUDIO;
     
    188211            /** @type {Map<String, TranscriptionViewModel>} */
    189212            transcriptions: new Map(),
    190             /** @type {Map<String, TranscriptionError>} */
     213            /** @type {Map<String, TranscriptionViewFailure>} */
    191214            failures: new Map(),
    192215            showCharDisplay: false,
     216            enableTextEditing: false,
    193217            /** @type {{id: String, url: String} | null} Gets the ID of the transcription for which the audio is currently loaded */
    194218            currentlyLoadedAudio: null,
     
    200224        playAudioFile(transcriptionId, startTime = 0)
    201225        {
    202             if (startTime < 0)
    203             {
     226            if (this.enableTextEditing && startTime != -1) { // Check the start time to know if we've been triggered by a word click
     227                return;
     228            }
     229
     230            // A value of -1 indicates that the play button has been used.
     231            // Any other causes of negative time values, for whatever unknown reason, are silently corrected
     232            if (startTime < 0) {
    204233                startTime = 0;
    205                 console.warn("Cannot start audio playback at a time of less than zero.");
    206234            }
    207235
     
    223251        },
    224252        removeFailure(id) {
    225             this.failures.delete(id);
     253            this.failures.get(id).isDeleted = true;
     254            delay(550).then(() => this.failures.delete(id));
    226255        },
    227256        getChars(transcriptionId)
     
    248277        currentAudioTime(newValue)
    249278        {
    250             // TODO: Replace with more efficient search. Even binary would be a significant improvment for longer transcriptions.
     279            // TODO: Replace with more efficient search. Even binary would be a significant improvement for longer transcriptions.
    251280            const t = this.transcriptions.get(this.currentlyLoadedAudio.id);
    252281
     
    297326    AudioUploadVM.isTranscribing = true;
    298327   
    299     await delay(200); // TODO: Remove - UI testing purposes only
     328    // await delay(200); // TODO: Remove - UI testing purposes only
    300329   
    301330    // Transcribe each audio file in batches.
     
    307336            {
    308337                if (!t.success) {
    309                     TranscriptionsListVM.failures.set(UUID.generate(), new TranscriptionError(t.log, t.file_name));
     338                    let failure = new TranscriptionViewFailure(t.file_name, t.log);
     339                    TranscriptionsListVM.failures.set(failure.id, failure);
    310340                }
    311341                else {
     
    326356        console.error("Failed to transcribe files");
    327357        console.error(e);
    328         TranscriptionsListVM.failures.set(UUID.generate(), e);
     358        let failure = new TranscriptionViewFailure(e.fileName, e.message);
     359        TranscriptionsListVM.failures.set(failure.id, failure);
    329360    }
    330361   
     
    367398                word: lastWord,
    368399                startTime: currStartTime,
    369                 endTime: transcription.metadata[transcription.metadata.length].start_time,
     400                endTime: transcription.metadata[transcription.metadata.length - 1].start_time,
    370401                shouldHighlight: false
    371402            });
  • main/trunk/model-interfaces-dev/atea/style/asr.scss

    r35304 r35305  
    2828
    2929.transform-slideout {
    30     -webkit-transition-duration: 0.5s;
    31     -moz-transition-duration: 0.5s;
    32     transition-duration: 0.5s;
     30    -webkit-transition-duration: 0.4s;
     31    -moz-transition-duration: 0.4s;
     32    transition-duration: 0.4s;
    3333
    3434    transform: translate(100%, 0);
     
    102102    display: flex;
    103103
    104     font: var(--monospace-font);
    105104    padding-top: 1em;
    106105
     
    116115}
    117116
    118 .transcription__word {
     117.transcription__word-highlight {
     118    background-color: rgba(255, 255, 0, 0.4);
     119}
     120
     121.transcription__word-container {
     122    font: var(--monospace-font);
    119123    display: inline-block;
    120124    margin-bottom: 1em;
    121125
    122126    &:hover {
    123         background-color: rgba(255, 255, 0, 0.4)
    124     }
    125 }
    126 
    127 .yellow {
    128     background-color: rgba(255, 255, 0, 0.4);
     127        @extend .transcription__word-highlight;
     128    }
     129}
     130
     131.transcription__word {
     132    font: var(--monospace-font);
     133    display: inline;
     134    background: transparent;
     135    width: auto;
     136    border: none;
     137
     138    &:disabled {
     139        color: black;
     140    }
    129141}
    130142
  • main/trunk/model-interfaces-dev/atea/style/material.scss

    r35302 r35305  
    168168    }
    169169
    170     &:active {
     170    &:active, &:focus {
    171171        border-bottom: 1px solid var(--primary-bg-color);
    172172       
  • main/trunk/model-interfaces-dev/atea/transform/pages/asr.xsl

    r35304 r35305  
    8181                <ul class="transcription__list">
    8282                    <!-- Displays any failed transcriptions -->
    83                     <li v-for="[key, value] in failures">
     83                    <li v-for="[id, failure] in failures">
     84                        <xsl:attribute name="v-bind:class">
     85                            <xsl:text disable-output-escaping="yes">{ 'transform-slideout': failure.isDeleted }</xsl:text>
     86                        </xsl:attribute>
     87
    8488                        <div class="transcription__error-container card">
    8589                            <div>
    86                                 Failed to transcribe <i v-if="value.file">{{ value.fileName }}</i><br/>
    87                                 <span v-if="value.message">Reason: {{ value.message }}</span>
     90                                Failed to transcribe <i v-if="failure.file">{{ failure.fileName }}</i><br/>
     91                                <span v-if="failure.message">Reason: {{ failure.message }}</span>
    8892                            </div>
    8993                           
    90                             <button class="btn-fab theme-flat" v-on:click="removeFailure(key)">
     94                            <button class="btn-fab theme-flat" v-on:click="removeFailure(id)">
    9195                                <span class="material-icons">&#xE14C;</span> <!-- clear -->
    9296                            </button>
     
    117121                            <div class="transcription__word-list" v-if="transcription.isExpanded">
    118122                                <div class="transcription__word-list__controls">
    119                                     <button class="btn-fab" v-on:click="playAudioFile(id)" type="button">
     123                                    <button class="btn-fab" v-on:click="playAudioFile(id, -1)" type="button">
    120124                                        <span class="material-icons">play_arrow</span>
    121125                                    </button>
    122126
    123                                     <input type="checkbox" v-model="showCharDisplay" />
     127                                    <input type="checkbox" v-model="showCharDisplay" title="Show characters" />
     128
     129                                    <input type="checkbox" v-model="enableTextEditing" title="Enable text editing" />
    124130                                </div>
    125131                               
    126132                                <ul class="transcription__list">
    127133                                    <li v-if="!showCharDisplay">
    128                                         <span v-for="word in transcription.words" class="transcription__word"
     134                                        <div v-for="word in transcription.words" class="transcription__word-container"
    129135                                            v-on:click="playAudioFile(id, word.startTime)">
    130136                                            <xsl:attribute name="v-bind:class">
    131                                                 <xsl:text disable-output-escaping="yes">{ yellow: word.shouldHighlight }</xsl:text>
     137                                                <xsl:text disable-output-escaping="yes">{ 'transcription__word-highlight': word.shouldHighlight }</xsl:text>
    132138                                            </xsl:attribute>
    133139
    134                                             {{ word.word }}
    135                                         </span>
     140                                            <input type="text" v-bind:size="word.word.length - 1" v-model="word.word" class="transcription__word"
     141                                                v-bind:disabled="!enableTextEditing" />
     142                                        </div>
    136143                                    </li>
    137144                                    <li v-if="showCharDisplay">
    138                                         <span v-for="char in getChars(id)" class="transcription__word"
     145                                        <span v-for="char in getChars(id)" class="transcription__word-container"
    139146                                              v-on:click="playAudioFile(id, char.startTime)">
    140147                                            {{ char.char }}
Note: See TracChangeset for help on using the changeset viewer.