diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0cf4f0f217..26fd3a417a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,37 @@ This project does not yet adheres to [Semantic Versioning](https://semv
\-
+## [0.31.2] - 2023-03-09
+
+# Added
+
+- Link from AssertedDistribution filter to BiologicalAssociations filter
+- All tab to biological relationships facet [#3334]
+- Biological Property to Manage controlled vocabulary terms
+
+### Changed
+
+- Add nomenclature code to relationships and statuses labels in Filter nomenclature [#3333]
+- All Loan edit requests resolve to the edit task [#3330]
+
+### Fixed
+
+- Biological association filter raises [#3335]
+- Mass annotator for Sources showed no options
+- People filtering doesn't work on Filter nomenclature [#3332]
+- Biological associations section shows incorrect results in Browse Otu [#3336]
+- Error message on Combination [#3340]
+- `Clone last citation` button doesn't work
+- Missing asserted distributions in Browse OTU and Quick forms radial [#3337]
+
+[#3330]: https://github.com/SpeciesFileGroup/taxonworks/issues/3330
+[#3332]: https://github.com/SpeciesFileGroup/taxonworks/issues/3332
+[#3333]: https://github.com/SpeciesFileGroup/taxonworks/issues/3333
+[#3334]: https://github.com/SpeciesFileGroup/taxonworks/issues/3334
+[#3335]: https://github.com/SpeciesFileGroup/taxonworks/issues/3335
+[#3336]: https://github.com/SpeciesFileGroup/taxonworks/issues/3336
+[#3337]: https://github.com/SpeciesFileGroup/taxonworks/issues/3337
+
## [0.31.1] - 2023-03-07
### Fixed
@@ -24,6 +55,7 @@ This project does not yet adheres to [Semantic Versioning](https://semv
- Short URLs not working due to Ruby 3.2 incompatibility.
### Changed
+
- `/combinations/` redirects to `/taxon_names/`
[#3328]: https://github.com/SpeciesFileGroup/taxonworks/issues/3328
@@ -32,6 +64,7 @@ This project does not yet adheres to [Semantic Versioning](https://semv
[#3327]: https://github.com/SpeciesFileGroup/taxonworks/issues/3327
[#3326]: https://github.com/SpeciesFileGroup/taxonworks/issues/3326
[#3325]: https://github.com/SpeciesFileGroup/taxonworks/issues/3325
+[#3324]: https://github.com/SpeciesFileGroup/taxonworks/issues/3324
## [0.31.0] - 2023-03-07
@@ -3393,7 +3426,9 @@ This project does not yet adheres to [Semantic Versioning](https://semv
- Loosing input page numbers when switching tabs on New Taxon Name task
[#1532]: https://github.com/SpeciesFileGroup/taxonworks/issues/1532
-[unreleased]: https://github.com/SpeciesFileGroup/taxonworks/compare/v0.31.1...development
+
+[unreleased]: https://github.com/SpeciesFileGroup/taxonworks/compare/v0.31.2...development
+[0.31.2]: https://github.com/SpeciesFileGroup/taxonworks/compare/v0.31.1...v0.31.2
[0.31.1]: https://github.com/SpeciesFileGroup/taxonworks/compare/v0.31.0...v0.31.1
[0.31.0]: https://github.com/SpeciesFileGroup/taxonworks/compare/v0.30.3...v0.31.0
[0.30.3]: https://github.com/SpeciesFileGroup/taxonworks/compare/v0.30.2...v0.30.3
diff --git a/app/assets/javascripts/views/loan_items/_form.js.erb b/app/assets/javascripts/views/loan_items/_form.js.erb
deleted file mode 100644
index 92343bb1df..0000000000
--- a/app/assets/javascripts/views/loan_items/_form.js.erb
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
-
- Code behind adding/remove loan items on /loan_items/:id/_form
-
- */
-var TW = TW || {};
-TW.views = TW.views || {};
-TW.views.loan_items = TW.views.loan_items || {};
-TW.views.loan_items.form = TW.views.loan_items.form || {};
-
-Object.assign(TW.views.loan_items.form, {
-
- add_loan_item: function(form, gid, label) {
- var random_index = new Date().getTime();
- var indexed_base_name = this.base_name + '[' + random_index + ']';
- var loan_item_list = form.find('.loan_items_list');
-
- var type_regex = /gid:\/\/taxon-works\/(.*)\/\d+/;
- var match = type_regex.exec(gid);
- var item_type = match[1];
-
- var total_field;
- if (gid.match(/Otu/)) {
- total_field = ' | ';
- } else {
- total_field = ' | ';
- }
-
- form.append( $(''));
-
- loan_item_list.append( $('
diff --git a/app/javascript/vue/components/radials/filter/links/AssertedDistribution.js b/app/javascript/vue/components/radials/filter/links/AssertedDistribution.js
index 497c6eae44..ca8df11ca5 100644
--- a/app/javascript/vue/components/radials/filter/links/AssertedDistribution.js
+++ b/app/javascript/vue/components/radials/filter/links/AssertedDistribution.js
@@ -1,11 +1,13 @@
import {
FILTER_OTU,
FILTER_SOURCE,
- FILTER_TAXON_NAME
+ FILTER_TAXON_NAME,
+ FILTER_BIOLOGICAL_ASSOCIATION
} from '../constants/filterLinks'
export const AssertedDistribution = [
FILTER_SOURCE,
FILTER_OTU,
- FILTER_TAXON_NAME
+ FILTER_TAXON_NAME,
+ FILTER_BIOLOGICAL_ASSOCIATION
]
diff --git a/app/javascript/vue/components/radials/object/components/asserted_distributions/asserted_distributions_annotator.vue b/app/javascript/vue/components/radials/object/components/asserted_distributions/asserted_distributions_annotator.vue
index 29ef9e56b3..542d5a4e17 100644
--- a/app/javascript/vue/components/radials/object/components/asserted_distributions/asserted_distributions_annotator.vue
+++ b/app/javascript/vue/components/radials/object/components/asserted_distributions/asserted_distributions_annotator.vue
@@ -49,11 +49,20 @@
{
+ asserted_distribution.geographic_area_id = $event
+ saveAssertedDistribution()
+ }
+ "
/>
+
\ No newline at end of file
+}
+
diff --git a/app/javascript/vue/routes/endpoints/base.js b/app/javascript/vue/routes/endpoints/base.js
index 1ad879c371..b96ef0a774 100644
--- a/app/javascript/vue/routes/endpoints/base.js
+++ b/app/javascript/vue/routes/endpoints/base.js
@@ -1,4 +1,5 @@
import AjaxCall from 'helpers/ajaxCall'
+import getPagination from 'helpers/getPagination'
import { isObject } from 'helpers/objects'
const BASE_PARAMS = {
@@ -15,12 +16,14 @@ const filterParams = (params, allowParams) => {
return params
}
- properties.forEach(property => {
+ properties.forEach((property) => {
if (allowProperties.includes(property)) {
const paramValue = params[property]
if (Array.isArray(paramValue)) {
- newObj[property] = paramValue.map(item => filterParams(item, allowParams[property]))
+ newObj[property] = paramValue.map((item) =>
+ filterParams(item, allowParams[property])
+ )
} else if (isObject(paramValue)) {
newObj[property] = filterParams(paramValue, allowParams[property])
} else {
@@ -33,41 +36,87 @@ const filterParams = (params, allowParams) => {
}
export default (model, permitParams) => ({
- all: params => AjaxCall('get', `/${model}.json`, { params }),
-
- create: (data, config) => AjaxCall('post', `/${model}.json`, filterParams(data, { ...BASE_PARAMS, ...permitParams }), config),
-
- destroy: id => AjaxCall('delete', `/${model}/${id}.json`),
-
- find: (id, params, config) => AjaxCall('get', `/${model}/${id}.json`, { params }, config),
-
- update: (id, data, config) => AjaxCall('patch', `/${model}/${id}.json`, filterParams(data, { ...BASE_PARAMS, ...permitParams }), config),
+ all: async (params = {}) => {
+ const url = `/${model}.json`
+ const maxPer = params.per || 500
+ const requests = [
+ await AjaxCall('get', url, {
+ params: {
+ ...params,
+ per: maxPer
+ }
+ })
+ ]
+ const { totalPages } = getPagination(requests[0])
+
+ if (totalPages > 1) {
+ for (let page = 2; page <= totalPages; page++) {
+ requests.push(AjaxCall('get', url, { params: { ...params, page } }))
+ }
+ }
- where: (params, config) => AjaxCall('get', `/${model}.json`, { params }, config),
+ const responses = await Promise.all(requests)
- autocomplete: (params, config) => AjaxCall('get', `/${model}/autocomplete`, { params }, config)
+ return {
+ body: [].concat(...responses.map(({ body }) => body))
+ }
+ },
+
+ create: (data, config) =>
+ AjaxCall(
+ 'post',
+ `/${model}.json`,
+ filterParams(data, { ...BASE_PARAMS, ...permitParams }),
+ config
+ ),
+
+ destroy: (id) => AjaxCall('delete', `/${model}/${id}.json`),
+
+ find: (id, params, config) =>
+ AjaxCall('get', `/${model}/${id}.json`, { params }, config),
+
+ update: (id, data, config) =>
+ AjaxCall(
+ 'patch',
+ `/${model}/${id}.json`,
+ filterParams(data, { ...BASE_PARAMS, ...permitParams }),
+ config
+ ),
+
+ where: (params, config) =>
+ AjaxCall('get', `/${model}.json`, { params }, config),
+
+ autocomplete: (params, config) =>
+ AjaxCall('get', `/${model}/autocomplete`, { params }, config)
})
-export {
- filterParams
-}
+export { filterParams }
-export const annotations = model => ({
- attributions: (id, params) => AjaxCall('get', `/${model}/${id}/attributions.json`, { params }),
+export const annotations = (model) => ({
+ attributions: (id, params) =>
+ AjaxCall('get', `/${model}/${id}/attributions.json`, { params }),
- citations: (id, params) => AjaxCall('get', `/${model}/${id}/citations.json`, { params }),
+ citations: (id, params) =>
+ AjaxCall('get', `/${model}/${id}/citations.json`, { params }),
- dataAttributes: (id, params) => AjaxCall('get', `/${model}/${id}/data_attributes.json`, { params }),
+ dataAttributes: (id, params) =>
+ AjaxCall('get', `/${model}/${id}/data_attributes.json`, { params }),
- depictions: (id, params) => AjaxCall('get', `/${model}/${id}/depictions.json`, { params }),
+ depictions: (id, params) =>
+ AjaxCall('get', `/${model}/${id}/depictions.json`, { params }),
- documentation: (id, params) => AjaxCall('get', `/${model}/${id}/documentation.json`, { params }),
+ documentation: (id, params) =>
+ AjaxCall('get', `/${model}/${id}/documentation.json`, { params }),
- identifiers: (id, params) => AjaxCall('get', `/${model}/${id}/identifiers.json`, { params }),
+ identifiers: (id, params) =>
+ AjaxCall('get', `/${model}/${id}/identifiers.json`, { params }),
- notes: (id, params) => AjaxCall('get', `/${model}/${id}/notes.json`, { params }),
+ notes: (id, params) =>
+ AjaxCall('get', `/${model}/${id}/notes.json`, { params }),
- tags: (id, params) => AjaxCall('get', `/${model}/${id}/tags.json`, { params }),
+ tags: (id, params) =>
+ AjaxCall('get', `/${model}/${id}/tags.json`, { params }),
- protocolRelationships: (id, params) => AjaxCall('get', `/${model}/${id}/protocol_relationships.json`, { params })
+ protocolRelationships: (id, params) =>
+ AjaxCall('get', `/${model}/${id}/protocol_relationships.json`, { params })
})
diff --git a/app/javascript/vue/tasks/controlled_vocabularies/manage/constants/controlled_vocabulary_term_types.js b/app/javascript/vue/tasks/controlled_vocabularies/manage/constants/controlled_vocabulary_term_types.js
index cb5fc0925a..3962ca7590 100644
--- a/app/javascript/vue/tasks/controlled_vocabularies/manage/constants/controlled_vocabulary_term_types.js
+++ b/app/javascript/vue/tasks/controlled_vocabularies/manage/constants/controlled_vocabulary_term_types.js
@@ -4,5 +4,6 @@ export default {
Predicate: 'A predicate is the label for a custom field/attribute.',
ConfidenceLevel: 'A confidence level is a curator defined status that pertains to their confidence in some quality of the data it is applied to.',
BiocurationGroup: 'A biocuration group groups biocurations classes into categories, like "Life Stage" or "Sex."',
- BiocurationClass: 'A biocuration class is a biological property that curators use to describe their specimens, like Female, or adult.'
+ BiocurationClass: 'A biocuration class is a biological property that curators use to describe their specimens, like Female, or adult.',
+ BiologicalProperty: 'A biological class that is assigned to the subject or object of a BiologicalAssociation through their use in the definition of a BiologicalRelationship. For example host or parasitod.'
}
diff --git a/app/javascript/vue/tasks/nomenclature/filter/components/recursiveList.vue b/app/javascript/vue/tasks/nomenclature/filter/components/recursiveList.vue
index 81f0601731..567c3d09b9 100644
--- a/app/javascript/vue/tasks/nomenclature/filter/components/recursiveList.vue
+++ b/app/javascript/vue/tasks/nomenclature/filter/components/recursiveList.vue
@@ -2,20 +2,23 @@
-
+ :key="key"
+ >
+ :object-list="item"
+ />
@@ -56,15 +59,15 @@ export default {
sortable.sort((a, b) => {
if (a[1][this.display] > b[1][this.display]) {
- return 1;
+ return 1
}
if (a[1][this.display] < b[1][this.display]) {
- return -1;
+ return -1
}
- return 0;
+ return 0
})
- sortable.forEach(item => {
+ sortable.forEach((item) => {
sortableObject[item[0]] = item[1]
})
@@ -73,29 +76,28 @@ export default {
},
methods: {
- selectItem (optionSelected) {
+ selectItem(optionSelected) {
this.$emit('selected', optionSelected)
},
- findExist (item) {
- return this.created.find(element => element.type == item.type)
+ findExist(item) {
+ return this.created.find((element) => element.type == item.type)
},
- isForThisRank (item) {
+ isForThisRank(item) {
return item.valid_subject_ranks?.includes(this.taxon.rank_string)
}
}
}
-
diff --git a/app/javascript/vue/tasks/otu/browse/store/actions/loadAssertedDistributions.js b/app/javascript/vue/tasks/otu/browse/store/actions/loadAssertedDistributions.js
index 59faa802bd..9046a4bd55 100644
--- a/app/javascript/vue/tasks/otu/browse/store/actions/loadAssertedDistributions.js
+++ b/app/javascript/vue/tasks/otu/browse/store/actions/loadAssertedDistributions.js
@@ -2,10 +2,7 @@ import { AssertedDistribution } from 'routes/endpoints'
import { MutationNames } from '../mutations/mutations'
import nonReactiveStore from '../nonReactiveStore.js'
-const embed = [
- 'shape',
- 'lavel_names'
-]
+const embed = ['shape', 'lavel_names']
const extend = [
'citations',
'geographic_area',
@@ -16,31 +13,41 @@ const extend = [
'otu'
]
-export default ({ commit }, otusId) => new Promise((resolve, reject) => {
- AssertedDistribution.where({ otu_id: otusId, embed, extend }).then(response => {
- const shapes = response.body.map(item => item.geographic_area.shape)
+export default ({ commit }, otusId) =>
+ new Promise((resolve, reject) => {
+ AssertedDistribution.all({ otu_id: otusId, embed, extend }).then(
+ (response) => {
+ const shapes = response.body.map((item) => item.geographic_area.shape)
- nonReactiveStore.geographicAreas = [...new Map(shapes.map(item => [item.properties.geographic_area.id, item])).values()]
+ nonReactiveStore.geographicAreas = [
+ ...new Map(
+ shapes.map((item) => [item.properties.geographic_area.id, item])
+ ).values()
+ ]
- const assertedDistributions = response.body.map(ad => {
- ad.geographic_area.shape = !!ad.geographic_area.shape
+ const assertedDistributions = response.body
+ .map((ad) => {
+ ad.geographic_area.shape = !!ad.geographic_area.shape
- return ad
- }).sort((a, b) => {
- const compareA = a.geographic_area.name
- const compareB = b.geographic_area.name
- if (compareA < compareB) {
- return -1
- } else if (compareA > compareB) {
- return 1
- } else {
- return 0
- }
- })
+ return ad
+ })
+ .sort((a, b) => {
+ const compareA = a.geographic_area.name
+ const compareB = b.geographic_area.name
+ if (compareA < compareB) {
+ return -1
+ } else if (compareA > compareB) {
+ return 1
+ } else {
+ return 0
+ }
+ })
- commit(MutationNames.SetAssertedDistributions, assertedDistributions)
- resolve(response)
- }, error => {
- reject(error)
+ commit(MutationNames.SetAssertedDistributions, assertedDistributions)
+ resolve(response)
+ },
+ (error) => {
+ reject(error)
+ }
+ )
})
-})
diff --git a/app/javascript/vue/tasks/otu/browse/store/actions/loadBiologicalAssociations.js b/app/javascript/vue/tasks/otu/browse/store/actions/loadBiologicalAssociations.js
index 74e1c6d838..3870ab9c6e 100644
--- a/app/javascript/vue/tasks/otu/browse/store/actions/loadBiologicalAssociations.js
+++ b/app/javascript/vue/tasks/otu/browse/store/actions/loadBiologicalAssociations.js
@@ -12,10 +12,16 @@ const extend = [
export default ({ state, commit }, globalId) =>
new Promise((resolve, reject) => {
- BiologicalAssociation.where({ any_global_id: globalId, extend }).then(response => {
- commit(MutationNames.SetBiologicalAssociations, state.biologicalAssociations.concat(response.body))
- resolve(response)
- }, error => {
- reject(error)
- })
+ BiologicalAssociation.all({ any_global_id: [globalId], extend }).then(
+ (response) => {
+ commit(
+ MutationNames.SetBiologicalAssociations,
+ state.biologicalAssociations.concat(response.body)
+ )
+ resolve(response)
+ },
+ (error) => {
+ reject(error)
+ }
+ )
})
diff --git a/app/javascript/vue/tasks/otu/browse/store/actions/loadCollectingEvents.js b/app/javascript/vue/tasks/otu/browse/store/actions/loadCollectingEvents.js
index 0daff79efe..9d45bcb57b 100644
--- a/app/javascript/vue/tasks/otu/browse/store/actions/loadCollectingEvents.js
+++ b/app/javascript/vue/tasks/otu/browse/store/actions/loadCollectingEvents.js
@@ -7,7 +7,7 @@ const maxCEPerCall = 100
export default ({ state, commit }, otusId) =>
new Promise((resolve, reject) => {
- CollectingEvent.where({ otu_id: otusId })
+ CollectingEvent.all({ otu_id: otusId })
.then(
(response) => {
const CEs = response.body
@@ -23,9 +23,7 @@ export default ({ state, commit }, otusId) =>
)
if (CEs.length) {
CEIds.forEach((idGroup) => {
- promises.push(
- Georeference.where({ collecting_event_id: idGroup })
- )
+ promises.push(Georeference.all({ collecting_event_id: idGroup }))
})
Promise.all(promises).then((responses) => {
diff --git a/app/javascript/vue/tasks/otu/browse/store/actions/loadCollectionObjects.js b/app/javascript/vue/tasks/otu/browse/store/actions/loadCollectionObjects.js
index b420e1d5c9..d041c927f1 100644
--- a/app/javascript/vue/tasks/otu/browse/store/actions/loadCollectionObjects.js
+++ b/app/javascript/vue/tasks/otu/browse/store/actions/loadCollectionObjects.js
@@ -3,7 +3,7 @@ import { MutationNames } from '../mutations/mutations'
export default ({ state, commit }, otuId) =>
new Promise((resolve, reject) => {
- CollectionObject.where({
+ CollectionObject.all({
otu_id: otuId,
current_determinations: true,
extend: ['citations', 'source']
diff --git a/app/javascript/vue/tasks/otu/browse/store/actions/loadCommonNames.js b/app/javascript/vue/tasks/otu/browse/store/actions/loadCommonNames.js
index accd4d578c..93561c82fe 100644
--- a/app/javascript/vue/tasks/otu/browse/store/actions/loadCommonNames.js
+++ b/app/javascript/vue/tasks/otu/browse/store/actions/loadCommonNames.js
@@ -2,6 +2,9 @@ import { MutationNames } from '../mutations/mutations'
import { CommonName } from 'routes/endpoints'
export default ({ commit, state }, id) =>
- CommonName.where({ otu_id: id }).then(response => {
- commit(MutationNames.SetCommonNames, state.commonNames.concat(response.body))
+ CommonName.all({ otu_id: id }).then((response) => {
+ commit(
+ MutationNames.SetCommonNames,
+ state.commonNames.concat(response.body)
+ )
})
diff --git a/app/javascript/vue/tasks/otu/browse/store/actions/loadDescendants.js b/app/javascript/vue/tasks/otu/browse/store/actions/loadDescendants.js
index 58f78881c5..a8b507ce47 100644
--- a/app/javascript/vue/tasks/otu/browse/store/actions/loadDescendants.js
+++ b/app/javascript/vue/tasks/otu/browse/store/actions/loadDescendants.js
@@ -23,7 +23,7 @@ function getAllCollectingEvents(taxonNames) {
chunks.forEach((ids) => {
if (ids.length) {
promises.push(
- CollectingEvent.where({ otu_id: [].concat(...ids) }).then(
+ CollectingEvent.all({ otu_id: [].concat(...ids) }).then(
(response) => {
collectingEvents.push(response.body)
}
@@ -55,7 +55,7 @@ function getAllGeoreferences(CEIds) {
if (chunks.length) {
chunks.forEach((ids) => {
promises.push(
- Georeference.where({ collecting_event_id: ids }).then((response) => {
+ Georeference.all({ collecting_event_id: ids }).then((response) => {
georeferences.push(response.body)
})
)
@@ -81,7 +81,7 @@ export default ({ commit, state }, otu) => {
georeferences: []
}
- TaxonName.where(params)
+ TaxonName.all(params)
.then((response) => {
descendants.taxon_names = response.body.filter(
(tn) => tn.id !== otu.taxon_name_id
diff --git a/app/javascript/vue/tasks/otu/browse/store/actions/loadInformation.js b/app/javascript/vue/tasks/otu/browse/store/actions/loadInformation.js
index ce6f1a3244..8c7846340d 100644
--- a/app/javascript/vue/tasks/otu/browse/store/actions/loadInformation.js
+++ b/app/javascript/vue/tasks/otu/browse/store/actions/loadInformation.js
@@ -3,13 +3,14 @@ import { MutationNames } from '../mutations/mutations'
import { TaxonName } from 'routes/endpoints'
export default ({ dispatch, commit, state }, otus) => {
- const otuIds = otus.map(otu => otu.id)
+ const otuIds = otus.map((otu) => otu.id)
- function loadOtuInformation (otu) {
+ function loadOtuInformation(otu) {
const promises = []
return new Promise((resolve, reject) => {
-
- promises.push(dispatch(ActionNames.LoadBiologicalAssociations, otu.global_id))
+ promises.push(
+ dispatch(ActionNames.LoadBiologicalAssociations, otu.global_id)
+ )
promises.push(dispatch(ActionNames.LoadDepictions, otu.id))
promises.push(dispatch(ActionNames.LoadCommonNames, otu.id))
@@ -21,7 +22,9 @@ export default ({ dispatch, commit, state }, otus) => {
if (state.currentOtu.taxon_name_id) {
dispatch(ActionNames.LoadTaxonName, state.currentOtu.taxon_name_id)
}
- TaxonName.where({ taxon_name_id: [...new Set(otus.map(otu => otu.taxon_name_id))] }).then(response => {
+ TaxonName.all({
+ taxon_name_id: [...new Set(otus.map((otu) => otu.taxon_name_id))]
+ }).then((response) => {
commit(MutationNames.SetTaxonNames, response.body)
})
@@ -42,5 +45,8 @@ export default ({ dispatch, commit, state }, otus) => {
state.loadState.assertedDistribution = false
}
processArray(otus)
- dispatch(ActionNames.LoadAssertedDistributions, state.otus.map(otu => otu.id))
+ dispatch(
+ ActionNames.LoadAssertedDistributions,
+ state.otus.map((otu) => otu.id)
+ )
}
diff --git a/app/javascript/vue/tasks/otu/filter/components/FilterView.vue b/app/javascript/vue/tasks/otu/filter/components/FilterView.vue
index d2eb030c1c..3def2b8069 100644
--- a/app/javascript/vue/tasks/otu/filter/components/FilterView.vue
+++ b/app/javascript/vue/tasks/otu/filter/components/FilterView.vue
@@ -3,27 +3,28 @@
v-model="params"
input-id="area_picker_autocomplete"
/>
-
+
+
-
-
+
-
+
+
date2 && subject_invalid_statuses.empty?
- soft_validations.add(:type, "#{self.subject_status.capitalize} #{self.subject_taxon_name.cached_html_name_and_author_year} should not be younger than citation (#{self.object_taxon_name.source.author_year}) of #{self.object_taxon_name.cached_html_name_and_author_year}")
+ soft_validations.add(:type, "#{self.subject_status.capitalize} #{self.subject_taxon_name.cached_html_name_and_author_year} should not be younger than citation (#{self.object_taxon_name.source&.author_year}) of #{self.object_taxon_name.cached_html_name_and_author_year}")
end
end
diff --git a/config/initializers/vendor/kaminari_config.rb b/config/initializers/vendor/kaminari_config.rb
index 632bf1d276..34f3499240 100644
--- a/config/initializers/vendor/kaminari_config.rb
+++ b/config/initializers/vendor/kaminari_config.rb
@@ -1,5 +1,5 @@
Kaminari.configure do |config|
- config.default_per_page = 25
+ config.default_per_page = 50
config.max_per_page = 10000
# config.window = 4
# config.outer_window = 0
diff --git a/db/schema.rb b/db/schema.rb
index 8c5466fff7..57d0ea3c20 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 2023_01_13_094500) do
+ActiveRecord::Schema.define(version: 2023_01_13_090400) do
# These are extensions that must be enabled in order to support this database
enable_extension "fuzzystrmatch"
@@ -379,8 +379,8 @@
end
create_table "confidences", id: :serial, force: :cascade do |t|
- t.integer "confidence_object_id", null: false
t.string "confidence_object_type", null: false
+ t.integer "confidence_object_id", null: false
t.integer "position", null: false
t.integer "created_by_id", null: false
t.integer "updated_by_id", null: false
@@ -612,8 +612,8 @@
end
create_table "documentation", id: :serial, force: :cascade do |t|
- t.integer "documentation_object_id", null: false
t.string "documentation_object_type", null: false
+ t.integer "documentation_object_id", null: false
t.integer "document_id", null: false
t.integer "project_id", null: false
t.integer "created_by_id", null: false
@@ -631,7 +631,7 @@
create_table "documents", id: :serial, force: :cascade do |t|
t.string "document_file_file_name", null: false
t.string "document_file_content_type", null: false
- t.integer "document_file_file_size", null: false
+ t.bigint "document_file_file_size", null: false
t.datetime "document_file_updated_at", null: false
t.integer "project_id", null: false
t.integer "created_by_id", null: false
@@ -840,8 +840,8 @@
t.string "vernacularName"
t.string "waterBody"
t.string "year"
- t.integer "dwc_occurrence_object_id"
t.string "dwc_occurrence_object_type"
+ t.integer "dwc_occurrence_object_id"
t.integer "created_by_id", null: false
t.integer "updated_by_id", null: false
t.integer "project_id"
@@ -1040,7 +1040,7 @@
t.datetime "updated_at", null: false
t.string "image_file_file_name"
t.string "image_file_content_type"
- t.integer "image_file_file_size"
+ t.bigint "image_file_file_size"
t.datetime "image_file_updated_at"
t.integer "updated_by_id", null: false
t.text "image_file_meta"
@@ -1121,8 +1121,8 @@
t.integer "project_id", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
- t.integer "loan_item_object_id"
t.string "loan_item_object_type"
+ t.integer "loan_item_object_id"
t.integer "total"
t.string "disposition"
t.index ["created_by_id"], name: "index_loan_items_on_created_by_id"
@@ -1151,7 +1151,7 @@
t.datetime "updated_at", null: false
t.string "recipient_honorific"
t.string "recipient_country"
- t.text "lender_address", default: "Lender's address not provided.", null: false
+ t.text "lender_address", null: false
t.boolean "is_gift"
t.index ["created_by_id"], name: "index_loans_on_created_by_id"
t.index ["project_id"], name: "index_loans_on_project_id"
@@ -1347,10 +1347,10 @@
end
create_table "origin_relationships", id: :serial, force: :cascade do |t|
- t.integer "old_object_id", null: false
t.string "old_object_type", null: false
- t.integer "new_object_id", null: false
+ t.integer "old_object_id", null: false
t.string "new_object_type", null: false
+ t.integer "new_object_id", null: false
t.integer "position"
t.integer "created_by_id", null: false
t.integer "updated_by_id", null: false
@@ -1434,8 +1434,8 @@
end
create_table "pinboard_items", id: :serial, force: :cascade do |t|
- t.integer "pinned_object_id", null: false
t.string "pinned_object_type", null: false
+ t.integer "pinned_object_id", null: false
t.integer "user_id", null: false
t.integer "project_id", null: false
t.integer "position", null: false
@@ -1499,7 +1499,7 @@
t.datetime "updated_at", null: false
t.integer "created_by_id", null: false
t.integer "updated_by_id", null: false
- t.jsonb "preferences", default: {}, null: false
+ t.jsonb "preferences", default: "{}", null: false
t.string "api_access_token"
t.index ["created_by_id"], name: "index_projects_on_created_by_id"
t.index ["updated_by_id"], name: "index_projects_on_updated_by_id"
@@ -1507,8 +1507,8 @@
create_table "protocol_relationships", id: :serial, force: :cascade do |t|
t.integer "protocol_id", null: false
- t.integer "protocol_relationship_object_id", null: false
t.string "protocol_relationship_object_type", null: false
+ t.integer "protocol_relationship_object_id", null: false
t.integer "position", null: false
t.integer "created_by_id", null: false
t.integer "updated_by_id", null: false
@@ -1766,8 +1766,8 @@
t.string "boundary_finder", null: false
t.boolean "has_border", null: false
t.string "layout", null: false
- t.jsonb "metadata_map", default: {}, null: false
- t.jsonb "specimen_coordinates", default: {}, null: false
+ t.jsonb "metadata_map", default: "{}", null: false
+ t.jsonb "specimen_coordinates", default: "{}", null: false
t.integer "project_id", null: false
t.integer "created_by_id", null: false
t.integer "updated_by_id", null: false
diff --git a/lib/queries/asserted_distribution/filter.rb b/lib/queries/asserted_distribution/filter.rb
index 98da3b9d2b..29c9a26451 100644
--- a/lib/queries/asserted_distribution/filter.rb
+++ b/lib/queries/asserted_distribution/filter.rb
@@ -33,7 +33,7 @@ class Filter < Query::Filter
# @return [Array]
attr_accessor :otu_id
- # @param otu_id [Array, Integer, String]
+ # @param geographic_area_id [Array, Integer, String]
# @return [Array]
attr_accessor :geographic_area_id
@@ -49,12 +49,12 @@ class Filter < Query::Filter
attr_accessor :geo_json
# @return [Boolean, nil]
+ # true - Return AssertedDistributions where the OTU is asserted as present according to the Source
+ # false - Return AssertedDistributions where the OTU is asserted as absent according to the Source
# nil - both
- # true - only 't'
- # false - only 'f'
attr_accessor :presence
- # @return Array
+ # @return [Array]
# @param [taxon name ids, nil]
# all Otus matching these taxon names
attr_accessor :taxon_name_id
@@ -119,7 +119,6 @@ def wkt_facet
end
def from_wkt(wkt_shape)
-
i = ::GeographicItem.joins(:geographic_areas).where(::GeographicItem.contained_by_wkt_sql(wkt_shape))
j = ::GeographicArea.joins(:geographic_items).where(geographic_items: i)
@@ -213,7 +212,7 @@ def taxon_name_id_facet
::AssertedDistribution.joins(:otu).joins(j.join_sources).where(z)
else
- ::AssertedDistribution.joins(:otu).where(otus: {taxon_name_id: taxon_name_id})
+ ::AssertedDistribution.joins(:otu).where(otus: {taxon_name_id:})
end
end
@@ -241,14 +240,14 @@ def biological_association_query_facet
s = 'WITH query_ad_ba AS (' + biological_association_query.all.to_sql + ') '
a = ::AssertedDistribution
- .joins("JOIN query_ad_ba as query_ad_ba1 on asserted_distributions.otu_id = query_ad_ba1.biological_association_subject_id AND query_ad_ba1.biological_association_subject_type = 'Otu'").to_sql
+ .joins("JOIN query_ad_ba as query_ad_ba1 on asserted_distributions.otu_id = query_ad_ba1.biological_association_subject_id AND query_ad_ba1.biological_association_subject_type = 'Otu'")
b = ::AssertedDistribution
- .joins("JOIN query_ad_ba as query_ad_ba2 on asserted_distributions.otu_id = query_ad_ba2.biological_association_object_id AND query_ad_ba2.biological_association_object_type = 'Otu'").to_sql
+ .joins("JOIN query_ad_ba as query_ad_ba2 on asserted_distributions.otu_id = query_ad_ba2.biological_association_object_id AND query_ad_ba2.biological_association_object_type = 'Otu'")
- s << ::AssertedDistribution.from("((#{a}) UNION (#{b})) as asserted_distributions").to_sql
+ s << referenced_klass_union([a,b]).to_sql
- ::AssertedDistribution.from('(' + s + ') as asserted_distributions')
+ ::AssertedDistribution.from('(' + s + ') as asserted_distributions').distinct
end
def and_clauses
diff --git a/lib/queries/biological_association/filter.rb b/lib/queries/biological_association/filter.rb
index 3cac612738..4407f56830 100644
--- a/lib/queries/biological_association/filter.rb
+++ b/lib/queries/biological_association/filter.rb
@@ -584,15 +584,28 @@ def collecting_event_query_facet
def otu_query_facet
return nil if otu_query.nil?
s = 'WITH query_otu_ba AS (' + otu_query.all.to_sql + ') '
- ::BiologicalAssociation
a = ::BiologicalAssociation
- .joins("JOIN query_otu_ba as query_otu_ba1 on biological_associations.biological_association_subject_id = query_otu_ba1.id AND biological_associations.biological_association_subject_type = 'Otu'").to_sql
+ .joins("JOIN query_otu_ba as query_otu_ba1 on biological_associations.biological_association_subject_id = query_otu_ba1.id AND biological_associations.biological_association_subject_type = 'Otu'")
b = ::BiologicalAssociation
- .joins("JOIN query_otu_ba as query_otu_ba2 on biological_associations.biological_association_object_id = query_otu_ba2.id AND biological_associations.biological_association_object_type = 'Otu'").to_sql
+ .joins("JOIN query_otu_ba as query_otu_ba2 on biological_associations.biological_association_object_id = query_otu_ba2.id AND biological_associations.biological_association_object_type = 'Otu'")
- s << ::BiologicalAssociation.from("((#{a} UNION (#{b})) as biological_associations").to_sql
+ s << referenced_klass_union([a,b]).to_sql
+ ::BiologicalAssociation.from('(' + s + ') as biological_associations')
+ end
+
+ def asserted_distribution_query_facet
+ return nil if asserted_distribution_query.nil?
+ s = 'WITH query_ad_ba AS (' + asserted_distribution_query.all.to_sql + ') '
+
+ a = ::BiologicalAssociation
+ .joins("JOIN query_ad_ba as query_ad_ba1 on biological_associations.biological_association_subject_id = query_ad_ba1.otu_id AND biological_associations.biological_association_subject_type = 'Otu'")
+
+ b = ::BiologicalAssociation
+ .joins("JOIN query_ad_ba as query_ad_ba2 on biological_associations.biological_association_object_id = query_ad_ba2.otu_id AND biological_associations.biological_association_object_type = 'Otu'")
+
+ s << referenced_klass_union([a,b]).to_sql
::BiologicalAssociation.from('(' + s + ') as biological_associations')
end
@@ -601,12 +614,12 @@ def collection_object_query_facet
s = 'WITH query_co_ba AS (' + collection_object_query.all.to_sql + ') '
a = ::BiologicalAssociation
- .joins("JOIN query_co_ba as query_co_ba1 on biological_associations.biological_association_subject_id = query_co_ba1.id AND biological_associations.biological_association_subject_type = 'CollectionObject'").to_sql
+ .joins("JOIN query_co_ba as query_co_ba1 on biological_associations.biological_association_subject_id = query_co_ba1.id AND biological_associations.biological_association_subject_type = 'CollectionObject'")
b = ::BiologicalAssociation
- .joins("JOIN query_co_ba as query_co_ba2 on biological_associations.biological_association_object_id = query_co_ba2.id AND biological_associations.biological_association_object_type = 'CollectionObject'").to_sql
+ .joins("JOIN query_co_ba as query_co_ba2 on biological_associations.biological_association_object_id = query_co_ba2.id AND biological_associations.biological_association_object_type = 'CollectionObject'")
- s << ::BiologicalAssociation.from('(' + [a,b].collect{|q| "(#{q})"}.join(' UNION ') + ') as biological_associations').to_sql
+ s << referenced_klass_union([a,b]).to_sql
::BiologicalAssociation.from('(' + s + ') as biological_associations')
end
@@ -620,12 +633,10 @@ def taxon_name_query_facet
a = ::BiologicalAssociation
.joins("JOIN otus on otus.id = biological_associations.biological_association_subject_id AND biological_associations.biological_association_subject_type = 'Otu'")
.joins('JOIN query_tn_ba as query_tn_ba1 on otus.taxon_name_id = query_tn_ba1.id')
- .to_sql
b = ::BiologicalAssociation
.joins("JOIN otus on otus.id = biological_associations.biological_association_object_id AND biological_associations.biological_association_object_type = 'Otu'")
.joins('JOIN query_tn_ba as query_tn_ba2 on otus.taxon_name_id = query_tn_ba2.id')
- .to_sql
c = ::BiologicalAssociation
.joins("JOIN collection_objects on collection_objects.id = biological_associations.biological_association_subject_id AND biological_associations.biological_association_subject_type = 'CollectionObject'")
@@ -633,7 +644,6 @@ def taxon_name_query_facet
.joins('JOIN otus on otus.id = taxon_determinations.otu_id')
.joins('JOIN query_tn_ba as query_tn_ba3 on otus.taxon_name_id = query_tn_ba3.id')
.where('taxon_determinations.position = 1')
- .to_sql
d = ::BiologicalAssociation
.joins("JOIN collection_objects on collection_objects.id = biological_associations.biological_association_object_id AND biological_associations.biological_association_object_type = 'CollectionObject'")
@@ -641,9 +651,8 @@ def taxon_name_query_facet
.joins('JOIN otus on otus.id = taxon_determinations.otu_id')
.joins('JOIN query_tn_ba as query_tn_ba4 on otus.taxon_name_id = query_tn_ba4.id')
.where('taxon_determinations.position = 1')
- .to_sql
- s << ::BiologicalAssociation.from('(' + [a,b,c,d].collect{|q| "(#{q})"}.join(' UNION ') + ') as biological_associations').to_sql
+ s << referenced_klass_union([a,b,c,d]).to_sql
::BiologicalAssociation.from('(' + s + ') as biological_associations')
end
@@ -662,6 +671,7 @@ def and_clauses
def merge_clauses
[
+ asserted_distribution_query_facet,
collecting_event_query_facet,
collection_object_query_facet,
otu_query_facet,
diff --git a/lib/queries/collecting_event/filter.rb b/lib/queries/collecting_event/filter.rb
index d092b0a183..4081cfc18f 100644
--- a/lib/queries/collecting_event/filter.rb
+++ b/lib/queries/collecting_event/filter.rb
@@ -106,8 +106,8 @@ def self.base_params
# @return [Boolean]
# @param collector_id_or [String]
- # 'true' - all ids treated as "or"
- # 'false', nil - all ids treated as "and"
+ # `false`, nil - treat the ids in collector_id as "or"
+ # 'true' - treat the ids in collector_id as "and" (only CollectingEvent with all and only all of collector_id will match)
attr_accessor :collector_id_or
# @param collection_objects [String, nil]
diff --git a/lib/queries/collection_object/filter.rb b/lib/queries/collection_object/filter.rb
index c31c8f3a09..267a590744 100644
--- a/lib/queries/collection_object/filter.rb
+++ b/lib/queries/collection_object/filter.rb
@@ -240,8 +240,8 @@ class Filter < Query::Filter
# @return [Boolean]
# @param determiner_id_or [String, nil]
- # `false`, nil - treat ids as "or"
- # 'true' - treat ids as "and" (only collection objects with all and only all will match)
+ # `false`, nil - treat the ids in determiner_id as "or"
+ # 'true' - treat the ids in determiner_id as "and" (only collection objects with all and only all will match)
attr_accessor :determiner_id_or
# @return [String, nil]
@@ -289,6 +289,7 @@ class Filter < Query::Filter
attr_accessor :determiner_name_regex
# @return Array
+ # match all CollectionObjects that are the origin of these Extracts
attr_accessor :extract_id
# @return Boolean
@@ -320,10 +321,10 @@ def initialize(query_params)
@collectors = boolean_param(params, :collectors)
@collecting_event_id = params[:collecting_event_id]
@collection_object_id = params[:collection_object_id]
- @collection_object_type = params[:collection_object_type].blank? ? nil : params[:collection_object_type]
+ @collection_object_type = (params[:collection_object_type].presence)
@current_determinations = boolean_param(params, :current_determinations)
@current_repository = boolean_param(params, :current_repository)
- @current_repository_id = params[:current_repository_id].blank? ? nil : params[:current_repository_id]
+ @current_repository_id = (params[:current_repository_id].presence)
@dates = boolean_param(params, :dates)
@descendants = boolean_param(params, :descendants)
@determiners = boolean_param(params, :determiners)
@@ -347,12 +348,12 @@ def initialize(query_params)
@preparation_type = boolean_param(params, :preparation_type)
@preparation_type_id = params[:preparation_type_id]
@repository = boolean_param(params, :repository)
- @repository_id = params[:repository_id].blank? ? nil : params[:repository_id]
- @sled_image_id = params[:sled_image_id].blank? ? nil : params[:sled_image_id]
+ @repository_id = (params[:repository_id].presence)
+ @sled_image_id = (params[:sled_image_id].presence)
@taxon_determinations = boolean_param(params, :taxon_determinations)
@taxon_name_id = params[:taxon_name_id]
@type_material = boolean_param(params, :type_material)
- @type_specimen_taxon_name_id = params[:type_specimen_taxon_name_id].blank? ? nil : params[:type_specimen_taxon_name_id]
+ @type_specimen_taxon_name_id = (params[:type_specimen_taxon_name_id].presence)
@validity = boolean_param(params, :validity)
@with_buffered_collecting_event = boolean_param(params, :with_buffered_collecting_event)
@with_buffered_determinations = boolean_param(params, :with_buffered_determinations)
@@ -462,7 +463,7 @@ def determiner_facet
o = ::TaxonDetermination.arel_table
r = ::Role.arel_table
- a = o.alias("a_det__")
+ a = o.alias('a_det__')
b = o.project(a[Arel.star]).from(a)
c = r.alias('det_r1')
@@ -599,7 +600,7 @@ def geographic_area_facet
def biocuration_facet
return nil if biocuration_class_id.empty?
::CollectionObject::BiologicalCollectionObject.joins(:biocuration_classifications)
- .where(biocuration_classifications: {biocuration_class_id: biocuration_class_id})
+ .where(biocuration_classifications: {biocuration_class_id:})
end
def loan_facet
@@ -614,7 +615,7 @@ def type_facet
def sled_image_facet
return nil if sled_image_id.nil?
- ::CollectionObject::BiologicalCollectionObject.joins(:depictions).where("depictions.sled_image_id = ?", sled_image_id)
+ ::CollectionObject::BiologicalCollectionObject.joins(:depictions).where('depictions.sled_image_id = ?', sled_image_id)
end
def biological_relationship_id_facet
@@ -752,7 +753,7 @@ def taxon_name_id_facet
else
q = ::CollectionObject.joins(taxon_determinations: [:otu])
- .where(otus: {taxon_name_id: taxon_name_id})
+ .where(otus: {taxon_name_id:})
if current_determinations
q = q.where(taxon_determinations: {position: 1})
diff --git a/lib/queries/concerns/protocols.rb b/lib/queries/concerns/protocols.rb
index 1c77fe1d31..f06a2dae71 100644
--- a/lib/queries/concerns/protocols.rb
+++ b/lib/queries/concerns/protocols.rb
@@ -4,13 +4,13 @@ module Queries::Concerns::Protocols
extend ActiveSupport::Concern
- def self.params
+ def self.params
[
:protocols,
:protocol_id_or,
:protocol_id_and,
- :protocol_id, # TODO: unused? or maybe in polymorphics setters!!
- protocol_id: [], # TODO: unused? or maybe in polymorphics setters!!
+ :protocol_id, # TODO: unused? or maybe in polymorphics setters!!
+ protocol_id: [], # TODO: unused? or maybe in polymorphics setters!!
protocol_id_or: [],
protocol_id_and: [],
]
@@ -18,15 +18,20 @@ def self.params
included do
# @return [Array]
- # @params protocol_id_and [:protocol_id_and | [protocol_id_and, .. ] ]
+ # @params protocol_id_and
+ # match any objects linked to all Protocols referenced here
attr_accessor :protocol_id_and
# @return [Array]
- # @params protocol_id_or [:protocol_id_or | [protocol_id_or, .. ] ]
+ # @params keyword_id_or
+ # match any objects linked to any Protocol referenced here
attr_accessor :protocol_id_or
# @return [Boolean, nil]
# @params protocols ['true', 'false', nil]
+ # true - return objects that reference any Protocol
+ # false - return objects that reference no Protocol
+ # nil - ignored
attr_accessor :protocols
def protocol_id_and
@@ -81,7 +86,7 @@ def self.merge_clauses
:protocol_id_facet,
:protocols_facet,
]
- end
+ end
private
@@ -92,7 +97,7 @@ def matching_protocol_id_or
t = ::ProtocolRelationship.arel_table
w = t[:protocol_relationship_object_id].eq(table[:id]).and( t[:protocol_relationship_object_type].eq(table.name.classify))
- w = w.and( t[:protocol_id].eq_any(protocol_id_or) ) if protocol_id_or.any?
+ w = w.and( t[:protocol_id].eq_any(protocol_id_or) ) if protocol_id_or.any?
k.where( ::ProtocolRelationship.where(w).arel.exists )
end
diff --git a/lib/queries/concerns/tags.rb b/lib/queries/concerns/tags.rb
index c08615a3b5..528cd1f167 100644
--- a/lib/queries/concerns/tags.rb
+++ b/lib/queries/concerns/tags.rb
@@ -7,7 +7,7 @@ module Queries::Concerns::Tags
extend ActiveSupport::Concern
def self.params
- [
+ [
:keyword_id_and,
:keyword_id_or,
:tags,
@@ -18,11 +18,13 @@ def self.params
included do
# @return [Array]
- # @params keyword_id_and [:keyword_id_and | [keyword_id_and, .. ] ]
+ # @params keyword_id_and
+ # match all objects tagged with all of the keywords referenced in this array
attr_accessor :keyword_id_and
# @return [Array]
- # @params keyword_id_or [:keyword_id_or | [keyword_id_or, .. ] ]
+ # @params keyword_id_or
+ # match all objects tagged with any of the keywords referenced in this array
attr_accessor :keyword_id_or
# @return [Boolean, nil]
@@ -61,7 +63,7 @@ def keyword_id_or
end
# @return [Arel::Table]
- def tag_table
+ def tag_table
::Tag.arel_table
end
@@ -99,14 +101,14 @@ def tags_facet
.where(tags: {id: nil})
end
end
-
+
def matching_keyword_id_or
return nil if keyword_id_or.empty?
k = table.name.classify.safe_constantize
t = ::Tag.arel_table
w = t[:tag_object_id].eq(table[:id]).and( t[:tag_object_type].eq(table.name.classify))
- w = w.and( t[:keyword_id].eq_any(keyword_id_or) ) if keyword_id_or.any?
+ w = w.and( t[:keyword_id].eq_any(keyword_id_or) ) if keyword_id_or.any?
k.where( ::Tag.where(w).arel.exists )
end
@@ -144,4 +146,4 @@ def matching_keyword_id_and
k.joins(Arel::Nodes::InnerJoin.new(b, Arel::Nodes::On.new(b[:id].eq(table[:id]))))
end
-end
\ No newline at end of file
+end
diff --git a/lib/queries/image/filter.rb b/lib/queries/image/filter.rb
index fcbfa1eb1b..e06db08dd6 100644
--- a/lib/queries/image/filter.rb
+++ b/lib/queries/image/filter.rb
@@ -22,8 +22,6 @@ class Filter < Query::Filter
collection_object_id: [],
depiction_object_type: [],
image_id: [],
- keyword_id_and: [],
- keyword_id_or: [],
otu_id: [],
otu_scope: [],
sled_image_id: [],
@@ -72,7 +70,7 @@ class Filter < Query::Filter
#
# !! Must be used with an otu_id !!
# @param otu_scope
- # One or more of:
+ # One or more of:
# :all (default, includes all below)
#
# :otu (those on the OTU)
@@ -205,13 +203,13 @@ def biocuration_facet
return nil if biocuration_class_id.empty?
::Image.joins(collection_objects: [:depictions]).merge(
::CollectionObject::BiologicalCollectionObject.joins(:biocuration_classifications)
- .where(biocuration_classifications: {biocuration_class_id: biocuration_class_id})
+ .where(biocuration_classifications: {biocuration_class_id:})
)
end
def depiction_object_type_facet
return nil if depiction_object_type.empty?
- ::Image.joins(:depictions).where(depictions: {depiction_object_type: depiction_object_type})
+ ::Image.joins(:depictions).where(depictions: {depiction_object_type:})
end
def depictions_facet
diff --git a/lib/queries/otu/filter.rb b/lib/queries/otu/filter.rb
index a824c9c058..385fff8efa 100644
--- a/lib/queries/otu/filter.rb
+++ b/lib/queries/otu/filter.rb
@@ -419,7 +419,7 @@ def asserted_distribution_query_facet
.joins('JOIN query_ad_otus as query_ad_otus1 on otus.id = query_ad_otus1.otu_id')
.to_sql
- ::Otu.from('(' + s + ') as otus')
+ ::Otu.from('(' + s + ') as otus').distinct
end
def content_query_facet
@@ -429,7 +429,7 @@ def content_query_facet
.joins('JOIN query_con_otus as query_con_otus1 on otus.id = query_con_otus1.otu_id')
.to_sql
- ::Otu.from('(' + s + ') as otus')
+ ::Otu.from('(' + s + ') as otus').distinct
end
def biological_association_query_facet
@@ -437,12 +437,12 @@ def biological_association_query_facet
s = 'WITH query_ba_otu AS (' + biological_association_query.all.to_sql + ') '
a = ::Otu
- .joins("JOIN query_ba_otu as query_ba_otu1 on otus.id = query_ba_otu1.biological_association_subject_id AND query_ba_otu1.biological_association_subject_type = 'Otu'").to_sql
+ .joins("JOIN query_ba_otu as query_ba_otu1 on otus.id = query_ba_otu1.biological_association_subject_id AND query_ba_otu1.biological_association_subject_type = 'Otu'")
b = ::Otu
- .joins("JOIN query_ba_otu as query_ba_otu2 on otus.id = query_ba_otu2.biological_association_object_id AND query_ba_otu2.biological_association_object_type = 'Otu'").to_sql
+ .joins("JOIN query_ba_otu as query_ba_otu2 on otus.id = query_ba_otu2.biological_association_object_id AND query_ba_otu2.biological_association_object_type = 'Otu'")
- s << ::Otu.from("((#{a}) UNION (#{b})) as otus").to_sql
+ s << referenced_klass_union([a,b]).to_sql
::Otu.from('(' + s + ') as otus')
end
@@ -455,7 +455,7 @@ def collection_object_query_facet
.joins('JOIN query_co_otus as query_co_otus1 on collection_objects.id = query_co_otus1.id')
.to_sql
- ::Otu.from('(' + s + ') as otus')
+ ::Otu.from('(' + s + ') as otus').distinct
end
def collecting_event_query_facet
@@ -466,7 +466,7 @@ def collecting_event_query_facet
.joins('JOIN query_ce_otus as query_ce_otus1 on collecting_events.id = query_ce_otus1.id')
.to_sql
- ::Otu.from('(' + s + ') as otus')
+ ::Otu.from('(' + s + ') as otus').distinct
end
def extract_query_facet
@@ -477,7 +477,7 @@ def extract_query_facet
.joins("JOIN query_ex_otus as query_ex_otus1 on origin_relationships.new_object_id = query_ex_otus1.id and origin_relationships.new_object_type = 'Extract'")
.to_sql
- ::Otu.from('(' + s + ') as otus')
+ ::Otu.from('(' + s + ') as otus').distinct
end
def taxon_name_query_facet
@@ -488,7 +488,7 @@ def taxon_name_query_facet
.joins('JOIN query_taxon_names as query_taxon_names1 on otus.taxon_name_id = query_taxon_names1.id')
.to_sql
- ::Otu.from('(' + s + ') as otus')
+ ::Otu.from('(' + s + ') as otus').distinct
end
def descriptor_query_facet
@@ -499,7 +499,7 @@ def descriptor_query_facet
.joins('JOIN query_de_otus as query_de_otus1 on observations.descriptor_id = query_de_otus1.id')
.to_sql
- ::Otu.from('(' + s + ') as otus')
+ ::Otu.from('(' + s + ') as otus').distinct
end
def loan_query_facet
@@ -508,15 +508,13 @@ def loan_query_facet
a = ::Otu.joins(:loan_items)
.joins('JOIN query_loan_otus as query_loan_otus1 on loan_items.loan_id = query_loan_otus1.id')
- .to_sql
b = ::Otu.joins(collection_objects: [:loan_items])
.joins('JOIN query_loan_otus as query_loan_otus1 on loan_items.loan_id = query_loan_otus1.id')
- .to_sql
- s << ::Otu.from("((#{a}) UNION (#{b})) as otus").to_sql
+ s << referenced_klass_union([a,b]).to_sql
- ::Otu.from('(' + s + ') as otus')
+ ::Otu.from('(' + s + ') as otus').distinct
end
def observation_query_facet
diff --git a/lib/queries/person/autocomplete.rb b/lib/queries/person/autocomplete.rb
index 3cff1cac2d..3fd704b0c3 100644
--- a/lib/queries/person/autocomplete.rb
+++ b/lib/queries/person/autocomplete.rb
@@ -138,13 +138,6 @@ def autocomplete
.where("roles.project_id IN (#{pr_id}) OR project_sources.project_id IN (#{pr_id}) OR (roles.project_id NOT IN (#{pr_id}) AND project_sources.project_id NOT IN (#{pr_id})) OR (roles.project_id IS NULL AND project_sources.project_id IS NULL)")
.group('people.id')
.order('in_project, use_count DESC')
- elsif role_type.present?
- a = a.left_outer_joins(:roles)
- .joins("LEFT OUTER JOIN sources ON roles.role_object_id = sources.id AND roles.role_object_type = 'Source'")
- .joins('LEFT OUTER JOIN project_sources ON sources.id = project_sources.source_id')
- .select("people.*, COUNT(roles.id) AS use_count, CASE WHEN MAX(roles.project_id) IN (#{pr_id}) THEN MAX(roles.project_id) ELSE MAX(project_sources.project_id) END AS in_project")
- .group('people.id')
- .order('in_project_id, use_count DESC')
end
end
diff --git a/lib/queries/person/filter.rb b/lib/queries/person/filter.rb
index 6728f99acf..6fee62dc5f 100644
--- a/lib/queries/person/filter.rb
+++ b/lib/queries/person/filter.rb
@@ -31,8 +31,6 @@ class Filter < Query::Filter
exact: [],
except_project_id: [],
except_role: [],
- keyword_id_and: [],
- keyword_id_or: [],
only_project_id: [],
person_id: [],
role: [],
@@ -276,7 +274,7 @@ def regex_facet
end
def name_facet
- return nil if name.nil? || !levenshtein_cuttoff.blank?
+ return nil if name.nil? || levenshtein_cuttoff.present?
if exact.include?('name')
table[:cached].eq(name)
else
@@ -285,7 +283,7 @@ def name_facet
end
def last_name_starts_with_facet
- return nil if last_name_starts_with.blank? || !levenshtein_cuttoff.blank?
+ return nil if last_name_starts_with.blank? || levenshtein_cuttoff.present?
table[:last_name].matches(last_name_starts_with + '%')
end
@@ -363,7 +361,7 @@ def without_facet
end
def levenshtein_facet
- return nil unless levenshtein_cuttoff && (!name.blank?)
+ return nil unless levenshtein_cuttoff && (name.present?)
::Person.where(
levenshtein_distance(:cached, name).lteq(levenshtein_cuttoff).to_sql
)
diff --git a/lib/queries/query/filter.rb b/lib/queries/query/filter.rb
index 8890d87b5e..6327270d87 100644
--- a/lib/queries/query/filter.rb
+++ b/lib/queries/query/filter.rb
@@ -34,7 +34,7 @@ class Query::Filter < Queries::Query
# This is read as :to <- [:from1, from2...] ].
SUBQUERIES = {
asserted_distribution: [:source, :otu, :biological_association, :taxon_name],
- biological_association: [:source, :collecting_event, :otu, :collection_object, :taxon_name],
+ biological_association: [:source, :collecting_event, :otu, :collection_object, :taxon_name, :asserted_distribution],
collecting_event: [:source, :collection_object, :biological_association, :otu, :image, :taxon_name],
collection_object: [:source, :loan, :otu, :taxon_name, :collecting_event, :biological_association, :extract, :image, :observation],
content: [:source, :otu, :taxon_name, :image],
diff --git a/lib/queries/source/filter.rb b/lib/queries/source/filter.rb
index dfb91cc2ef..e0636f75a5 100644
--- a/lib/queries/source/filter.rb
+++ b/lib/queries/source/filter.rb
@@ -2,14 +2,14 @@ module Queries
module Source
class Filter < Query::Filter
- ATTRIBUTES = (::Source.core_attributes - %w{bibtex_type title author}).map(&:to_sym).freeze
+ ATTRIBUTES = (::Source.core_attributes - %w{bibtex_type title author}).map(&:to_sym).freeze
include Queries::Concerns::Attributes
include Queries::Concerns::Empty
include Queries::Concerns::Notes
include Queries::Concerns::Tags
-
+
PARAMS = [
*ATTRIBUTES,
:source_id,
@@ -38,8 +38,6 @@ class Filter < Query::Filter
bibtex_type: [],
citation_object_type: [],
empty: [],
- keyword_id_and: [],
- keyword_id_or: [],
not_empty: [],
serial_id: [],
source_id: [],
@@ -71,6 +69,8 @@ class Filter < Query::Filter
attr_accessor :author_id
# @params author [Boolean, nil]
+ # `false`, nil - treat the ids in author_id as "or"
+ # 'true' - treat the ids in author_id as "and" (only Sources with all and only all will match)
attr_accessor :author_id_or
# @params author [Array of Integer, Topic#id]
@@ -255,7 +255,7 @@ def source_type_facet
def year_facet
return nil if year_start.blank?
- if year_start && !year_end.blank?
+ if year_start && year_end.present?
table[:year].gteq(year_start)
.and(table[:year].lteq(year_end))
else # only start
@@ -272,7 +272,7 @@ def author_id_facet
o = table
r = ::Role.arel_table
- a = o.alias("a_")
+ a = o.alias('a_')
b = o.project(a[Arel.star]).from(a)
c = r.alias('r1')
@@ -297,7 +297,7 @@ def author_id_facet
def topic_id_facet
return nil if topic_id.empty?
- ::Source.joins(:citation_topics).where(citation_topics: { topic_id: topic_id }).distinct
+ ::Source.joins(:citation_topics).where(citation_topics: { topic_id: }).distinct
end
def in_project_facet
@@ -379,7 +379,7 @@ def serial_facet
def citation_object_type_facet
return nil if citation_object_type.empty?
::Source.joins(:citations)
- .where(citations: {citation_object_type: citation_object_type}).distinct
+ .where(citations: {citation_object_type:}).distinct
end
def nomenclature_facet
diff --git a/lib/queries/taxon_name/filter.rb b/lib/queries/taxon_name/filter.rb
index 816646f72c..ec583182ab 100644
--- a/lib/queries/taxon_name/filter.rb
+++ b/lib/queries/taxon_name/filter.rb
@@ -228,7 +228,8 @@ class Filter < Query::Filter
# @return [Boolean]
# @param [String]
- # 'true'
+ # `false`, nil - treat the ids in taxon_name_author_id as "or" (match any TaxonName with any of these authors)
+ # 'true' - treat the ids in taxon_name_author_id as "and" (only TaxonNames with all and only all will match)
attr_accessor :taxon_name_author_id_or
# @return [String, nil]
@@ -278,7 +279,7 @@ def initialize(query_params)
@parent_id = params[:parent_id]
@rank = params[:rank]
@sort = params[:sort]
- @taxon_name_author_id = params[:taxon_name_author_ids]
+ @taxon_name_author_id = params[:taxon_name_author_id]
@taxon_name_author_id_or = boolean_param(params, :taxon_name_author_id_or)
@taxon_name_classification = params[:taxon_name_classification] || []
@taxon_name_id = params[:taxon_name_id]
@@ -366,11 +367,11 @@ def nomenclature_code
def geo_json_facet
return nil if geo_json.nil?
- otus = ::Queries::Otu::Filter.new(geo_json: geo_json).all
- collection_objects = ::Queries::CollectionObject::Filter.new(geo_json: geo_json).all
+ otus = ::Queries::Otu::Filter.new(geo_json:).all
+ collection_objects = ::Queries::CollectionObject::Filter.new(geo_json:).all
a = ::TaxonName.joins(:taxon_taxon_determinations).where(taxon_determinations: { biological_collection_object: collection_objects} )
- b = ::TaxonName.joins(:otus).where(otus: otus)
+ b = ::TaxonName.joins(:otus).where(otus:)
::TaxonName.from("((#{a.to_sql}) UNION (#{b.to_sql})) as taxon_names")
end
@@ -378,11 +379,11 @@ def geo_json_facet
def not_specified_facet
return nil if not_specified.nil?
if not_specified
- ::TaxonName.where(table[:cached].matches("%NOT SPECIFIED%").or(
- table[:cached_original_combination].matches("%NOT SPECIFIED%")))
+ ::TaxonName.where(table[:cached].matches('%NOT SPECIFIED%').or(
+ table[:cached_original_combination].matches('%NOT SPECIFIED%')))
else
- ::TaxonName.where(table[:cached].does_not_match("%NOT SPECIFIED%").and(
- table[:cached_original_combination].does_not_match("%NOT SPECIFIED%")))
+ ::TaxonName.where(table[:cached].does_not_match('%NOT SPECIFIED%').and(
+ table[:cached_original_combination].does_not_match('%NOT SPECIFIED%')))
end
end
@@ -504,7 +505,7 @@ def taxon_name_author_id_facet
o = table
r = ::Role.arel_table
- a = o.alias("a_")
+ a = o.alias('a_')
b = o.project(a[Arel.star]).from(a)
c = r.alias('r1')
@@ -517,7 +518,7 @@ def taxon_name_author_id_facet
)
e = c[:id].not_eq(nil)
- f = c[:person_id].eq_any(taxon_name_author_ids)
+ f = c[:person_id].eq_any(taxon_name_author_id)
b = b.where(e.and(f))
b = b.group(a['id'])
@@ -626,7 +627,7 @@ def collecting_event_id_facet
return nil if collecting_event_id.empty?
::TaxonName
.joins(:collection_objects)
- .where(collection_objects: {collecting_event_id: collecting_event_id})
+ .where(collection_objects: {collecting_event_id:})
end
def combinations_facet
diff --git a/lib/queries/type_material/autocomplete.rb b/lib/queries/type_material/autocomplete.rb
new file mode 100644
index 0000000000..9c05e6c5fd
--- /dev/null
+++ b/lib/queries/type_material/autocomplete.rb
@@ -0,0 +1,38 @@
+module Queries
+ module TypeMaterial
+ class Autocomplete < Query::Autocomplete
+
+ # @return [String]
+ def where_sql
+ with_project_id.and(with_cached_taxon_name.or(with_cached_identifier)).to_sql
+ end
+
+ # @return [Scope]
+ def all
+ ::TypeMaterial.includes(:protonym, collection_object: [:identifiers] ).where(where_sql).references(:taxon_names).limit(dynamic_limit).all
+ end
+
+ # @return [Arel::Table]
+ def taxon_name_table
+ ::TaxonName.arel_table
+ end
+
+ # @return [Arel::Table]
+ def identifier_table
+ ::Identifier.arel_table
+ end
+
+ # source, material, prototonym
+ # @return [Arel::Nodes::Matches]
+ def with_cached_taxon_name
+ taxon_name_table[:cached].matches_any(terms)
+ end
+
+ # @return [Arel::Nodes::Matches]
+ def with_cached_identifier
+ identifier_table[:cached].matches_any(terms)
+ end
+
+ end
+ end
+end
\ No newline at end of file
diff --git a/lib/taxonworks/version.rb b/lib/taxonworks/version.rb
index 5f429b379a..5c50136335 100644
--- a/lib/taxonworks/version.rb
+++ b/lib/taxonworks/version.rb
@@ -1,3 +1,3 @@
module Taxonworks
- VERSION = "0.31.1"
+ VERSION = "0.31.2"
end