Skip to content

Commit

Permalink
CLDR-17953 Improve UI and implementation for VXML generation (#4056)
Browse files Browse the repository at this point in the history
  • Loading branch information
btangmu authored Oct 9, 2024
1 parent 92664d5 commit faf68e4
Show file tree
Hide file tree
Showing 6 changed files with 382 additions and 309 deletions.
31 changes: 17 additions & 14 deletions tools/cldr-apps/js/src/esm/cldrGenerateVxml.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,24 @@ import * as cldrStatus from "./cldrStatus.mjs";

const SECONDS_IN_MS = 1000;

const NORMAL_RETRY = 10 * SECONDS_IN_MS; // "Normal" retry: starting or about to start
const REQUEST_TIMER = 5 * SECONDS_IN_MS; // Fetch status this often

const VXML_URL = "api/vxml";

// These must match the back end; used in requests
class LoadingPolicy {
class RequestType {
static START = "START"; // start generating vxml
static CONTINUE = "CONTINUE"; // continue generating vxml
static STOP = "STOP"; // stop (cancel) generating vxml
static CANCEL = "CANCEL"; // cancel (stop) generating vxml
}

// These must match the back end; used in responses
class Status {
static INIT = "INIT"; // before making a request (back end does not have INIT)
static WAITING = "WAITING"; // waiting on other users/tasks
static PROCESSING = "PROCESSING"; // in progress
static READY = "READY"; // finished successfully
static STOPPED = "STOPPED"; // due to error or cancellation (LoadingPolicy.STOP)
static SUCCEEDED = "SUCCEEDED"; // finished successfully
static STOPPED = "STOPPED"; // due to error, verification failure, or cancellation
}

let canGenerate = false;
Expand All @@ -45,23 +45,23 @@ function viewMounted(setData) {
function start() {
// Disable announcements during VXML generation to reduce risk of interference
cldrAnnounce.enableAnnouncements(false);
requestVxml(LoadingPolicy.START);
requestVxml(RequestType.START);
}

function fetchStatus() {
if (!canGenerate || "generate_vxml" !== cldrStatus.getCurrentSpecial()) {
canGenerate = false;
} else if (canGenerate) {
requestVxml(LoadingPolicy.CONTINUE);
requestVxml(RequestType.CONTINUE);
}
}

function stop() {
requestVxml(LoadingPolicy.STOP);
function cancel() {
requestVxml(RequestType.CANCEL);
}

function requestVxml(loadingPolicy) {
const args = { loadingPolicy: loadingPolicy };
function requestVxml(requestType) {
const args = { requestType: requestType };
const init = cldrAjax.makePostData(args);
cldrAjax
.doFetch(VXML_URL, init)
Expand All @@ -79,10 +79,13 @@ function setVxmlData(data) {
}
callbackToSetData(data);
if (data.status === Status.WAITING || data.status === Status.PROCESSING) {
window.setTimeout(fetchStatus.bind(this), NORMAL_RETRY);
} else if (data.status === Status.READY || data.status === Status.STOPPED) {
window.setTimeout(fetchStatus.bind(this), REQUEST_TIMER);
} else if (
data.status === Status.SUCCEEDED ||
data.status === Status.STOPPED
) {
cldrAnnounce.enableAnnouncements(true); // restore
}
}

export { Status, canGenerateVxml, start, stop, viewMounted };
export { Status, cancel, canGenerateVxml, start, viewMounted };
88 changes: 74 additions & 14 deletions tools/cldr-apps/js/src/views/GenerateVxml.vue
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
<script setup>
import { onMounted, ref } from "vue";
import { onMounted, ref, reactive } from "vue";
import * as cldrGenerateVxml from "../esm/cldrGenerateVxml.mjs";
const STATUS = cldrGenerateVxml.Status;
let hasPermission = ref(false);
let message = ref("");
let output = ref("");
let directory = ref("");
let localeId = ref("");
let localesDone = ref(0);
let localesTotal = ref(0);
let percent = ref(0);
let status = ref(STATUS.INIT);
let verificationStatus = ref("");
let verificationFailures = null; /* array of strings */
let verificationWarnings = null; /* array of strings */
function mounted() {
cldrGenerateVxml.viewMounted(setData);
Expand All @@ -20,25 +26,56 @@ onMounted(mounted);
function start() {
if (hasPermission) {
cldrGenerateVxml.start();
message = ref("");
directory = ref("");
localeId = ref("");
localesDone = ref(0);
localesTotal = ref(0);
percent = ref(0);
status.value = STATUS.WAITING;
verificationStatus = ref("");
verificationFailures = verificationWarnings = null;
cldrGenerateVxml.start();
}
}
function stop() {
cldrGenerateVxml.stop();
function cancel() {
cldrGenerateVxml.cancel();
status.value = STATUS.STOPPED;
}
function canStop() {
function canCancel() {
return status.value === STATUS.WAITING || status.value === STATUS.PROCESSING;
}
function setData(data) {
message.value = data.message;
percent.value = data.percent;
status.value = data.status;
output.value = data.output;
directory.value = data.directory;
localeId.value = data.localeId;
localesDone.value = data.localesDone;
localesTotal.value = data.localesTotal;
verificationStatus.value = data.verificationStatus;
verificationFailures = reactive(data.verificationFailures); // array
verificationWarnings = reactive(data.verificationWarnings); // array
}
function copyDirectory() {
navigator.clipboard.writeText(directory.value);
}
function progressBarStatus() {
// Reference: https://ant.design/components/progress#api
if (status.value === STATUS.STOPPED) {
return "exception";
} else if (status.value === STATUS.SUCCEEDED) {
return "success";
} else if (percent.value > 0 && percent.value < 100) {
return "active";
} else {
return "normal";
}
}
defineExpose({
Expand All @@ -49,18 +86,34 @@ defineExpose({
<template>
<div v-if="!hasPermission">Please log in as Admin to use this feature.</div>
<div v-else>
<p v-if="status != STATUS.INIT">Current Status: {{ status }}</p>
<p v-if="message">
<span v-html="message"></span>
</p>
<p v-if="status != STATUS.INIT">Generation Status: {{ status }}</p>
<p class="buttons">
<button v-if="canStop()" @click="stop()">Stop</button>
<button v-if="canCancel()" @click="cancel()">Cancel</button>
<button v-else @click="start()">Generate VXML Now</button>
</p>
<p class="progressBar">
<a-progress :percent="percent" />
<a-progress :percent="percent" :status="progressBarStatus()" />
</p>
<p v-if="directory">
<span>Directory created: {{ directory }}</span>
&nbsp;
<button @click="copyDirectory()">Copy</button>
</p>
<p v-if="message">{{ message }}</p>
<p v-if="localeId">
Wrote locale: {{ localeId }} ({{ localesDone }} / {{ localesTotal }})
</p>
<p v-html="output"></p>
<p v-if="verificationStatus">
Verification Status: {{ verificationStatus }}
</p>
<div v-if="verificationFailures?.length">
<h2 class="sectionHeader">Verification Failures</h2>
<p v-for="msg of verificationFailures" :key="msg">{{ msg }}</p>
</div>
<div v-if="verificationWarnings?.length">
<h2 class="sectionHeader">Verification Warnings</h2>
<p v-for="msg of verificationWarnings" :key="msg">{{ msg }}</p>
</div>
</div>
</template>

Expand All @@ -72,4 +125,11 @@ defineExpose({
.progressBar {
width: 50%;
}
.sectionHeader {
font-weight: bold;
margin-top: 1em;
margin-bottom: 0.5em;
font-size: 20px;
}
</style>
Loading

0 comments on commit faf68e4

Please sign in to comment.