app/javascript/vue/tasks/observation_matrices/dashboard/components/table.vue
<template>
<div class="full_width">
<spinner-component
v-if="sorting"
:full-screen="true"
legend="Loading..."
/>
<div class="flex-separate margin-small-bottom">
<div class="horizontal-left-content">
<button
class="button normal-input button-default margin-small-right"
type="button"
@click="selectAll"
>
Select all
</button>
<button
class="button normal-input button-default margin-small-right"
type="button"
@click="unselect"
>
Unselect all
</button>
<add-to-matrix
class="margin-small-right"
:otu-ids="selectedIds"
/>
<button-interactive-key
class="margin-small-right"
:otu-ids="selectedIds"
/>
<button-edit-image-matrix
class="margin-small-right"
:otu-ids="selectedIds"
@on-create="openImageMatrix"
/>
<button-image-matrix :otu-ids="selectedIds" />
</div>
<ul class="no_bullets context-menu">
<li>
<label class="middle">
<input
v-model="withOtus"
type="checkbox"
/>
Show taxon names with OTUs only
</label>
</li>
<li class="horizontal-left-content">
<div class="header-box middle separate-right">
<span v-if="taxon">Scoped: {{ taxon.name }}</span>
</div>
<div class="header-box middle separate-left">
<select
v-model="selectedFieldset"
class="normal-input"
>
<option
v-for="(field, key) in fieldset"
:key="key"
:value="key"
>
{{ key }}
</option>
</select>
</div>
</li>
</ul>
</div>
<table
class="full_width"
v-if="tableRanks"
>
<thead>
<tr>
<th>Selected</th>
<th>OTU name</th>
<template
v-for="header in fieldset[selectedFieldset]"
:key="header"
>
<th @click="sortBy(header)">
<span v-html="header.replace('_', '<br>')" />
</th>
</template>
<th>Code</th>
</tr>
</thead>
<tbody>
<template
v-for="(row, index) in renderList.data"
:key="row.taxon_name_id"
>
<tr
class="contextMenuCells"
:class="{ even: index % 2 }"
>
<td>
<input
:disabled="!row.otu_id"
:value="row.otu_id"
v-model="selectedIds"
type="checkbox"
/>
</td>
<td v-html="otuLabel(row)" />
<template
v-for="header in fieldset[selectedFieldset]"
:key="header"
>
<td>
{{ row[header] }}
</td>
</template>
<td>
<modal-list
:otu-id="getValueFromTable('otu_id', index)"
:taxon-name-id="getValueFromTable('taxon_name_id', index)"
/>
</td>
</tr>
</template>
</tbody>
</table>
</div>
</template>
<script>
import { GetterNames } from '../store/getters/getters'
import { RouteNames } from '@/routes/routes'
import ModalList from './modalList'
import SpinnerComponent from '@/components/ui/VSpinner'
import AddToMatrix from './addToMatrix'
import ButtonImageMatrix from './buttonImageMatrix.vue'
import ButtonEditImageMatrix from './ButtonEditImageMatrix.vue'
import ButtonInteractiveKey from './ButtonInteractiveKey.vue'
export default {
components: {
ModalList,
SpinnerComponent,
AddToMatrix,
ButtonImageMatrix,
ButtonEditImageMatrix,
ButtonInteractiveKey
},
props: {
tableList: {
type: Object,
default: () => ({})
},
filter: {
type: Object,
default: undefined
}
},
computed: {
rankList() {
return this.$store.getters[GetterNames.GetRanks]
},
taxon() {
return this.$store.getters[GetterNames.GetTaxon]
},
renderList() {
const data = (
this.withOtus
? this.tableRanks.data.filter((item) => item[4])
: this.tableRanks.data
).map((row) =>
Object.fromEntries(
row.map((value, index) => [
this.tableRanks.column_headers[index],
value
])
)
)
return {
column_headers: this.tableRanks.column_headers,
data
}
}
},
data() {
return {
renderFromPosition: 6,
rankNames: [],
tableRanks: {
data: []
},
fieldset: {
observations: [
'descriptors_scored_for_otus',
'otu_observation_count',
'otu_observation_depictions'
]
},
selectedFieldset: 'observations',
ascending: false,
sorting: false,
withOtus: false,
selectedIds: []
}
},
watch: {
rankList: {
handler(newVal) {
this.rankNames = [...new Set(this.getRankNames(newVal))]
},
deep: true
},
tableList: {
handler(newVal) {
this.sorting = true
this.selectedIds = []
setTimeout(() => {
this.tableRanks = this.tableList
this.$nextTick(() => {
this.sorting = false
})
}, 50)
}
}
},
methods: {
getRankNames(list, nameList = []) {
for (const key in list) {
if (typeof list[key] === 'object') {
this.getRankNames(list[key], nameList)
} else {
if (key === 'name') {
nameList.push(list[key])
}
}
}
return nameList
},
getValueFromTable(header, rowIndex) {
const otuIndex = this.tableRanks.column_headers.findIndex(
(item) => item === header
)
return this.tableRanks.data[rowIndex][otuIndex]
},
sortBy(headerName) {
this.sorting = true
setTimeout(() => {
const index = this.tableRanks.column_headers.findIndex(
(item) => item === headerName
)
this.tableRanks.data.sort((a, b) => {
return this.ascending
? (a[index] === null) - (b[index] === null) ||
+(a[index] > b[index]) ||
-(a[index] < b[index])
: (a[index] === null) - (b[index] === null) ||
-(a[index] > b[index]) ||
+(a[index] < b[index])
})
this.ascending = !this.ascending
this.$nextTick(() => {
this.sorting = false
})
}, 50)
},
unselect() {
this.selectedIds = []
},
selectAll() {
this.selectedIds = this.renderList.data
.filter((column) => column.otu_id)
.map((column) => column.otu_id)
},
openImageMatrix({ matrixId, otuIds }) {
window.open(
`${
RouteNames.ImageMatrix
}?observation_matrix_id=${matrixId}&edit=true&otu_filter=${otuIds.join(
'|'
)}`,
'_blank'
)
this.showModal = false
},
getValidMark(isValid) {
return isValid ? '✓' : '❌'
},
otuLabel(row) {
return `
<a href="/tasks/otus/browse?otu_id=${row.otu_id}">
<span class="otu_tag">
<span
class="otu_tag_otu_name"
title="${row.otu_id}">${row.otu_name || ''}
</span>
<span
class="otu_tag_taxon_name"
title="${row.taxon_name_id}"
>
<i>${row.cached}</i> ${row.cached_author_year || ''}
</span> ${this.getValidMark(row.cached_is_valid)}
</span>
</a>`
}
}
}
</script>