app/javascript/vue/tasks/otu/browse/app.vue
<template>
<div id="browse-otu">
<select-otu
:otus="otuList"
@selected="loadOtu"
/>
<spinner-component
:full-screen="true"
legend="Loading..."
:logo-size="{ width: '100px', height: '100px' }"
v-if="isLoading"
/>
<div class="flex-separate middle">
<h1>Browse OTUs</h1>
<div class="horizontal-left-content">
<ul
v-if="navigate"
class="no_bullets"
>
<li v-for="item in navigate.previous_otus">
<a
:href="`/tasks/otus/browse?otu_id=${item.id}`"
v-html="item.object_tag"
/>
</li>
</ul>
<template v-if="otu">
<autocomplete
class="float_right separate-left separate-right autocomplete-search-bar"
url="/otus/autocomplete"
placeholder="Search a otu"
param="term"
:clear-after="true"
@getItem="loadOtu"
label="label_html"
/>
<ul
v-if="navigate"
class="no_bullets"
>
<li v-for="item in navigate.next_otus">
<a
:href="`/tasks/otus/browse?otu_id=${item.id}`"
v-html="item.object_tag"
/>
</li>
</ul>
</template>
</div>
</div>
<template v-if="otu">
<header-bar
class="separate-bottom"
:menu="menu"
:otu="otu"
/>
<div class="separate-top separate-bottom"></div>
<draggable
handle=".handle"
:item-key="(element) => element"
v-model="preferences.sections"
>
<template #item="{ element }">
<component
v-if="showForRanks(componentNames[element])"
class="separate-bottom full_width"
:title="componentNames[element].title"
:status="componentNames[element].status"
:otu="otu"
:is="element"
/>
</template>
</draggable>
</template>
<search-otu
v-else
class="container"
@select="loadOtu"
/>
</div>
</template>
<script>
import HeaderBar from './components/HeaderBar'
import SpinnerComponent from '@/components/ui/VSpinner'
import ImageGallery from './components/gallery/Main'
import ContentComponent from './components/Content'
import AssertedDistribution from './components/AssertedDistribution'
import BiologicalAssociations from './components/BiologicalAssociations'
import AnnotationsComponent from './components/Annotations'
import NomenclatureHistory from './components/timeline/Timeline.vue'
import Distribution from './components/Distribution.vue'
import CollectingEventSection from './components/collectingEvent/CollectingEventSection.vue'
import Descendants from './components/Descendants/Descendants.vue'
import CollectionObjects from './components/CollectionObjects'
import TypeSpecimens from './components/specimens/Type'
import TypeSection from './components/TypeSection.vue'
import CommonNames from './components/CommonNames'
import DescriptionComponent from './components/Description.vue'
import CoordinateOtus from './components/coordinate/CoordinateOtus.vue'
import Autocomplete from '@/components/ui/Autocomplete'
import SearchOtu from './components/SearchOtu'
import Draggable from 'vuedraggable'
import SelectOtu from './components/selectOtu'
import { ActionNames } from './store/actions/actions'
import { TaxonName, Otu, User } from '@/routes/endpoints'
import { GetterNames } from './store/getters/getters'
import { MutationNames } from './store/mutations/mutations'
import COMPONENT_NAMES from './const/componentNames'
import ShowForThisGroup from '@/tasks/nomenclature/new_taxon_name/helpers/showForThisGroup.js'
export default {
components: {
SearchOtu,
HeaderBar,
ImageGallery,
SpinnerComponent,
ContentComponent,
DescriptionComponent,
AssertedDistribution,
BiologicalAssociations,
AnnotationsComponent,
NomenclatureHistory,
CollectingEventSection,
CollectionObjects,
TypeSpecimens,
CommonNames,
Autocomplete,
Draggable,
Descendants,
SelectOtu,
TypeSection,
CoordinateOtus,
Distribution
},
computed: {
preferences: {
get() {
return this.$store.getters[GetterNames.GetPreferences]
},
set(value) {
this.$store.commit(MutationNames.SetPreferences, value)
}
},
menu() {
return this.preferences.sections.map(
(name) => this.componentNames[name].title
)
},
taxonName() {
return this.$store.getters[GetterNames.GetTaxonName]
},
otu() {
return this.$store.getters[GetterNames.GetCurrentOtu]
},
otus() {
return this.$store.getters[GetterNames.GetOtus]
}
},
data() {
return {
isLoading: false,
navigate: undefined,
tmp: undefined,
otuList: [],
componentNames: COMPONENT_NAMES
}
},
watch: {
otus: {
handler(newVal) {
this.$store.dispatch(ActionNames.LoadInformation, newVal)
},
deep: true
},
preferences: {
handler(newVal, oldVal) {
if (newVal && JSON.stringify(newVal) !== JSON.stringify(this.tmp)) {
this.tmp = newVal
User.update(this.$store.getters[GetterNames.GetUserId], {
user: { layout: { browseOtu: newVal } }
}).then((response) => {
this.preferences = response.body.preferences.layout?.browseOtu
})
}
},
deep: true
}
},
created() {
const urlParams = new URLSearchParams(window.location.search)
const otuId = urlParams.get('otu_id')
? urlParams.get('otu_id')
: location.pathname.split('/')[4]
const taxonId = urlParams.get('taxon_name_id')
if (/^\d+$/.test(otuId)) {
this.$store.dispatch(ActionNames.LoadOtus, otuId).then(() => {
this.isLoading = false
})
Otu.navigation(otuId).then((response) => {
this.navigate = response.body
})
} else if (taxonId) {
TaxonName.otus(taxonId).then(({ body }) => {
if (!body.length) {
TW.workbench.alert.create(
`No page available. There is no OTU for this taxon name.`,
'notice'
)
return
}
if (body.length > 1) {
this.otuList = body
} else {
this.$store.dispatch(ActionNames.LoadOtus, body[0].id).then(() => {
this.isLoading = false
})
}
})
} else {
this.isLoading = false
}
},
methods: {
loadOtu(event) {
window.open(`/tasks/otus/browse?otu_id=${event.id}`, '_self')
},
updatePreferences() {
User.update(this.preferences.id, {
user: { layout: { [this.keyStorage]: this.componentsOrder } }
}).then((response) => {
this.preferences.layout = response.preferences
this.componentsOrder = response.preferences.layout[this.keyStorage]
})
},
showForRanks(section) {
const rankGroup = section.rankGroup
return rankGroup
? this.taxonName
? ShowForThisGroup(rankGroup, this.taxonName)
: section.otu
: true
}
}
}
</script>
<style lang="scss">
#browse-otu {
.anchor {
scroll-margin-top: 9rem;
}
.autocomplete-search-bar {
input {
width: 500px;
}
}
.container {
margin: 0 auto;
width: 1240px;
min-width: auto;
}
.section-title {
text-transform: uppercase;
font-size: 14px;
}
.expand-box {
width: 24px;
height: 24px;
padding: 0px;
background-size: 10px;
background-position: center;
}
.mark-box {
width: 10px;
height: 10px;
padding: 0px;
}
}
</style>