6
0

media-control.vue 5.2 KB

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