InferenceJobsList cleanup accross Face Animator and Voice Designer, including revised localization name space

This commit is contained in:
Victor committed 2023-12-06 21:56:38 -08:00
1 parent f7f6a28e12
commit 893ccd2f78
29 files changed
+604 -246

No files matched your search

@@ -0,0 +1,31 @@
{
"core": {
"heading": "সর্বশেষ চাকরি"
},
"face_animator": {
"ATTEMPT_FAILED": "ফেস অ্যানিমেশন প্রচেষ্টা ব্যর্থ হয়েছে৷",
"COMPLETE_FAILURE": "ফেস অ্যানিমেশন ব্যর্থ হয়েছে৷",
"COMPLETE_SUCCESS": "ফেস অ্যানিমেশন সম্পূর্ণ",
"PENDING": "মুলতুবি ফেস অ্যানিমেশন",
"STARTED": "ফেস অ্যানিমেশন চলছে",
"UNKNOWN": "অ্যানিমেশন অবস্থা অজানা",
"heading": "ফেস অ্যানিমেটর চাকরি"
},
"subtitles": {
"ATTEMPT_FAILED": "প্রয়াস {{attemptCount}} ব্যর্থ, আবার চেষ্টা.",
"COMPLETE_FAILURE": "অনুগ্রহপূর্বক আবার চেষ্টা করুন",
"COMPLETE_SUCCESS": "ফলাফল দেখুন",
"PENDING": "সারিতে যোগ করা হচ্ছে",
"STARTED": "অনুগ্রহপূর্বক অপেক্ষা করুন",
"UNKNOWN": "অনুগ্রহ করে অপেক্ষা করুন বা আবার চেষ্টা করুন"
},
"voice_designer": {
"ATTEMPT_FAILED": "ফেস অ্যানিমেশন প্রচেষ্টা ব্যর্থ হয়েছে৷",
"COMPLETE_FAILURE": "ফেস অ্যানিমেশন ব্যর্থ হয়েছে৷",
"COMPLETE_SUCCESS": "ফেস অ্যানিমেশন সম্পূর্ণ",
"PENDING": "ভয়েস ডিজাইনার মুলতুবি",
"STARTED": "ভয়েস ডিজাইনার চলছে",
"UNKNOWN": "ভয়েস ডিজাইনার অবস্থা অজানা",
"heading": "ভয়েস ডিজাইনার চাকরি"
}
}
@@ -0,0 +1,31 @@
{
"core": {
"heading": "Neueste Jobs"
},
"face_animator": {
"ATTEMPT_FAILED": "Gesichtsanimationsversuch fehlgeschlagen",
"COMPLETE_FAILURE": "Gesichtsanimation fehlgeschlagen.",
"COMPLETE_SUCCESS": "Gesichtsanimation abgeschlossen",
"PENDING": "Ausstehende Gesichtsanimation",
"STARTED": "Gesichtsanimation läuft",
"UNKNOWN": "Animationsstatus unbekannt",
"heading": "Jobs als Gesichtsanimator"
},
"subtitles": {
"ATTEMPT_FAILED": "Versuch {{attemptCount}} fehlgeschlagen, versuche es erneut.",
"COMPLETE_FAILURE": "Bitte versuche es erneut",
"COMPLETE_SUCCESS": "Zeige Ergebnis",
"PENDING": "Zur Warteschlange hinzufügen",
"STARTED": "Bitte warten",
"UNKNOWN": "Bitte warten Sie oder versuchen Sie es erneut"
},
"voice_designer": {
"ATTEMPT_FAILED": "Gesichtsanimationsversuch fehlgeschlagen",
"COMPLETE_FAILURE": "Gesichtsanimation fehlgeschlagen.",
"COMPLETE_SUCCESS": "Gesichtsanimation abgeschlossen",
"PENDING": "Voice Designer Ausstehend",
"STARTED": "Voice Designer in Bearbeitung",
"UNKNOWN": "Voice Designer-Status unbekannt",
"heading": "Jobs als Sprachdesigner"
}
}
@@ -0,0 +1,31 @@
{
"core": {
"heading": "Latest Jobs"
},
"face_animator": {
"ATTEMPT_FAILED": "Face Animation Atempt Failed",
"COMPLETE_FAILURE": "Face Animation Failed.",
"COMPLETE_SUCCESS": "Face Animation Complete",
"PENDING": "Pending Face Animation",
"STARTED": "Face Animation In Progress",
"UNKNOWN": "Animation Status Uknown",
"heading": "Face Animator Jobs"
},
"subtitles": {
"ATTEMPT_FAILED": "Atempt {{attemptCount}} failed, trying again.",
"COMPLETE_FAILURE": "Please try again",
"COMPLETE_SUCCESS": "View result",
"PENDING": "Adding to queue",
"STARTED": "Please wait",
"UNKNOWN": "Please wait or try again"
},
"voice_designer": {
"ATTEMPT_FAILED": "Face Animation Atempt Failed",
"COMPLETE_FAILURE": "Face Animation Failed.",
"COMPLETE_SUCCESS": "Face Animation Complete",
"PENDING": "Voice Designer Pending",
"STARTED": "Voice Designer In Progress",
"UNKNOWN": "Voice Designer Status Uknown",
"heading": "Voice Designer Jobs"
}
}
@@ -0,0 +1,31 @@
{
"core": {
"heading": "Ultimos trabajos"
},
"face_animator": {
"ATTEMPT_FAILED": "Error al intentar animar la cara",
"COMPLETE_FAILURE": "Error en la animación de la cara.",
"COMPLETE_SUCCESS": "Animación facial completa",
"PENDING": "Animación de cara pendiente",
"STARTED": "Animación facial en progreso",
"UNKNOWN": "Estado de la animación desconocido",
"heading": "Trabajos de animador facial"
},
"subtitles": {
"ATTEMPT_FAILED": "intento {{attemptCount}} falló, intentándolo de nuevo.",
"COMPLETE_FAILURE": "Inténtalo de nuevo",
"COMPLETE_SUCCESS": "Ver resultado",
"PENDING": "Agregar a la cola",
"STARTED": "Espere por favor",
"UNKNOWN": "Espere o intente nuevamente"
},
"voice_designer": {
"ATTEMPT_FAILED": "Error al intentar animar la cara",
"COMPLETE_FAILURE": "Error en la animación de la cara.",
"COMPLETE_SUCCESS": "Animación facial completa",
"PENDING": "Diseñador de voz pendiente",
"STARTED": "Diseñador de voz en progreso",
"UNKNOWN": "Estado del diseñador de voz desconocido",
"heading": "Empleos de Diseñador de voz"
}
}
@@ -0,0 +1,31 @@
{
"core": {
"heading": "Derniers emplois"
},
"face_animator": {
"ATTEMPT_FAILED": "Échec de la tentative d'animation du visage",
"COMPLETE_FAILURE": "Échec de l'animation du visage.",
"COMPLETE_SUCCESS": "Animation du visage terminée",
"PENDING": "Animation de visage en attente",
"STARTED": "Animation du visage en cours",
"UNKNOWN": "Statut de l'animation inconnu",
"heading": "Emplois d'animateur de visage"
},
"subtitles": {
"ATTEMPT_FAILED": "Tentative {{attemptCount}} échoué, j'ai réessayé.",
"COMPLETE_FAILURE": "Veuillez réessayer",
"COMPLETE_SUCCESS": "Voir résultat",
"PENDING": "Ajout à la file d'attente",
"STARTED": "S'il vous plaît, attendez",
"UNKNOWN": "Veuillez patienter ou réessayer"
},
"voice_designer": {
"ATTEMPT_FAILED": "Échec de la tentative d'animation du visage",
"COMPLETE_FAILURE": "Échec de l'animation du visage.",
"COMPLETE_SUCCESS": "Animation du visage terminée",
"PENDING": "Concepteur de voix en attente",
"STARTED": "Concepteur de voix en cours",
"UNKNOWN": "Statut de Voice Designer inconnu",
"heading": "Emplois de concepteur de voix"
}
}
@@ -0,0 +1,31 @@
{
"core": {
"heading": "नवीनतम नौकरियाँ"
},
"face_animator": {
"ATTEMPT_FAILED": "फेस एनीमेशन का प्रयास विफल रहा",
"COMPLETE_FAILURE": "फेस एनीमेशन विफल.",
"COMPLETE_SUCCESS": "फेस एनीमेशन पूर्ण",
"PENDING": "लंबित चेहरा एनीमेशन",
"STARTED": "फेस एनिमेशन प्रगति पर है",
"UNKNOWN": "एनीमेशन स्थिति अज्ञात",
"heading": "फेस एनिमेटर नौकरियां"
},
"subtitles": {
"ATTEMPT_FAILED": "प्रयास {{attemptCount}} विफल, पुनः प्रयास कर रहा हूँ।",
"COMPLETE_FAILURE": "कृपया पुन: प्रयास करें",
"COMPLETE_SUCCESS": "परिणाम देख",
"PENDING": "कतार में जोड़ा जा रहा है",
"STARTED": "कृपया प्रतीक्षा करें",
"UNKNOWN": "कृपया प्रतीक्षा करें या पुनः प्रयास करें"
},
"voice_designer": {
"ATTEMPT_FAILED": "फेस एनीमेशन का प्रयास विफल रहा",
"COMPLETE_FAILURE": "फेस एनीमेशन विफल.",
"COMPLETE_SUCCESS": "फेस एनीमेशन पूर्ण",
"PENDING": "वॉइस डिज़ाइनर लंबित",
"STARTED": "वॉयस डिज़ाइनर प्रगति पर है",
"UNKNOWN": "वॉइस डिज़ाइनर स्थिति अज्ञात",
"heading": "वॉयस डिजाइनर नौकरियां"
}
}
@@ -0,0 +1,31 @@
{
"core": {
"heading": "Pekerjaan Terbaru"
},
"face_animator": {
"ATTEMPT_FAILED": "Upaya Animasi Wajah Gagal",
"COMPLETE_FAILURE": "Animasi Wajah Gagal.",
"COMPLETE_SUCCESS": "Animasi Wajah Lengkap",
"PENDING": "Animasi Wajah Tertunda",
"STARTED": "Animasi Wajah Sedang Berlangsung",
"UNKNOWN": "Status Animasi Tidak Diketahui",
"heading": "Pekerjaan Animator Wajah"
},
"subtitles": {
"ATTEMPT_FAILED": "Mencoba {{attemptCount}} gagal, coba lagi.",
"COMPLETE_FAILURE": "Silakan coba lagi",
"COMPLETE_SUCCESS": "Lihat hasil",
"PENDING": "Menambah antrian",
"STARTED": "Harap tunggu",
"UNKNOWN": "Harap tunggu atau coba lagi"
},
"voice_designer": {
"ATTEMPT_FAILED": "Upaya Animasi Wajah Gagal",
"COMPLETE_FAILURE": "Animasi Wajah Gagal.",
"COMPLETE_SUCCESS": "Animasi Wajah Lengkap",
"PENDING": "Desainer Suara Tertunda",
"STARTED": "Perancang Suara Sedang Berlangsung",
"UNKNOWN": "Status Perancang Suara Tidak Diketahui",
"heading": "Pekerjaan Desainer Suara"
}
}
@@ -0,0 +1,31 @@
{
"core": {
"heading": "Ultimi lavori"
},
"face_animator": {
"ATTEMPT_FAILED": "Tentativo di animazione del volto non riuscito",
"COMPLETE_FAILURE": "Animazione del volto non riuscita.",
"COMPLETE_SUCCESS": "Animazione del volto completata",
"PENDING": "Animazione del volto in attesa",
"STARTED": "Animazione del volto in corso",
"UNKNOWN": "Stato dell'animazione sconosciuto",
"heading": "Lavori di animatore di volti"
},
"subtitles": {
"ATTEMPT_FAILED": "Tentativo {{attemptCount}} fallito, riprovando.",
"COMPLETE_FAILURE": "Per favore riprova",
"COMPLETE_SUCCESS": "Visualizza risultato",
"PENDING": "Aggiunta alla coda",
"STARTED": "attendere prego",
"UNKNOWN": "Attendi o riprova"
},
"voice_designer": {
"ATTEMPT_FAILED": "Tentativo di animazione del volto non riuscito",
"COMPLETE_FAILURE": "Animazione del volto non riuscita.",
"COMPLETE_SUCCESS": "Animazione del volto completata",
"PENDING": "Voice Designer in attesa",
"STARTED": "Designer vocale in corso",
"UNKNOWN": "Stato del Voice Designer sconosciuto",
"heading": "Lavori di progettista vocale"
}
}
@@ -0,0 +1,31 @@
{
"core": {
"heading": "最新の求人"
},
"face_animator": {
"ATTEMPT_FAILED": "顔アニメーションの試行が失敗しました",
"COMPLETE_FAILURE": "顔のアニメーションが失敗しました。",
"COMPLETE_SUCCESS": "顔のアニメーションが完了しました",
"PENDING": "保留中の顔のアニメーション",
"STARTED": "顔のアニメーションが進行中",
"UNKNOWN": "アニメーションステータス不明",
"heading": "フェイスアニメーターの仕事"
},
"subtitles": {
"ATTEMPT_FAILED": "試みる {{attemptCount}} 失敗しました。再試行してください。",
"COMPLETE_FAILURE": "もう一度試してください",
"COMPLETE_SUCCESS": "結果を見る",
"PENDING": "キューに追加中",
"STARTED": "お待ちください",
"UNKNOWN": "しばらく待つか、もう一度試してください"
},
"voice_designer": {
"ATTEMPT_FAILED": "顔アニメーションの試行が失敗しました",
"COMPLETE_FAILURE": "顔のアニメーションが失敗しました。",
"COMPLETE_SUCCESS": "顔のアニメーションが完了しました",
"PENDING": "ボイスデザイナー保留中",
"STARTED": "ボイスデザイナー進行中",
"UNKNOWN": "ボイスデザイナーのステータスは不明",
"heading": "ボイスデザイナーの仕事"
}
}
@@ -0,0 +1,31 @@
{
"core": {
"heading": "최신 채용 정보"
},
"face_animator": {
"ATTEMPT_FAILED": "얼굴 애니메이션 시도가 실패했습니다.",
"COMPLETE_FAILURE": "얼굴 애니메이션이 실패했습니다.",
"COMPLETE_SUCCESS": "얼굴 애니메이션 완료",
"PENDING": "보류 중인 얼굴 애니메이션",
"STARTED": "얼굴 애니메이션 진행 중",
"UNKNOWN": "애니메이션 상태를 알 수 없음",
"heading": "얼굴 애니메이터 채용"
},
"subtitles": {
"ATTEMPT_FAILED": "시도 {{attemptCount}} 실패했습니다. 다시 시도해 보세요.",
"COMPLETE_FAILURE": "다시 시도해 주세요",
"COMPLETE_SUCCESS": "결과 보기",
"PENDING": "대기열에 추가 중",
"STARTED": "기다리세요",
"UNKNOWN": "기다리거나 다시 시도해 주세요."
},
"voice_designer": {
"ATTEMPT_FAILED": "얼굴 애니메이션 시도가 실패했습니다.",
"COMPLETE_FAILURE": "얼굴 애니메이션이 실패했습니다.",
"COMPLETE_SUCCESS": "얼굴 애니메이션 완료",
"PENDING": "음성 디자이너 보류 중",
"STARTED": "음성 디자이너 진행 중",
"UNKNOWN": "음성 디자이너 상태 알 수 없음",
"heading": "음성 디자이너 채용"
}
}
@@ -0,0 +1,31 @@
{
"core": {
"heading": "Últimos trabalhos"
},
"face_animator": {
"ATTEMPT_FAILED": "Falha na tentativa de animação facial",
"COMPLETE_FAILURE": "Falha na animação facial.",
"COMPLETE_SUCCESS": "Animação facial completa",
"PENDING": "Animação facial pendente",
"STARTED": "Animação facial em andamento",
"UNKNOWN": "Status da animação desconhecido",
"heading": "Empregos de animador facial"
},
"subtitles": {
"ATTEMPT_FAILED": "Tentativa {{attemptCount}} falhou, tentando novamente.",
"COMPLETE_FAILURE": "Por favor, tente novamente",
"COMPLETE_SUCCESS": "Ver resultado",
"PENDING": "Adicionando à fila",
"STARTED": "Por favor, aguarde",
"UNKNOWN": "Aguarde ou tente novamente"
},
"voice_designer": {
"ATTEMPT_FAILED": "Falha na tentativa de animação facial",
"COMPLETE_FAILURE": "Falha na animação facial.",
"COMPLETE_SUCCESS": "Animação facial completa",
"PENDING": "Designer de voz pendente",
"STARTED": "Designer de voz em andamento",
"UNKNOWN": "Status do Voice Designer desconhecido",
"heading": "Empregos de designer de voz"
}
}
@@ -0,0 +1,31 @@
{
"core": {
"heading": "Последние вакансии"
},
"face_animator": {
"ATTEMPT_FAILED": "Попытка анимации лица не удалась",
"COMPLETE_FAILURE": "Не удалось выполнить анимацию лица.",
"COMPLETE_SUCCESS": "Анимация лица завершена",
"PENDING": "Ожидание анимации лица",
"STARTED": "Анимация лица в процессе",
"UNKNOWN": "Статус анимации неизвестен",
"heading": "Вакансии Face Animator"
},
"subtitles": {
"ATTEMPT_FAILED": "Попытка {{attemptCount}} не получилось, попробую еще раз.",
"COMPLETE_FAILURE": "Пожалуйста, попробуйте еще раз",
"COMPLETE_SUCCESS": "Посмотреть результат",
"PENDING": "Добавление в очередь",
"STARTED": "пожалуйста, подождите",
"UNKNOWN": "Пожалуйста, подождите или попробуйте еще раз"
},
"voice_designer": {
"ATTEMPT_FAILED": "Попытка анимации лица не удалась",
"COMPLETE_FAILURE": "Не удалось выполнить анимацию лица.",
"COMPLETE_SUCCESS": "Анимация лица завершена",
"PENDING": "Голосовой дизайнер на рассмотрении",
"STARTED": "Голосовой дизайнер в разработке",
"UNKNOWN": "Статус дизайнера голоса неизвестен",
"heading": "Вакансии голосового дизайнера"
}
}
@@ -0,0 +1,31 @@
{
"core": {
"heading": "งานล่าสุด"
},
"face_animator": {
"ATTEMPT_FAILED": "ความพยายามในแอนิเมชั่นใบหน้าล้มเหลว",
"COMPLETE_FAILURE": "ภาพเคลื่อนไหวใบหน้าล้มเหลว",
"COMPLETE_SUCCESS": "แอนิเมชั่นใบหน้าเสร็จสมบูรณ์",
"PENDING": "ภาพเคลื่อนไหวใบหน้าที่รอดำเนินการ",
"STARTED": "อยู่ระหว่างดำเนินการภาพเคลื่อนไหวใบหน้า",
"UNKNOWN": "ไม่ทราบสถานะแอนิเมชั่น",
"heading": "งานแอนิเมเตอร์ใบหน้า"
},
"subtitles": {
"ATTEMPT_FAILED": "พยายาม {{attemptCount}} ล้มเหลว ลองอีกครั้ง",
"COMPLETE_FAILURE": "กรุณาลองอีกครั้ง",
"COMPLETE_SUCCESS": "ดูผลลัพธ์",
"PENDING": "กำลังเพิ่มเข้าคิว.",
"STARTED": "โปรดรอ",
"UNKNOWN": "กรุณารอสักครู่หรือลองอีกครั้ง"
},
"voice_designer": {
"ATTEMPT_FAILED": "ความพยายามในแอนิเมชั่นใบหน้าล้มเหลว",
"COMPLETE_FAILURE": "ภาพเคลื่อนไหวใบหน้าล้มเหลว",
"COMPLETE_SUCCESS": "แอนิเมชั่นใบหน้าเสร็จสมบูรณ์",
"PENDING": "โปรแกรมออกแบบเสียงรอดำเนินการ",
"STARTED": "อยู่ระหว่างการออกแบบเสียง",
"UNKNOWN": "ไม่ทราบสถานะผู้ออกแบบเสียง",
"heading": "งานนักออกแบบเสียง"
}
}
@@ -0,0 +1,31 @@
{
"core": {
"heading": "En Son İşler"
},
"face_animator": {
"ATTEMPT_FAILED": "Yüz Animasyonu Denemesi Başarısız",
"COMPLETE_FAILURE": "Yüz Animasyonu Başarısız.",
"COMPLETE_SUCCESS": "Yüz Animasyonu Tamamlandı",
"PENDING": "Bekleyen Yüz Animasyonu",
"STARTED": "Yüz Animasyonu Devam Ediyor",
"UNKNOWN": "Animasyon Durumu Bilinmiyor",
"heading": "Yüz Animatörü İş İlanları"
},
"subtitles": {
"ATTEMPT_FAILED": "deneme {{attemptCount}} başarısız oldu, tekrar denedi.",
"COMPLETE_FAILURE": "Lütfen tekrar deneyin",
"COMPLETE_SUCCESS": "Sonucu göster",
"PENDING": "Kuyruğa ekleniyor",
"STARTED": "Lütfen bekleyin",
"UNKNOWN": "Lütfen bekleyin veya tekrar deneyin"
},
"voice_designer": {
"ATTEMPT_FAILED": "Yüz Animasyonu Denemesi Başarısız",
"COMPLETE_FAILURE": "Yüz Animasyonu Başarısız.",
"COMPLETE_SUCCESS": "Yüz Animasyonu Tamamlandı",
"PENDING": "Ses Tasarımcısı Beklemede",
"STARTED": "Ses Tasarımcısı Devam Ediyor",
"UNKNOWN": "Ses Tasarımcısı Durumu Bilinmiyor",
"heading": "Ses Tasarımcısı İş İlanları"
}
}
@@ -0,0 +1,31 @@
{
"core": {
"heading": "Việc làm mới nhất"
},
"face_animator": {
"ATTEMPT_FAILED": "Nỗ lực hoạt hình khuôn mặt không thành công",
"COMPLETE_FAILURE": "Hoạt ảnh khuôn mặt không thành công.",
"COMPLETE_SUCCESS": "Hoạt hình khuôn mặt hoàn chỉnh",
"PENDING": "Hoạt ảnh khuôn mặt đang chờ xử lý",
"STARTED": "Đang tiến hành hoạt ảnh khuôn mặt",
"UNKNOWN": "Trạng thái hoạt ảnh không xác định",
"heading": "Công việc của nhà làm phim hoạt hình khuôn mặt"
},
"subtitles": {
"ATTEMPT_FAILED": "cố gắng {{attemptCount}} thất bại, thử lại.",
"COMPLETE_FAILURE": "Vui lòng thử lại",
"COMPLETE_SUCCESS": "Xem kết quả",
"PENDING": "Thêm vào hàng đợi",
"STARTED": "Vui lòng chờ",
"UNKNOWN": "Vui lòng đợi hoặc thử lại"
},
"voice_designer": {
"ATTEMPT_FAILED": "Nỗ lực hoạt hình khuôn mặt không thành công",
"COMPLETE_FAILURE": "Hoạt ảnh khuôn mặt không thành công.",
"COMPLETE_SUCCESS": "Hoạt hình khuôn mặt hoàn chỉnh",
"PENDING": "Trình thiết kế giọng nói đang chờ xử lý",
"STARTED": "Đang thiết kế giọng nói",
"UNKNOWN": "Trạng thái thiết kế giọng nói Không xác định",
"heading": "Công việc thiết kế giọng nói"
}
}
@@ -0,0 +1,31 @@
{
"core": {
"heading": "最新职位"
},
"face_animator": {
"ATTEMPT_FAILED": "脸部动画尝试失败",
"COMPLETE_FAILURE": "脸部动画失败。",
"COMPLETE_SUCCESS": "脸部动画完成",
"PENDING": "待处理的脸部动画",
"STARTED": "脸部动画正在进行中",
"UNKNOWN": "动画状态未知",
"heading": "脸部动画师职位"
},
"subtitles": {
"ATTEMPT_FAILED": "尝试 {{attemptCount}} 失败了,再试一次。",
"COMPLETE_FAILURE": "请再试一次",
"COMPLETE_SUCCESS": "查看结果",
"PENDING": "添加到队列",
"STARTED": "请稍等",
"UNKNOWN": "请稍候或重试"
},
"voice_designer": {
"ATTEMPT_FAILED": "面部动画尝试失败",
"COMPLETE_FAILURE": "脸部动画失败。",
"COMPLETE_SUCCESS": "脸部动画完成",
"PENDING": "语音设计师待定",
"STARTED": "语音设计正在进行中",
"UNKNOWN": "语音设计师状态未知",
"heading": "语音设计师职位"
}
}
@@ -0,0 +1,7 @@
.face-animator-job {
h6 {
margin-bottom: 0;
white-space: nowrap
}
span { font-weight: lighter; }
}
@@ -1,88 +1,21 @@
import React, { useEffect, useState } from 'react';
// import { a } from '@react-spring/web';
import {
GetPendingTtsJobCount, GetPendingTtsJobCountIsOk, GetPendingTtsJobCountSuccessResponse
} from "@storyteller/components/src/api/tts/GetPendingTtsJobCount";
import { FrontendInferenceJobType } from "@storyteller/components/src/jobs/InferenceJob";
import React from 'react';
import { FrontendInferenceJobType, InferenceJob } from "@storyteller/components/src/jobs/InferenceJob";
// import { springs } from "resources";
import { useInferenceJobs } from "hooks";
import { Button } from 'components/common';
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faChevronRight, faHourglass1, faRemove, faTrophy, faWarning } from "@fortawesome/free-solid-svg-icons";
const DEFAULT_QUEUE_REFRESH_INTERVAL_MILLIS = 15000;
import JobItem from './JobItem';
import { useInferenceJobs, useLocalize } from "hooks";
import "./InferenceJobsList.scss";
interface JobsListProps{
jobType: FrontendInferenceJobType,
onSelect?: (e:any) => any,
statusTxt: any,
t: any,
}
export default function InferenceJobsList({ jobType, onSelect, statusTxt, t }: JobsListProps) {
const { inferenceJobs = [] } = useInferenceJobs(jobType);
export default function InferenceJobsList({ jobType, onSelect }: JobsListProps) {
const { inferenceJobs = [], jobStatusDescription } = useInferenceJobs(jobType);
const { t } = useLocalize("InferenceJobs");
const [pending, pendingSet] = useState<GetPendingTtsJobCountSuccessResponse>({
success: true,
pending_job_count: 0,
cache_time: new Date(0), // NB: Epoch is used for vector clock's initial state
refresh_interval_millis: DEFAULT_QUEUE_REFRESH_INTERVAL_MILLIS,
});
const statusIcons = [faHourglass1,faHourglass1,faWarning,faRemove,faTrophy];
// const statusTxt = (which: number, config = {}) => ["animationPending","animationInProgress","animationFailed","animationDead","animationSuccess"].map((str,i) => t(`status.${str}`,config))[which];
const processFail = (fail = "") => {
switch (fail) {
case "face_not_detected": return "Face not detected, try another picture";
default: return "Uknown failure";
}
};
useEffect(() => {
const fetch = async () => {
const response = await GetPendingTtsJobCount();
if (GetPendingTtsJobCountIsOk(response)) {
if (
response.cache_time.getTime() > pending.cache_time.getTime()
) {
pendingSet(response);
}
}
};
// TODO: We're having an outage and need to lower this.
//const interval = setInterval(async () => fetch(), 15000);
const refreshInterval = Math.max(
DEFAULT_QUEUE_REFRESH_INTERVAL_MILLIS,
pending.refresh_interval_millis
);
const interval = setInterval(async () => fetch(), refreshInterval);
fetch();
return () => clearInterval(interval);
}, [pending]);
return inferenceJobs.length ? <div {...{ className: "face-animator-jobs panel" }}>
<h5>{ t("headings.yourJobs") }</h5>
{ inferenceJobs.map((job: any, key: number) => {
return <div {...{ className: "panel face-animator-job", key }}>
<FontAwesomeIcon {...{ className: `job-status-icon job-status-${job.statusIndex}`, icon: statusIcons[job.statusIndex] }}/>
<div {...{ className: "job-details" }}>
<h4>
{ statusTxt(job.statusIndex,{ attemptCount: job.attemptCount || "" }) }
</h4>
<span>
{ job.maybeFailureCategory ? `${ processFail(job.maybeFailureCategory) }` : "" }
</span>
</div>
{
job.maybeResultToken ? <Button {...{
href: `media/${job.maybeResultToken}`,
icon: faChevronRight,
iconFlip: true,
label: t("inputs.viewResult"),
onClick: onSelect
}} />: null
}
</div>
}).reverse()}
</div> : null;
return inferenceJobs.length ? <div {...{ className: "face-animator-jobs panel" }}>
<h5>{ t("core.heading") }</h5>
{ inferenceJobs.map((job: InferenceJob, key: number) => <JobItem {...{ jobStatusDescription, jobType, key, onSelect, t, ...job }} />).reverse() }
</div> : null;
};
@@ -0,0 +1,54 @@
import React from 'react';
import { Button } from 'components/common';
import { FrontendInferenceJobType, InferenceJob } from "@storyteller/components/src/jobs/InferenceJob";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faChevronRight, faCircleQuestion, faHourglass1, faRemove, faSkull, faTrophy, faWarning } from "@fortawesome/free-solid-svg-icons";
interface JobListItem extends InferenceJob {
jobType: FrontendInferenceJobType,
jobStatusDescription?: any,
onSelect?: any
t?: any
}
export default function JobItem({ maybeFailureCategory, maybeResultToken, onSelect, jobState, jobStatusDescription, jobType: inputType, t }: JobListItem) {
const processFail = (fail = "") => {
switch (fail) {
case "face_not_detected": return "Face not detected, try another picture";
default: return "Uknown failure";
}
};
const jobType = FrontendInferenceJobType[inputType];
const jobStatus = jobStatusDescription(jobState);
const jobStatusClass = jobStatus.toLowerCase().replace("_","-");
const statusIcons = [
faCircleQuestion, // UNKNOWN
faHourglass1, // PENDING
faHourglass1, // STARTED
faWarning, // COMPLETE_SUCCESS
faRemove, // COMPLETE_FAILURE
faTrophy, // ATTEMPT_FAILED
faSkull // DEAD
];
return <div {...{ className: `face-animator-job job-status-${jobStatusClass}` }}>
<FontAwesomeIcon {...{ className: "job-status-icon", icon: statusIcons[jobState] }}/>
<div {...{ className: "job-details" }}>
<h6>
{ t(`${jobType}.${jobStatus}`) }
</h6>
<span>
{ maybeFailureCategory ?`${ processFail(maybeFailureCategory) }` : t(`subtitles.${jobStatus}`) }
</span>
</div>
{
maybeResultToken ? <Button {...{
href: `media/${maybeResultToken}`,
icon: faChevronRight,
iconFlip: true,
// label: t("inputs.viewResult"),
onClick: onSelect
}} />: null
}
</div>;
};
@@ -1,6 +1,4 @@
import React from 'react';
import { JobState } from "@storyteller/components/src/jobs/JobStates";
import { InferenceJob } from "@storyteller/components/src/jobs/InferenceJob";
import { InferenceJobsContext } from 'context';
interface Props {
@@ -9,19 +7,7 @@ interface Props {
}
export default function InferenceJobs({ children, byCategory }: Props) {
const processStatus = (job: InferenceJob) => {
switch (job.jobState) {
case JobState.PENDING:
case JobState.UNKNOWN: return 0;
case JobState.STARTED: return 1
case JobState.ATTEMPT_FAILED: return 2;
case JobState.COMPLETE_FAILURE:
case JobState.DEAD: return 3;
case JobState.COMPLETE_SUCCESS: return 4;
default: return -1;
}
};
return <InferenceJobsContext.Provider {...{ value: { byCategory, processStatus } }}>
return <InferenceJobsContext.Provider {...{ value: { byCategory } }}>
{ children }
</InferenceJobsContext.Provider>
};
@@ -1,31 +1,5 @@
import { createContext } from 'react';
import { JobState } from "@storyteller/components/src/jobs/JobStates";
import { FrontendInferenceJobType, InferenceJob } from "@storyteller/components/src/jobs/InferenceJob";
function initInferenceJobsByCategoryMap() : Map<FrontendInferenceJobType, InferenceJob[]> {
let inferenceJobsByCategory = new Map();
inferenceJobsByCategory.set(FrontendInferenceJobType.FaceAnimation, []);
inferenceJobsByCategory.set(FrontendInferenceJobType.TextToSpeech, []);
inferenceJobsByCategory.set(FrontendInferenceJobType.VoiceConversion, []);
return inferenceJobsByCategory;
};
interface InferenceJobsContext { byCategory?: any }
const processStatus = (job: InferenceJob) => {
switch (job.jobState) {
case JobState.PENDING:
case JobState.UNKNOWN: return 0;
case JobState.STARTED: return 1
case JobState.ATTEMPT_FAILED: return 2;
case JobState.COMPLETE_FAILURE:
case JobState.DEAD: return 3;
case JobState.COMPLETE_SUCCESS: return 4;
default: return -1;
}
};
// export default createContext({
// byCategory: initInferenceJobsByCategoryMap(),
// nahmean: false
// });
export default createContext({ byCategory: initInferenceJobsByCategoryMap(), processStatus });
export default createContext<InferenceJobsContext>({ });
@@ -1,15 +1,12 @@
import { useContext } from 'react';
import { JobState } from "@storyteller/components/src/jobs/JobStates";
import { FrontendInferenceJobType } from "@storyteller/components/src/jobs/InferenceJob";
import { InferenceJobsContext } from 'context';
export default function useInferenceJobs(jobType: FrontendInferenceJobType) {
const { byCategory, processStatus } = useContext(InferenceJobsContext);
const { byCategory } = useContext(InferenceJobsContext);
return {
inferenceJobs: (byCategory.get(jobType) || []).map((job,i) => ({
...job!,
statusIndex: processStatus(job!)
})),
processStatus
inferenceJobs: (byCategory?.get(jobType) || []),
jobStatusDescription: (jobState: JobState) => Object.keys(JobState).filter(key => isNaN(Number(key)))[jobState]
};
};
@@ -19,10 +19,8 @@ import {
// EnqueueFaceAnimationIsSuccess,
// EnqueueFaceAnimationRequest,
} from "@storyteller/components/src/api/face_animation/EnqueueFaceAnimation";
import FaceAnimatorSubViews from "./sub_views";
import FaceAnimatorTitle from "./FaceAnimatorTitle";
import FaceAnimatorInput from "./FaceAnimatorInput";
import FaceAnimatorWorking from "./FaceAnimatorWorking";
import FaceAnimatorSuccess from "./FaceAnimatorSuccess";
import InferenceJobsList from "components/layout/InferenceJobsList";
import { FaceAnimatorCore } from "./FaceAnimatorTypes";
import { BasicVideo } from "components/common";
@@ -135,13 +133,18 @@ export default function FaceAnimator({ enqueueInferenceJob, sessionSubscription
leave: { opacity: 0, position: "absolute" },
});
const statusTxt = (which: number, config = {}) => ["animationPending","animationInProgress","animationFailed","animationDead","animationSuccess"].map((str,i) => t(`status.${str}`,config))[which];
const failures = (fail = "") => {
switch (fail) {
case "face_not_detected": return "Face not detected, try another picture";
default: return "Uknown failure";
}
};
return <div {...{ className: "container-panel pt-4" }}>
<div {...{ className: "panel face-animator-main" }}>
<FaceAnimatorTitle {...headerProps} />
{transitions((style, i) => {
const Page = [FaceAnimatorInput, FaceAnimatorWorking, FaceAnimatorSuccess ][page];
const Page = FaceAnimatorSubViews[page];
return Page ? <Page
{...{
audioProps,
@@ -168,10 +171,9 @@ export default function FaceAnimator({ enqueueInferenceJob, sessionSubscription
})}
</div>
<InferenceJobsList {...{
t,
failures,
onSelect: () => Analytics.voiceConversionClickDownload(),
jobType: FrontendInferenceJobType.FaceAnimation,
statusTxt
}}/>
<div {...{ className: "face-animator-mobile-sample" }}>
<BasicVideo {...{ src: "/videos/face-animator-instruction-en.mp4" }} />
@@ -1,90 +0,0 @@
import React, { useEffect, useState } from 'react';
// import { a } from '@react-spring/web';
import {
GetPendingTtsJobCount,
GetPendingTtsJobCountIsOk,
GetPendingTtsJobCountSuccessResponse,
} from "@storyteller/components/src/api/tts/GetPendingTtsJobCount";
// import { springs } from "resources";
import { useInferenceJobs } from "hooks";
import { Button } from 'components/common';
import { Analytics } from "common/Analytics";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faChevronRight, faHourglass1, faRemove, faTrophy, faWarning } from "@fortawesome/free-solid-svg-icons";
import { FrontendInferenceJobType } from "@storyteller/components/src/jobs/InferenceJob";
const DEFAULT_QUEUE_REFRESH_INTERVAL_MILLIS = 15000;
export default function FaceAnimatorJobs({ t }: { t: any }) {
const { inferenceJobs = [] } = useInferenceJobs(FrontendInferenceJobType.FaceAnimation);
const [pending, pendingSet] = useState<GetPendingTtsJobCountSuccessResponse>({
success: true,
pending_job_count: 0,
cache_time: new Date(0), // NB: Epoch is used for vector clock's initial state
refresh_interval_millis: DEFAULT_QUEUE_REFRESH_INTERVAL_MILLIS,
});
const statusIcons = [faHourglass1,faHourglass1,faWarning,faRemove,faTrophy];
const statusTxt = (which: number, config = {}) => ["animationPending","animationInProgress","animationFailed","animationDead","animationSuccess"].map((str,i) => t(`status.${str}`,config))[which];
const processFail = (fail = "") => {
switch (fail) {
case "face_not_detected": return "Face not detected, try another picture";
default: return "Uknown failure";
}
};
// const transitions = useTransition(inferenceJobs, { // not today
// ...springs.soft,
// from: { opacity: 0, position: "absolute" },
// enter: { opacity: 1, position: "relative" },
// leave: { opacity: 0, position: "absolute" },
// });
useEffect(() => {
const fetch = async () => {
const response = await GetPendingTtsJobCount();
if (GetPendingTtsJobCountIsOk(response)) {
if (
response.cache_time.getTime() > pending.cache_time.getTime()
) {
pendingSet(response);
}
}
};
// TODO: We're having an outage and need to lower this.
//const interval = setInterval(async () => fetch(), 15000);
const refreshInterval = Math.max(
DEFAULT_QUEUE_REFRESH_INTERVAL_MILLIS,
pending.refresh_interval_millis
);
const interval = setInterval(async () => fetch(), refreshInterval);
fetch();
return () => clearInterval(interval);
}, [pending]);
return inferenceJobs.length ? <div {...{ className: "face-animator-jobs panel" }}>
<h5>{ t("headings.yourJobs") }</h5>
{ inferenceJobs.map((job, key) => {
return <div {...{ className: "panel face-animator-job", key }}>
<FontAwesomeIcon {...{ className: `job-status-icon job-status-${job.statusIndex}`, icon: statusIcons[job.statusIndex] }}/>
<div {...{ className: "job-details" }}>
<h4>
{ statusTxt(job.statusIndex,{ attemptCount: job.attemptCount || "" }) }
</h4>
<span>
{ job.maybeFailureCategory ? `${ processFail(job.maybeFailureCategory) }` : "" }
</span>
</div>
{
job.maybeResultToken ? <Button {...{
href: `media/${job.maybeResultToken}`,
icon: faChevronRight,
iconFlip: true,
label: t("inputs.viewResult"),
onClick:() => Analytics.voiceConversionClickDownload()
}} />: null
}
</div>
}).reverse()}
</div> : null;
};
@@ -1,7 +1,7 @@
import React from "react";
import { animated } from "@react-spring/web";
import { TempAudioPlayer, AudioBlobPreview, AudioInput, BasicVideo, Checkbox, ImageInput, SegmentButtons } from "components/common";
import { FaceAnimatorSlide } from "./FaceAnimatorTypes";
import { FaceAnimatorSlide } from "../FaceAnimatorTypes";
export default function FaceAnimatorInput({ audioProps, imageProps, frameDimensions, frameDimensionsChange, disableFaceEnhancement, disableFaceEnhancementChange, preferPresetAudio, preferPresetAudioSet, presetAudio, still, stillChange, toggle, style, t, removeWatermark, removeWatermarkChange, }: FaceAnimatorSlide) {
return <animated.div {...{ className: "lipsync-editor row", style }}>
@@ -1,6 +1,6 @@
import React from 'react';
import { a } from '@react-spring/web';
import { FaceAnimatorSlide } from "./FaceAnimatorTypes";
import { FaceAnimatorSlide } from "../FaceAnimatorTypes";
export default function FaceAnimatorSuccess({ style, t }: FaceAnimatorSlide) {
return <a.div {...{ className: "lipsync-success", style }}>
@@ -2,7 +2,7 @@ import React from 'react';
import { a, useTransition } from "@react-spring/web";
import { Spinner } from "components/common";
import { springs } from "resources";
import { FaceAnimatorSlide } from "./FaceAnimatorTypes";
import { FaceAnimatorSlide } from "../FaceAnimatorTypes";
export default function FaceAnimatorWorking({ audioProps, imageProps, index, style, t }: FaceAnimatorSlide) {
const workStatus = [
@@ -0,0 +1,7 @@
import FaceAnimatorInput from "./FaceAnimatorInput";
import FaceAnimatorWorking from "./FaceAnimatorWorking";
import FaceAnimatorSuccess from "./FaceAnimatorSuccess";
const FaceAnimatorSubViews = [FaceAnimatorInput, FaceAnimatorWorking, FaceAnimatorSuccess];
export default FaceAnimatorSubViews;
@@ -1,12 +1,6 @@
import React, { useState } from "react";
import { Redirect, useHistory, useLocation } from "react-router-dom";
import {
faPenToSquare,
faPlus,
faRightToBracket,
faStar,
faWaveform,
} from "@fortawesome/pro-solid-svg-icons";
import { faPenToSquare, faPlus, faRightToBracket, faStar, faWaveform } from "@fortawesome/pro-solid-svg-icons";
import InferenceJobsList from "components/layout/InferenceJobsList";
import { useLocalize } from "hooks";
import Panel from "components/common/Panel";
@@ -149,14 +143,12 @@ function VoiceDesignerMainPage() {
};
});
const statusTxt = (status: number, config: any) =>
[
"Voice pending...",
"Voice in progress",
"Voice failed",
"Voice dead",
"Voice created successfully",
][status];
const failures = (fail = "") => {
switch (fail) {
// case "face_not_detected": return "Face not detected, try another picture"; // voice designer can have failure states too!
default: return "Uknown failure";
}
};
const createVoiceButton = {
label: `Create new voice`,
@@ -192,9 +184,9 @@ function VoiceDesignerMainPage() {
<>
<InferenceJobsList
{...{
failures,
jobType: FrontendInferenceJobType.VoiceDesignerCreateVoice,
t,
statusTxt,
t
}}
/>
<Panel mb={true}>