Skip to content

Commit

Permalink
- ADD: Added germplasm match search page.
Browse files Browse the repository at this point in the history
  • Loading branch information
sebastian-raubach committed Dec 16, 2024
1 parent c1e55dd commit 8b94d63
Show file tree
Hide file tree
Showing 7 changed files with 166 additions and 4 deletions.
4 changes: 3 additions & 1 deletion src/components/dropdowns/UserSettingsDropdown.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
<b-dropdown-item :to="{ name: Pages.userPermissions }" v-if="userIsAtLeast(storeToken.userType, USER_TYPE_ADMINISTRATOR)"><span class="text-warning"><MdiIcon :path="mdiAccountKey"/></span> {{ $t('dropdownUserSettingsUserPermissions') }}</b-dropdown-item>
<b-dropdown-item v-if="storeServerSettings.dataImportMode !== 'NONE'" :to="{ name: Pages.importUpload }"><span class="text-warning"><MdiIcon :path="mdiUpload"/></span> {{ $t('dropdownUserSettingsDataUpload') }}</b-dropdown-item>
<b-dropdown-item :to="{ name: Pages.germplasmUnifier }"><span class="text-warning"><MdiIcon :path="mdiSetMerge"/></span> {{ $t('dropdownUserSettingsGermplasmUnifier') }}</b-dropdown-item>
<b-dropdown-item :to="{ name: Pages.germplasmMatch }"><span class="text-warning"><MdiIcon :path="mdiTextSearch"/></span> {{ $t('dropdownUserSettingsGermplasmMatchSearch') }}</b-dropdown-item>
<b-dropdown-item :to="{ name: Pages.userFeedback }" v-if="storeServerSettings.supportsFeedback"><span class="text-warning"><MdiIcon :path="mdiCommentQuoteOutline"/></span> {{ $t('dropdownUserSettingsUserFeedback') }}</b-dropdown-item>
</template>
<!-- Settings -->
Expand All @@ -34,7 +35,7 @@ import GetTokenModal from '@/components/modals/GetTokenModal'
import MdiIcon from '@/components/icons/MdiIcon'
import { userIsAtLeast, apiDeleteToken, apiPostToken, USER_TYPE_ADMINISTRATOR, USER_TYPE_DATA_CURATOR } from '@/mixins/api/auth'
import { mdiAccount, mdiCog, mdiAccountKey, mdiUpload, mdiCircleMultiple, mdiSetMerge, mdiLogoutVariant, mdiLoginVariant, mdiCommentQuoteOutline } from '@mdi/js'
import { mdiAccount, mdiCog, mdiAccountKey, mdiUpload, mdiCircleMultiple, mdiSetMerge, mdiLogoutVariant, mdiLoginVariant, mdiCommentQuoteOutline, mdiTextSearch } from '@mdi/js'
import { Pages } from '@/mixins/pages'
const emitter = require('tiny-emitter/instance')
Expand All @@ -56,6 +57,7 @@ export default {
mdiLogoutVariant,
mdiLoginVariant,
mdiCommentQuoteOutline,
mdiTextSearch,
enabled: true,
USER_TYPE_ADMINISTRATOR,
USER_TYPE_DATA_CURATOR
Expand Down
6 changes: 3 additions & 3 deletions src/components/tables/BaseTable.vue
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@
<div v-else />
<!-- Row count -->
<template v-if="currentRequestData !== null && pagination.totalCount >= 0">
<div v-if="showAllItems !== true" class="d-flex mx-2 mb-1" id="table-row-count">{{ $tc('paginationCountCustom', pagination.totalCount, { from: (currentRequestData.page * currentRequestData.limit + 1).toLocaleString(), to: (Math.min((currentRequestData.page + 1) * currentRequestData.limit, pagination.totalCount)).toLocaleString(), count: pagination.totalCount.toLocaleString() }) }}</div>
<div v-else class="d-flex mx-2 mb-1" id="table-row-count">{{ $tc('paginationCountCustom', pagination.totalCount, { from: 1, to: (Math.min((currentRequestData.page + 1) * currentRequestData.limit, pagination.totalCount)).toLocaleString(), count: pagination.totalCount.toLocaleString() }) }}</div>
<div v-if="showAllItems" class="d-flex mx-2 mb-1" id="table-row-count">{{ $tc('paginationCountCustom', pagination.totalCount, { from: 1, to: pagination.totalCount.toLocaleString(), count: pagination.totalCount.toLocaleString() }) }}</div>
<div v-else class="d-flex mx-2 mb-1" id="table-row-count">{{ $tc('paginationCountCustom', pagination.totalCount, { from: (currentRequestData.page * currentRequestData.limit + 1).toLocaleString(), to: (Math.min((currentRequestData.page + 1) * currentRequestData.limit, pagination.totalCount)).toLocaleString(), count: pagination.totalCount.toLocaleString() }) }}</div>
</template>
</div>
<!-- Progress bar below it all that indicates the loading state -->
Expand Down Expand Up @@ -162,7 +162,7 @@
</div>

<!-- Page indicator and pagination -->
<div class="d-flex">
<div class="d-flex" v-if="!showAllItems">
<b-button-group class="table-pagination" v-show="pagination.totalCount > storeTablePerPage">
<b-button class="text-primary page-link" @click="showJumpToPage" id="table-jump-to-page"><MdiIcon :path="mdiBookOpenPageVariant" /> {{ $t('paginationPageCustom', { from: pagination.currentPage, to: maxPage }) }}</b-button>
<b-pagination v-model="pagination.currentPage"
Expand Down
4 changes: 4 additions & 0 deletions src/components/tables/GermplasmTable.vue
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,10 @@ export default {
tableMode: {
type: String,
default: 'base'
},
showAllItems: {
type: Boolean,
default: null
}
},
data: function () {
Expand Down
1 change: 1 addition & 0 deletions src/mixins/pages.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const Pages = Object.freeze({
germinateSettings: 'germinate-settings',
germplasm: 'germplasm',
germplasmUnifier: 'germplasm-unifier',
germplasmMatch: 'germplasm-match',
passport: 'passport',
climates: 'climates',
climateDetails: 'climate-details',
Expand Down
8 changes: 8 additions & 0 deletions src/plugins/i18n/en_GB.json
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@
"dropdownUserSettingsUserPermissions": "User permissions",
"dropdownUserSettingsDataUpload": "Data uploader",
"dropdownUserSettingsGermplasmUnifier": "Germplasm unifier",
"dropdownUserSettingsGermplasmMatchSearch": "Germplasm match search",
"dropdownUserSettingsGerminateSettings": "Germinate settings",
"dropdownUserSettingsGetToken": "Get access token",
"dropdownLabelGermplasmSearch": "{germplasm}, Rep: {rep}, Block: {block}, Treatment: {treatment}, Row: {row}, Column: {column}",
Expand Down Expand Up @@ -787,6 +788,13 @@
"pageGermplasmUnifierSgoneImportTitle": "SGONE import",
"pageGermplasmUnifierSgoneImportText": "SGONE is a tool for identifying potential duplicates in your data. The output from SGONE can be directly imported into Germinate to automate the germplasm unification. Just load the SGONE output below and hit 'merge'.",
"pageGermplasmUnifierSgoneLink": "SGONE is available at: <a rel='noopener noreferrer' target='_blank' href='https://cropgeeks.github.io/sgone'>https://cropgeeks.github.io/sgone</a>.",
"pageGermplasmMatchTitle": "Germplasm match search",
"pageGermplasmMatchText": "On this page, you can paste a number of primary identifiers into the box to search for matches. Germinate will return any matches in the table and any identifiers not found in the box below.",
"pageGermplasmMatchSearchCount": "Searched for: {search}, found: {result}.",
"formLabelGermplasmMatchSearch": "Identifiers to search for",
"formDescriptionGermplasmMatchSearch": "Paste any identifiers you want to search for here. One identifier per row.",
"formLabelGermplasmMatchNotFound": "Identifiers not found",
"formDescriptionGermplasmMatchNotFound": "These identifiers have not been found in the database.",
"pageGroupsDescriptionTitle": "Group description",
"pageGroupsMembersTitle": "Group members",
"pageGroupsPublicationsText": "This is a list of all publications referencing this group.",
Expand Down
7 changes: 7 additions & 0 deletions src/router/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,13 @@ const routes = [
component: () => import(/* webpackChunkName: "germplasm" */ '@/views/data/germplasm/Germplasm.vue'),
beforeEnter: requireAuth
},
{
path: 'germplasm-match',
name: Pages.germplasmMatch,
meta: { minUserType: USER_TYPE_DATA_CURATOR },
component: () => import(/* webpackChunkName: "germplasm-match" */ '@/views/data/germplasm/GermplasmMatch.vue'),
beforeEnter: requireAuth
},
{
path: 'germplasm-unifier',
name: Pages.germplasmUnifier,
Expand Down
140 changes: 140 additions & 0 deletions src/views/data/germplasm/GermplasmMatch.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
<template>
<div>
<h1>{{ $t('pageGermplasmMatchTitle') }}</h1>
<hr />
<p v-html="$t('pageGermplasmMatchText')" />

<b-form @submit.prevent="refresh">
<b-form-group :label="$t('formLabelGermplasmMatchSearch')" :description="$t('formDescriptionGermplasmMatchSearch')" label-for="germplasmmatch">
<b-form-textarea v-model="search" id="germplasmmatch" :rows="10" />
</b-form-group>
</b-form>

<b-button @click="refresh" variant="primary" class="mb-3"><MdiIcon :path="mdiRefresh" /> {{ $t('buttonUpdate') }}</b-button>

<div v-if="filterOn && filterOn.length > 0">
<p v-if="searchTerms && searchTerms.length > 0 && germplasm && germplasm.length > 0">
{{ $t('pageGermplasmMatchSearchCount', { search: searchTerms.length, result: germplasm.length } ) }}
</p>

<b-form-group :label="$t('formLabelGermplasmMatchNotFound')" :description="$t('formDescriptionGermplasmMatchNotFound')" label-for="notfound">
<b-form-textarea :value="notFound" id="notfound" :rows="10" />
</b-form-group>

<!-- Table showing all germplasm matches -->
<GermplasmTable showAllItems :getData="getData" :getIds="getIds" :downloadTable="downloadFunction" ref="germplasmTable" />
</div>
</div>
</template>

<script>
import MdiIcon from '@/components/icons/MdiIcon'
import GermplasmTable from '@/components/tables/GermplasmTable'
import { MAX_JAVA_INTEGER } from '@/mixins/api/base'
import { apiPostGermplasmTable, apiPostGermplasmTableIds } from '@/mixins/api/germplasm.js'
import { apiPostTableExport } from '@/mixins/api/misc.js'
import { mdiRefresh } from '@mdi/js'
export default {
components: {
GermplasmTable,
MdiIcon
},
data: function () {
return {
mdiRefresh,
filterOn: [],
search: null,
searchTerms: [],
germplasm: []
}
},
computed: {
downloadFunction: function () {
return this.downloadTable
},
notFound: function () {
if (this.germplasm && this.germplasm.length > 0 && this.searchTerms && this.searchTerms.length > 0) {
const set = new Set(this.searchTerms)
this.germplasm.forEach(g => set.delete(g.germplasmName))
return [...set].join('\n')
} else {
return null
}
}
},
methods: {
refresh: function () {
if (this.search) {
const set = new Set(this.search.split(/\r?\n/).filter(s => s).map(s => s.trim()))
this.searchTerms = [...set]
this.filterOn = [{
column: 'germplasmName',
comparator: 'inSet',
operator: 'and',
values: this.searchTerms
}]
this.$nextTick(() => this.$refs.germplasmTable.refresh())
} else {
this.searchTerms = []
this.filterOn = []
}
},
resetFilter: function (update) {
if (update.filter.length === 0) {
this.filterOn = []
}
},
adjustFilter: function (data) {
const copy = JSON.parse(JSON.stringify(data))
if (copy.filter) {
copy.filter = this.filterOn.concat(copy.filter)
} else {
copy.filter = this.filterOn.concat()
}
return copy
},
downloadTable: function (data, callback) {
const copy = this.adjustFilter(data)
return apiPostTableExport({ filter: copy.filter }, 'germplasm', callback)
},
getData: function (data, callback) {
this.germplasm = []
const copy = this.adjustFilter(data)
copy.page = 1
copy.limit = MAX_JAVA_INTEGER
return new Promise((resolve, reject) => {
apiPostGermplasmTable(copy, callback)
.then(r => {
if (r.data && r.data.data) {
this.germplasm = JSON.parse(JSON.stringify(r.data.data))
} else {
this.germplasm = []
}
resolve(r)
})
.catch(e => reject(e))
})
},
getIds: function (data, callback) {
const copy = this.adjustFilter(data)
return apiPostGermplasmTableIds(copy, callback)
},
onDownloadTableClicked: function () {
this.$refs.germplasmTable.onDownloadTableClicked()
}
}
}
</script>

<style>
</style>

0 comments on commit 8b94d63

Please sign in to comment.