Skip to content

Commit

Permalink
Merge pull request #4200 from SpeciesFileGroup/browse_field_occurrence
Browse files Browse the repository at this point in the history
Browse field occurrence
  • Loading branch information
jlpereira authored Feb 12, 2025
2 parents ec43a18 + f384470 commit 8f2527b
Show file tree
Hide file tree
Showing 63 changed files with 1,072 additions and 32 deletions.
4 changes: 4 additions & 0 deletions app/controllers/tasks/field_occurrences/browse_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
class Tasks::FieldOccurrences::BrowseController < ApplicationController
include TaskControllerConfiguration

end
5 changes: 3 additions & 2 deletions app/javascript/packs/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ import '../vue/tasks/biological_associations/network/main.js'
import '../vue/tasks/collecting_events/stepwise/collectors/main.js'
import '../vue/tasks/leads/new_lead/main.js'
import '../vue/tasks/leads/show/main.js'
import '../vue/tasks/field_occurrences/new_field_occurrences/main.js'
import '../vue/tasks/field_occurrences/new/main.js'
import '../vue/tasks/metadata/vocabulary/project_vocabulary/main.js'
import '../vue/tasks/otus/new_otu/main.js'
import '../vue/tasks/leads/hub/main.js'
Expand All @@ -117,4 +117,5 @@ import '../vue/tasks/unify/objects/main.js'
import '../vue/tasks/images/new_filename_depicting_image/main.js'
import '../vue/tasks/biological_associations/new/main.js'
import '../vue/tasks/otus/duplicates/main.js'
import '../vue/tasks/data_attributes/multi_update/main.js'
import '../vue/tasks/field_occurrences/browse/main.js'
import '../vue/tasks/data_attributes/multi_update/main.js'
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,14 @@ import {
LABEL_CODE_128,
IDENTIFIER_LOCAL_CATALOG_NUMBER,
COLLECTION_OBJECT,
COLLECTING_EVENT
COLLECTING_EVENT,
FIELD_OCCURRENCE
} from '@/constants/index.js'
import {
Label,
Identifier,
CollectionObject,
FieldOccurrence,
CollectingEvent
} from '@/routes/endpoints'
import { onBeforeMount, ref, watch } from 'vue'
Expand All @@ -87,6 +89,17 @@ const LABEL_TYPES = {
[LABEL_CODE_128]: QRCodeComponent
}
const TYPES = {
[FIELD_OCCURRENCE]: {
service: FieldOccurrence,
property: 'field_occurrence'
},
[COLLECTION_OBJECT]: {
service: CollectionObject,
property: 'collection_object'
}
}
const props = defineProps({
objectId: {
type: Number,
Expand Down Expand Up @@ -123,12 +136,12 @@ watch(collectingEvent, (newVal) => {
})
onBeforeMount(async () => {
const ceId = (await CollectionObject.find(props.objectId)).body
.collecting_event_id
const ceId = (await TYPES[props.objectType].service.find(props.objectId)).body
?.collecting_event_id
Identifier.where({
identifier_object_id: props.objectId,
identifier_object_type: COLLECTION_OBJECT,
identifier_object_type: props.objectType,
type: IDENTIFIER_LOCAL_CATALOG_NUMBER
}).then(({ body }) => {
identifier.value = body[0]
Expand Down Expand Up @@ -180,10 +193,12 @@ function removeLabel(label) {
}
function addCollectingEvent(ce) {
CollectionObject.update(props.objectId, {
collection_object: { collecting_event_id: ce.id || null }
}).then((_) => {
collectingEvent.value = ce.id ? ce : undefined
})
TYPES[props.objectType].service
.update(props.objectId, {
[TYPES[props.objectType].property]: { collecting_event_id: ce.id || null }
})
.then(() => {
collectingEvent.value = ce.id ? ce : undefined
})
}
</script>
2 changes: 2 additions & 0 deletions app/javascript/vue/routes/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const RouteNames = {
BiologicalRelationshipComposer: '/tasks/biological_relationships/composer',
BrowseAssertedDistribution: '/tasks/otus/browse_asserted_distributions',
BrowseCollectionObject: '/tasks/collection_objects/browse',
BrowseFieldOccurrence: '/tasks/field_occurrences/browse',
BrowseNomenclature: '/tasks/nomenclature/browse',
BrowseOtu: '/tasks/otus/browse',
ContentEditorTask: '/tasks/content/editor/index',
Expand Down Expand Up @@ -57,6 +58,7 @@ const RouteNames = {
NewCombination: '/tasks/nomenclature/new_combination',
NewDescriptor: '/tasks/descriptors/new_descriptor',
NewExtract: '/tasks/extracts/new_extract',
NewFieldOccurrence: '/tasks/field_occurrences/new_field_occurrences',
NewLead: '/tasks/leads/new_lead',
NewNamespace: '/tasks/namespaces/new_namespace',
NewObservationMatrix: '/tasks/observation_matrices/new_matrix',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,27 @@
<template>
<PanelContainer title="Identifiers">
<TableAttributes
:header="['Identifier', 'On']"
:items="identifiers"
/>
<table class="table-attributes">
<thead>
<tr class="cell-head">
<th>Identifier</th>
<th>On</th>
</tr>
</thead>
<tbody>
<template
v-for="(value, key) in identifiers"
:key="key"
>
<tr>
<td v-html="key" />
<td
class="cell-value"
v-html="value"
/>
</tr>
</template>
</tbody>
</table>
</PanelContainer>
</template>

Expand All @@ -12,19 +30,40 @@ import { useStore } from 'vuex'
import { computed } from 'vue'
import { GetterNames } from '../../store/getters/getters'
import PanelContainer from './PanelContainer.vue'
import TableAttributes from '../Table/TableAttributes.vue'
const store = useStore()
const identifiers = computed(() => {
const list = store.getters[GetterNames.GetIdentifiers]
const newlist = {}
for (const key in list) {
list[key].forEach(identifier => {
list[key].forEach((identifier) => {
newlist[identifier.objectTag] = key
})
}
return newlist
})
</script>

<style lang="scss">
.table-attributes {
box-shadow: none;
tr {
border-bottom: 1px solid #eaeaea;
}
th {
border-bottom: 2px solid #eaeaea;
}
.cell-value {
font-weight: 500;
word-break: break-all;
}
.cell-head {
text-transform: uppercase;
}
}
</style>
134 changes: 134 additions & 0 deletions app/javascript/vue/tasks/field_occurrences/browse/app.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
<template>
<div class="flex flex-separate middle">
<VSpinner
v-if="isLoading"
full-screen
/>
<h1>Browse field occurrence</h1>
<VAutocomplete
v-if="store.fieldOccurrence"
class="autocomplete"
url="/field_occurrences/autocomplete"
placeholder="Search a field occurrence"
param="term"
label="label_html"
clear-after
@get-item="({ id }) => loadData(id)"
/>
</div>
<FOHeader @select="loadData" />
<TableGrid
:columns="1"
gap="1em"
>
<TableGrid
:columns="ceStore.collectingEvent ? 3 : 2"
gap="1em"
:column-width="{
default: 'min-content',
0: '1fr',
1: ceStore.collectingEvent ? '2fr' : '1fr',
2: '1fr'
}"
>
<PanelFO />
<PanelCE />
<ColumnThree />
</TableGrid>
</TableGrid>
</template>

<script setup>
import { FIELD_OCCURRENCE, COLLECTING_EVENT } from '@/constants'
import { URLParamsToJSON } from '@/helpers'
import { onBeforeMount, ref } from 'vue'
import VAutocomplete from '@/components/ui/Autocomplete.vue'
import FOHeader from './components/FOHeader.vue'
import PanelFO from './components/Panel/PanelFO.vue'
import PanelCE from './components/PanelCE/PanelCE.vue'
import ColumnThree from './components/ColumnThree.vue'
import TableGrid from '@/components/layout/Table/TableGrid.vue'
import VSpinner from '@/components/ui/VSpinner.vue'
import useFieldOccurrenceStore from './store/store.js'
import useCollectingEventStore from './store/collectingEvent.js'
import useDeterminationStore from './store/determinations.js'
import useDepictionStore from './store/depictions.js'
import useBiocurationStore from './store/biocurations.js'
import useBiologicalAssociationStore from './store/biologicalAssociations.js'
import useIdentifierStore from './store/identifiers.js'
import { setParam } from '@/helpers'
import { RouteNames } from '@/routes/routes'
defineOptions({
name: 'BrowseFieldOccurrence'
})
const store = useFieldOccurrenceStore()
const ceStore = useCollectingEventStore()
const depictionStore = useDepictionStore()
const biocurationStore = useBiocurationStore()
const determinationStore = useDeterminationStore()
const biologicalAssociationStore = useBiologicalAssociationStore()
const identifierStore = useIdentifierStore()
const isLoading = ref(false)
onBeforeMount(async () => {
const { field_occurrence_id: foId } = URLParamsToJSON(location.href)
if (foId) {
loadData(foId)
}
})
async function loadData(foId) {
const requests = []
const args = {
objectId: foId,
objectType: FIELD_OCCURRENCE
}
try {
isLoading.value = true
store.$reset()
ceStore.$reset()
depictionStore.$reset()
biocurationStore.$reset()
determinationStore.$reset()
biologicalAssociationStore.$reset()
identifierStore.$reset()
await store.load(foId)
const ceId = store.fieldOccurrence.collecting_event_id
setParam(RouteNames.BrowseFieldOccurrence, 'field_occurrence_id', foId)
if (ceId) {
requests.push(
ceStore.load(ceId),
identifierStore.load({
objectId: ceId,
objectType: COLLECTING_EVENT
})
)
}
requests.push(
depictionStore.load(args),
biocurationStore.load(args),
determinationStore.load(args),
biologicalAssociationStore.load(args),
identifierStore.load(args)
)
Promise.all(requests).finally(() => {
isLoading.value = false
})
} catch {
TW.workbench.alert.create('No field occurrence found.', 'notice')
}
}
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<template>
<TableGrid
:columns="1"
gap="1em"
>
<SoftValidations
v-if="false"
class="column-validation"
/>
<PanelIdentifier />
<PanelDepictions />
<PanelMap />
</TableGrid>
</template>

<script setup>
import SoftValidations from '@/components/soft_validations/panel.vue'
import PanelIdentifier from './Panel/PanelIdentifier.vue'
import TableGrid from '@/components/layout/Table/TableGrid.vue'
import PanelDepictions from './Panel/PanelDepictions.vue'
import PanelMap from './Panel/PanelMap.vue'
</script>
Loading

0 comments on commit 8f2527b

Please sign in to comment.