SpeciesFileGroup/taxonworks

View on GitHub
app/javascript/vue/tasks/digitize/components/biologicalAssociation/main.vue

Summary

Maintainability
Test Coverage
<template>
  <div>
    <block-layout :warning="!list.find((item) => item['id'])">
      <template #header>
        <h3>Biological Associations</h3>
      </template>
      <template #body>
        <div class="separate-bottom">
          <div class="flex-separate middle">
            <h3
              v-if="biologicalRelationship"
              class="relationship-title"
            >
              <template v-if="flip">
                <span
                  v-for="item in biologicalRelationship.object_biological_properties"
                  :key="item.id"
                  class="separate-right background-info"
                  v-html="item.name"
                />
                <span v-html="biologicalRelationship.inverted_name" />
                <span
                  v-for="item in biologicalRelationship.subject_biological_properties"
                  :key="item.id"
                  class="separate-left background-info"
                  v-html="item.name"
                />
              </template>
              <template v-else>
                <span
                  v-for="item in biologicalRelationship.subject_biological_properties"
                  :key="item.id"
                  class="separate-right background-info"
                  v-html="item.name"
                />
                <span>{{
                  biologicalRelationship.hasOwnProperty('label')
                    ? biologicalRelationship.label
                    : biologicalRelationship.name
                }}</span>
                <span
                  v-for="item in biologicalRelationship.object_biological_properties"
                  :key="item.id"
                  class="separate-left background-info"
                  v-html="item.name"
                />
              </template>
              <button
                v-if="biologicalRelationship.inverted_name"
                class="separate-left button button-default flip-button"
                type="button"
                @click="flip = !flip"
              >
                Flip
              </button>
              <span
                @click="
                  () => {
                    biologicalRelationship = undefined
                    flip = false
                  }
                "
                class="separate-left"
                data-icon="reset"
              />
            </h3>
            <h3
              class="subtle relationship-title"
              v-else
            >
              Choose relationship
            </h3>
            <lock-component
              v-model="settings.locked.biological_association.relationship"
            />
          </div>
          <div class="flex-separate middle">
            <h3
              v-if="biologicalRelation"
              class="relation-title"
            >
              <span v-html="displayRelated" />
              <span
                @click="biologicalRelation = undefined"
                class="separate-left"
                data-icon="reset"
              />
            </h3>
            <h3
              v-else
              class="subtle relation-title"
            >
              Choose relation
            </h3>
            <lock-component
              v-model="settings.locked.biological_association.related"
            />
          </div>
        </div>
        <div
          v-if="!biologicalRelationship"
          class="horizontal-left-content full_width"
        >
          <biological
            class="separate-bottom"
            @select="biologicalRelationship = $event"
          />
        </div>
        <div class="horizontal-left-content">
          <related
            v-if="!biologicalRelation"
            class="separate-bottom separate-top"
            @select="biologicalRelation = $event"
          />
        </div>
        <FormCitation
          v-model="citation"
          class="separate-top"
          :klass="BIOLOGICAL_ASSOCIATION"
          original
          @source="addLabel"
        />

        <div class="separate-top">
          <button
            type="button"
            :disabled="!validateFields"
            @click="addAssociation"
            class="normal-input button button-default"
          >
            Add
          </button>
        </div>
        <table-list
          class="separate-top"
          :list="list"
          @delete="removeBiologicalRelationship"
        />
      </template>
    </block-layout>
  </div>
</template>
<script>
import Biological from './biological.vue'
import Related from './related.vue'
import FormCitation from '@/components/Form/FormCitation.vue'
import TableList from './table.vue'
import BlockLayout from '@/components/layout/BlockLayout.vue'
import LockComponent from '@/components/ui/VLock/index.vue'
import makeCitation from '@/factory/Citation.js'
import { BIOLOGICAL_ASSOCIATION } from '@/constants/index'
import { GetterNames } from '../../store/getters/getters.js'
import { MutationNames } from '../../store/mutations/mutations'
import { BiologicalAssociation } from '@/routes/endpoints'

export default {
  components: {
    Biological,
    Related,
    FormCitation,
    BlockLayout,
    TableList,
    LockComponent
  },

  computed: {
    validateFields() {
      return this.biologicalRelationship && this.biologicalRelation
    },

    displayRelated() {
      return (
        this.biologicalRelation?.object_tag ||
        this.biologicalRelation?.label_html
      )
    },

    collectionObject() {
      return this.$store.getters[GetterNames.GetCollectionObject]
    },

    settings: {
      get() {
        return this.$store.getters[GetterNames.GetSettings]
      },
      set(value) {
        this.$store.commit(MutationNames.SetSettings, value)
      }
    },

    list: {
      get() {
        return this.$store.getters[GetterNames.GetBiologicalAssociations]
      },
      set(value) {
        this.$store.commit(MutationNames.SetBiologicalAssociations, value)
      }
    }
  },

  data() {
    return {
      biologicalRelationship: undefined,
      biologicalRelation: undefined,
      citation: makeCitation(),
      queueAssociations: [],
      flip: false,
      BIOLOGICAL_ASSOCIATION
    }
  },

  watch: {
    collectionObject(newVal) {
      if (!this.settings.locked.biological_association.relationship) {
        this.biologicalRelationship = undefined
      }
      if (!this.settings.locked.biological_association.related) {
        this.biologicalRelation = undefined
      }
    }
  },

  methods: {
    addLabel(source) {
      this.citation.source = source
    },

    addAssociation() {
      const data = {
        biological_relationship: this.biologicalRelationship,
        object: this.biologicalRelation,
        biological_relationship_id: this.biologicalRelationship.id,
        biological_association_object_id: this.biologicalRelation.id,
        biological_association_object_type: this.biologicalRelation.type,
        origin_citation_attributes: this.citation
      }

      this.list.push(data)

      if (!this.settings.locked.biological_association.relationship) {
        this.biologicalRelationship = undefined
      }
      if (!this.settings.locked.biological_association.related) {
        this.biologicalRelation = undefined
      }

      this.citation = makeCitation()
    },

    removeBiologicalRelationship(index) {
      const biologicalRelationship = this.list[index]

      if (biologicalRelationship.id) {
        BiologicalAssociation.destroy(biologicalRelationship.id)
      }

      this.list.splice(index, 1)
    }
  }
}
</script>
<style lang="scss">
.radial-annotator {
  .biological_relationships_annotator {
    overflow-y: scroll;
    .flip-button {
      min-width: 30px;
    }
    .relationship-title {
      margin-left: 1em;
    }
    .relation-title {
      margin-left: 2em;
    }
    .switch-radio {
      label {
        min-width: 95px;
      }
    }
    .background-info {
      padding: 3px;
      padding-left: 6px;
      padding-right: 6px;
      border-radius: 3px;
      background-color: #ded2f9;
    }
    textarea {
      padding-top: 14px;
      padding-bottom: 14px;
      width: 100%;
      height: 100px;
    }
    .pages {
      width: 86px;
    }
    .vue-autocomplete-input,
    .vue-autocomplete {
      width: 376px;
    }
  }
}
</style>