media-control.vue 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. <template>
  2. <div class="media-control">
  3. <button-input type="transparent"
  4. style="color: var(--on_error)"
  5. :class="{disabled: !hasNext}"
  6. @click="$emit('control', !control)">
  7. {{ control ? '&#9660;' : '&#9650;' }}
  8. </button-input>
  9. <button-input type="transparent"
  10. style="color: var(--on_error)"
  11. :class="{disabled: !hasPrevious}"
  12. @click="previous">
  13. &lt;
  14. </button-input>
  15. <button-row class="media-control">
  16. <button-input type="primary"
  17. style="color: var(--on_error)">
  18. Reset
  19. </button-input>
  20. <button-input type="primary"
  21. style="color: var(--on_error)"
  22. @click="$emit('predict', 'current')">
  23. Predict
  24. </button-input>
  25. </button-row>
  26. <button-input type="transparent"
  27. style="color: var(--on_error)"
  28. :class="{disabled: !hasNext}"
  29. @click="next">
  30. &gt;
  31. </button-input>
  32. <button-input type="transparent" v-if="model.supports.includes('labeled-images')">
  33. <img alt="label" src="@/assets/icons/tag.svg"
  34. :class="{tagged: currentLabel}"
  35. @touchstart.stop @mousedown.stop
  36. @click.stop="showLabelSelection = true">
  37. </button-input>
  38. <select v-if="showLabelSelection"
  39. @touchstart.stop @mousedown.stop
  40. @change="labelSelf"
  41. @focusout="showLabelSelection = false">
  42. <option value="">None</option>
  43. <option v-for="label in labelList"
  44. :key="label.id"
  45. :value="label.id"
  46. :selected="label === currentLabel">
  47. {{ label.name }}
  48. </option>
  49. </select>
  50. </div>
  51. </template>
  52. <script>
  53. import ButtonInput from "@/components/base/button-input";
  54. import ButtonRow from "@/components/base/button-row";
  55. export default {
  56. name: "media-control",
  57. components: {ButtonRow, ButtonInput},
  58. props: ['hasPrevious', 'hasNext', 'control', 'data', 'project', 'model', 'socket'],
  59. data: function () {
  60. return {
  61. showLabelSelection: false
  62. }
  63. },
  64. computed: {
  65. mediaUrl: function () {
  66. return this.socket.media(this.project.id, this.data.id);
  67. },
  68. labelList: function () {
  69. return Object.keys(this.project.labels).map(key => this.project.labels[key]);
  70. },
  71. currentLabel: function () {
  72. const predictions = Object.keys(this.data.predictionResults).map(k => this.data.predictionResults[k]);
  73. for (let result of predictions) {
  74. if (!('x' in result || 'y' in result || 'w' in result || 'h' in result)) {
  75. return this.project.labels[result.label];
  76. }
  77. }
  78. return false;
  79. }
  80. },
  81. methods: {
  82. previous: function () {
  83. if (this.hasPrevious)
  84. this.$emit('previous', null);
  85. },
  86. next: function () {
  87. if (this.hasNext)
  88. this.$emit('next', null);
  89. },
  90. labelSelf: function (event) {
  91. const options = event.target.options;
  92. const option = options[options.selectedIndex];
  93. const value = option.value;
  94. this.socket.post(this.mediaUrl, {
  95. label: value ? value : false
  96. });
  97. this.showLabelSelection = false;
  98. }
  99. }
  100. }
  101. </script>
  102. <style scoped>
  103. .media-control {
  104. position: relative;
  105. display: flex;
  106. justify-content: center;
  107. align-items: center;
  108. margin: 0 0.5rem;
  109. }
  110. .disabled {
  111. opacity: 0.4;
  112. }
  113. img {
  114. filter: invert(1);
  115. opacity: 0.4;
  116. }
  117. img.tagged {
  118. opacity: 1;
  119. }
  120. select {
  121. position: absolute;
  122. width: 100%;
  123. height: 100%;
  124. }
  125. </style>