SpeciesFileGroup/taxonworks

View on GitHub
app/javascript/vue/tasks/field_occurrences/new_field_occurrences/components/HeaderBar.vue

Summary

Maintainability
Test Coverage
<template>
  <Navbar>
    <div class="flex-separate full_width">
      <div class="middle margin-small-left">
        <Autocomplete
          url="/field_occurrences/autocomplete"
          param="term"
          placeholder="Search"
          label="label_html"
          :legend="
            settings.isLoading
              ? 'Loading, please wait...'
              : 'Saving, please wait...'
          "
          clear-after
          @get-item="({ id }) => loadForms(id)"
        />
        <span
          v-if="foStore.fieldOccurrence.id"
          class="margin-small-left"
          v-html="foStore.fieldOccurrence.object_tag"
        />
        <span
          class="margin-small-left"
          v-else
        >
          New record
        </span>
        <div
          v-if="foStore.fieldOccurrence.id"
          class="horizontal-left-content margin-small-left gap-small"
        >
          <RadialAnnotator :global-id="foStore.fieldOccurrence.global_id" />
          <RadialObject :global-id="foStore.fieldOccurrence.global_id" />
        </div>
      </div>
      <ul class="context-menu no_bullets">
        <li class="horizontal-right-content gap-small">
          <span
            v-if="isUnsaved"
            class="medium-icon margin-small-right"
            title="You have unsaved changes."
            data-icon="warning"
          />
          <VRecent @selected="({ id }) => loadForms(id)" />
          <VBtn
            color="create"
            medium
            :disabled="!validateSave"
            @click="save"
          >
            Save
          </VBtn>
          <VBtn
            medium
            color="create"
            :disabled="!validateSave"
            @click="saveAndNew"
          >
            Save and new
          </VBtn>
          <VBtn
            medium
            color="primary"
            @click="reset"
          >
            New
          </VBtn>
        </li>
      </ul>
    </div>
  </Navbar>
  <VSpinner
    v-if="settings.isSaving || settings.isLoading"
    full-screen
  />
</template>

<script setup>
import RadialAnnotator from '@/components/radials/annotator/annotator.vue'
import RadialObject from '@/components/radials/object/radial.vue'
import Autocomplete from '@/components/ui/Autocomplete.vue'
import Navbar from '@/components/layout/NavBar.vue'
import useFieldOccurrenceStore from '../store/fieldOccurrence.js'
import useCitationStore from '../store/citations.js'
import useCEStore from '@/components/Form/FormCollectingEvent/store/collectingEvent.js'
import useDeterminationStore from '../store/determinations.js'
import useSettingStore from '../store/settings.js'
import useBiocurationStore from '../store/biocurations.js'
import useIdentifierStore from '../store/identifier.js'
import VBtn from '@/components/ui/VBtn/index.vue'
import VRecent from './Recent.vue'
import useHotkey from 'vue3-hotkey'
import platformKey from '@/helpers/getPlatformKey'
import VSpinner from '@/components/ui/VSpinner.vue'
import { setParam } from '@/helpers'
import { computed, onBeforeMount, watch, ref } from 'vue'
import { FIELD_OCCURRENCE } from '@/constants'

const foStore = useFieldOccurrenceStore()
const settings = useSettingStore()
const citationStore = useCitationStore()
const determinationStore = useDeterminationStore()
const ceStore = useCEStore()
const biocurationStore = useBiocurationStore()
const identifierStore = useIdentifierStore()
const fieldOccurrenceId = computed(() => foStore.fieldOccurrence.id)
const isUnsaved = computed(
  () =>
    citationStore.hasUnsaved ||
    determinationStore.hasUnsaved ||
    biocurationStore.hasUnsaved ||
    foStore.fieldOccurrence.isUnsaved ||
    ceStore.isUnsaved ||
    identifierStore.isUnsaved
)

const validateSave = computed(() => {
  return (
    determinationStore.determinations.length &&
    (ceStore.isUnsaved || ceStore.collectingEvent.id)
  )
})

async function save() {
  try {
    settings.isSaving = true
    const ce = ceStore.isUnsaved
      ? (await ceStore.save()).body
      : ceStore.collectingEvent

    foStore.fieldOccurrence.collecting_event_id = ce.id

    const { body } = await foStore.save()
    const args = {
      objectId: body.id,
      objectType: FIELD_OCCURRENCE
    }
    const requests = [
      citationStore.save(args),
      determinationStore.load(args),
      biocurationStore.save(args),
      identifierStore.save(args)
    ]

    return Promise.all(requests).then((_) => {
      settings.isSaving = false
      TW.workbench.alert.create(
        'Field occurrence was successfully saved.',
        'notice'
      )
    })
  } catch (e) {}
}

function reset() {
  const { locked } = settings

  foStore.$reset()

  if (!locked.collectingEvent) {
    ceStore.reset()
  }

  if (locked.biocurations) {
    biocurationStore.resetIds()
  } else {
    biocurationStore.list = []
  }

  identifierStore.reset({ keepNamespace: locked.namespace })
  determinationStore.reset({ keepRecords: locked.taxonDeterminations })
  citationStore.reset({ keepRecords: locked.citations })
}

async function saveAndNew() {
  await save()
  reset()
}

watch(fieldOccurrenceId, (newVal, oldVal) => {
  if (newVal !== oldVal) {
    setParam('/tasks/field_occurrences/new_field_occurrences', {
      field_occurrence_id: newVal,
      collecting_event_id: undefined,
      otu_id: undefined
    })
  }
})

onBeforeMount(() => {
  const urlParams = new URLSearchParams(window.location.search)
  const id = urlParams.get('field_occurrence_id')
  const ceId = urlParams.get('collecting_event_id')

  if (/^\d+$/.test(id)) {
    loadForms(id)
  }

  if (ceId) {
    ceStore.load(ceId)
  }
})

async function loadForms(id) {
  const args = {
    objectId: id,
    objectType: FIELD_OCCURRENCE
  }

  settings.isLoading = true

  foStore.load(id).then(async ({ body }) => {
    const ceId = body.collecting_event_id

    if (ceId) {
      await ceStore.load(ceId)
    }
  })

  const requests = [
    determinationStore.load(args),
    biocurationStore.load(args),
    citationStore.load(args),
    identifierStore.load(args)
  ]

  Promise.all(requests).then((_) => {
    settings.isLoading = false
  })
}

const hotkeys = ref([
  {
    keys: [platformKey(), 's'],
    preventDefault: true,
    handler() {
      if (validateSave.value) {
        save()
      }
    }
  },
  {
    keys: [platformKey(), 'n'],
    preventDefault: true,
    handler() {
      if (validateSave.value) {
        saveAndNew()
      }
    }
  },
  {
    keys: [platformKey(), 'r'],
    preventDefault: true,
    handler() {
      reset()
    }
  }
])

const stop = useHotkey(hotkeys.value)

TW.workbench.keyboard.createLegend(
  `${platformKey()}+s`,
  'Save',
  'New field occurrence'
)
TW.workbench.keyboard.createLegend(
  `${platformKey()}+n`,
  'Save and new',
  'New field occurrence'
)
TW.workbench.keyboard.createLegend(
  `${platformKey()}+r`,
  'Reset all',
  'New field occurrence'
)
</script>