1
1

project-labels-window.vue 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. <template>
  2. <div class="project-labels-window">
  3. <div class="label" v-for="label in labels" :key="label.id">
  4. <editable-headline :value="label.name"
  5. @change="editLabel(label.id, $event)"
  6. @remove="removeLabel(label.id)">{{ label.name }}
  7. </editable-headline>
  8. <media-selector v-if="labeledImages[label.id].length > 0"
  9. :project-id="currentProject.id"
  10. :media="labeledImages[label.id]"
  11. current="-1"
  12. :socket="socket"></media-selector>
  13. <div v-else
  14. class="no-elements">
  15. No labeled images found...
  16. </div>
  17. </div>
  18. <div class="label">
  19. <input-group>
  20. <text-input placeholder="New Label"
  21. v-model="createLabelValue"
  22. @enter="createLabel"/>
  23. <button-input type="primary" @click="createLabel">
  24. create
  25. </button-input>
  26. </input-group>
  27. </div>
  28. </div>
  29. </template>
  30. <script>
  31. import TextInput from "@/components/base/text-input";
  32. import MediaSelector from "@/components/media/media-selector";
  33. import EditableHeadline from "@/components/base/editable-headline";
  34. import ButtonInput from "@/components/base/button-input";
  35. import InputGroup from "@/components/base/input-group";
  36. export default {
  37. name: "project-labels-window",
  38. components: {InputGroup, ButtonInput, EditableHeadline, MediaSelector, TextInput},
  39. props: ['currentProject', 'socket'],
  40. data: function () {
  41. return {
  42. createLabelValue: ''
  43. }
  44. },
  45. computed: {
  46. labels: function () {
  47. let labels = Object.keys(this.currentProject.labels)
  48. .map(e => this.currentProject.labels[e]);
  49. labels.sort((a, b) => a.name < b.name ? -1 : +1);
  50. return labels;
  51. },
  52. labeledImages: function () {
  53. const result = {};
  54. for (let label of this.labels)
  55. result[label.id] = [];
  56. for (let image of Object.values(this.currentProject.data)) {
  57. for (let prediction of Object.values(image['predictionResults'])) {
  58. if ('label' in prediction
  59. && prediction.label in result
  60. && !result[prediction.label].includes(image)) {
  61. result[prediction.label].push(image);
  62. }
  63. }
  64. }
  65. return result;
  66. }
  67. },
  68. methods: {
  69. createLabel: function () {
  70. if (!this.createLabelValue)
  71. return;
  72. this.socket.post('/projects/' + this.currentProject.id + '/labels', {name: this.createLabelValue});
  73. this.createLabelValue = '';
  74. },
  75. editLabel: function (id, value) {
  76. this.socket.post('/projects/' + this.currentProject.id + '/labels/' + id, {name: value});
  77. },
  78. removeLabel: function (id) {
  79. this.socket.post('/projects/' + this.currentProject.id + '/labels/' + id, {delete: true});
  80. }
  81. }
  82. }
  83. </script>
  84. <style scoped>
  85. .project-labels-window {
  86. padding: 1rem;
  87. overflow: auto;
  88. }
  89. .label {
  90. margin-bottom: 1rem;
  91. }
  92. /deep/ .element {
  93. border: none;
  94. }
  95. /deep/ .element:not(:first-child) {
  96. margin-left: 0.1rem;
  97. }
  98. /deep/ .element:not(:last-child) {
  99. margin-right: 0.1rem;
  100. }
  101. .no-elements {
  102. margin-top: 0.5rem;
  103. }
  104. </style>