You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

120 lines
2.8 KiB

  1. <template lang="pug">
  2. extends ./annotation.pug
  3. block annotation-area
  4. div.card.has-text-weight-bold.has-text-white.has-background-royalblue
  5. div.card-content
  6. div.content
  7. audio(
  8. ref="player"
  9. controls
  10. v-bind:src="audioFile"
  11. v-shortkey="{ playOrPauseAudio: ['alt', 'p'] }"
  12. v-on:shortkey="playOrPauseAudio"
  13. )
  14. section
  15. header.header
  16. textarea.textarea(
  17. v-model="transcription"
  18. v-debounce="syncTranscription"
  19. type="text"
  20. placeholder="Transcribe audio here..."
  21. autofocus
  22. )
  23. </template>
  24. <style scoped>
  25. audio {
  26. height: 3em;
  27. width: 100%;
  28. display: block;
  29. margin: 0 auto;
  30. }
  31. </style>
  32. <script>
  33. import annotationMixin from './annotationMixin';
  34. import HTTP from './http';
  35. export default {
  36. mixins: [annotationMixin],
  37. data: () => ({
  38. transcription: '',
  39. isAudioPlaying: false,
  40. }),
  41. computed: {
  42. annotation() {
  43. const annotations = this.annotations[this.pageNumber];
  44. return annotations && annotations[0];
  45. },
  46. audioFile() {
  47. const docs = this.docs[this.pageNumber];
  48. return docs && docs.text;
  49. },
  50. },
  51. watch: {
  52. annotations() {
  53. this.updateTranscription();
  54. },
  55. pageNumber() {
  56. this.updateTranscription();
  57. },
  58. },
  59. methods: {
  60. async playOrPauseAudio() {
  61. const player = this.$refs.player;
  62. if (this.isAudioPlaying) {
  63. player.pause();
  64. this.isAudioPlaying = false;
  65. } else {
  66. await player.play();
  67. this.isAudioPlaying = true;
  68. }
  69. },
  70. updateTranscription() {
  71. const text = this.annotation && this.annotation.text;
  72. this.transcription = text || '';
  73. },
  74. async syncTranscription(text) {
  75. const docId = this.docs[this.pageNumber].id;
  76. const annotations = this.annotations[this.pageNumber];
  77. const hasTranscription = text.trim().length > 0;
  78. if (!hasTranscription && !this.annotation) {
  79. return;
  80. }
  81. if (!hasTranscription && this.annotation) {
  82. await HTTP.delete(`docs/${docId}/annotations/${this.annotation.id}`);
  83. annotations.splice(0, annotations.length);
  84. return;
  85. }
  86. if (this.annotation) {
  87. const annotation = { ...this.annotation, text };
  88. await HTTP.put(`docs/${docId}/annotations/${this.annotation.id}`, annotation);
  89. } else {
  90. const annotation = { text };
  91. const response = await HTTP.post(`docs/${docId}/annotations`, annotation);
  92. annotations.unshift({ ...response.data, text });
  93. }
  94. },
  95. async submit() {
  96. const state = this.getState();
  97. this.url = `docs?q=${this.searchQuery}&speech2text_annotations__isnull=${state}&offset=${this.offset}&ordering=${this.ordering}`;
  98. await this.search();
  99. this.pageNumber = 0;
  100. },
  101. },
  102. };
  103. </script>