|
8 | 8 |
|
9 | 9 | <BrapiStudySelect |
10 | 10 | class="mt-3" |
| 11 | + v-model:study="study" |
11 | 12 | ref="brapiStudySelect" |
12 | 13 | /> |
| 14 | + |
| 15 | + <v-btn :text="$t('buttonReceiveData')" :prepend-icon="mdiCloudDownload" color="primary" variant="tonal" :disabled="!study" @click="pullData" /> |
| 16 | + |
| 17 | + <v-virtual-scroll |
| 18 | + max-height="25vh" |
| 19 | + class="my-3" |
| 20 | + :items="errors" |
| 21 | + > |
| 22 | + <template #default="{ item }"> |
| 23 | + <v-list-item :title="item" :prepend-icon="mdiAlertCircle" active active-class="text-error" /> |
| 24 | + </template> |
| 25 | + </v-virtual-scroll> |
| 26 | + |
| 27 | + <LayoutDimensions |
| 28 | + class="mt-3" |
| 29 | + v-model="layout" |
| 30 | + v-model:layout-type="layoutType" |
| 31 | + :is-edit="false" |
| 32 | + :can-change="false" |
| 33 | + v-if="layout" |
| 34 | + /> |
13 | 35 | </v-form> |
14 | 36 | </template> |
15 | 37 |
|
|
25 | 47 | <script setup lang="ts"> |
26 | 48 | import BrapiConfig from '@/components/util/BrapiConfig.vue' |
27 | 49 | import BrapiStudySelect from '@/components/util/BrapiStudySelect.vue' |
| 50 | + import { brapiDefaultCatchHandler, brapiGetObservationUnits } from '@/plugins/brapi' |
| 51 | + import type { Study } from '@/plugins/types/brapi' |
| 52 | + import type { TrialPlus, BrapiImportCell } from '@/plugins/types/client' |
| 53 | + import { CellCategory, DisplayOrder, type Cell, type Layout } from '@/plugins/types/gridscore' |
| 54 | + import { getColumnIndex, getRowIndex, isNumber } from '@/plugins/util' |
| 55 | + import { mdiAlertCircle, mdiCloudDownload } from '@mdi/js' |
28 | 56 |
|
| 57 | + import emitter from 'tiny-emitter/instance' |
| 58 | + import { useI18n } from 'vue-i18n' |
| 59 | +
|
| 60 | + const { t } = useI18n() |
| 61 | +
|
| 62 | + const trial = defineModel<TrialPlus>() |
29 | 63 | const dialog = ref(false) |
30 | | - const canContinue = computed(() => false) |
| 64 | + const layout = ref<Layout>() |
| 65 | + const study = ref<Study>() |
| 66 | + const layoutType = ref<'grid' | 'list'>('grid') |
| 67 | + const errors = ref<string[]>([]) |
| 68 | + const cells = ref<BrapiImportCell[]>([]) |
| 69 | +
|
| 70 | + const canContinue = computed(() => study.value !== undefined && trial.value !== undefined && cells.value.length > 0) |
31 | 71 |
|
32 | 72 | const brapiStudySelect = useTemplateRef('brapiStudySelect') |
33 | 73 |
|
| 74 | + function pullData () { |
| 75 | + errors.value = [] |
| 76 | + layout.value = undefined |
| 77 | + emitter.emit('show-loading', true) |
| 78 | +
|
| 79 | + if (study.value) { |
| 80 | + brapiGetObservationUnits(study.value.studyDbId) |
| 81 | + .then(result => { |
| 82 | + const rows = new Set<number>() |
| 83 | + const columns = new Set<number>() |
| 84 | + cells.value = [] |
| 85 | +
|
| 86 | + result.forEach(ou => { |
| 87 | + if (ou.observationUnitPosition && ou.observationUnitPosition.positionCoordinateX && ou.observationUnitPosition.positionCoordinateY) { |
| 88 | + let columnIndex: number | undefined = undefined |
| 89 | + let rowIndex: number | undefined = undefined |
| 90 | + let germplasmIdentifier = undefined |
| 91 | + let rep = undefined |
| 92 | + let brapiId = undefined |
| 93 | + let control = undefined |
| 94 | +
|
| 95 | + if (ou.observationUnitPosition.positionCoordinateXType === 'GRID_COL' && isNumber(ou.observationUnitPosition.positionCoordinateX, true)) { |
| 96 | + columnIndex = +ou.observationUnitPosition.positionCoordinateX |
| 97 | + columns.add(columnIndex) |
| 98 | + } else { |
| 99 | + errors.value.push(t('widgetBrapiTrialImportErrorNoColumnInformation', { germplasm: ou.germplasmName || ou.observationUnitDbId })) |
| 100 | + } |
| 101 | + if (ou.observationUnitPosition.positionCoordinateYType === 'GRID_ROW' && isNumber(ou.observationUnitPosition.positionCoordinateY, true)) { |
| 102 | + rowIndex = +ou.observationUnitPosition.positionCoordinateY |
| 103 | + rows.add(rowIndex) |
| 104 | + } else { |
| 105 | + errors.value.push(t('widgetBrapiTrialImportErrorNoRowInformation', { germplasm: ou.germplasmName || ou.observationUnitDbId })) |
| 106 | + } |
| 107 | + if (ou.observationUnitName) { |
| 108 | + germplasmIdentifier = ou.observationUnitName |
| 109 | + } else if (ou.germplasmName) { |
| 110 | + germplasmIdentifier = ou.germplasmName |
| 111 | + } else { |
| 112 | + errors.value.push(t('widgetBrapiTrialImportErrorNoGermplasmName', { germplasm: ou.observationUnitDbId })) |
| 113 | + } |
| 114 | + if (ou.germplasmDbId) { |
| 115 | + brapiId = ou.germplasmDbId |
| 116 | + } else { |
| 117 | + errors.value.push(t('widgetBrapiTrialImportErrorNoGermplasmDbId', { germplasm: ou.observationUnitDbId })) |
| 118 | + } |
| 119 | + if (ou.observationUnitPosition.observationLevel && ou.observationUnitPosition.observationLevel.levelName === 'rep') { |
| 120 | + rep = ou.observationUnitPosition.observationLevel.levelCode |
| 121 | + } |
| 122 | + if (ou.observationUnitPosition.entryType && ou.observationUnitPosition.entryType === 'CHECK') { |
| 123 | + control = true |
| 124 | + } |
| 125 | +
|
| 126 | + if (germplasmIdentifier && columnIndex !== undefined && rowIndex !== undefined && brapiId) { |
| 127 | + cells.value.push({ |
| 128 | + germplasm: germplasmIdentifier, |
| 129 | + rep, |
| 130 | + brapiId, |
| 131 | + row: rowIndex, |
| 132 | + column: columnIndex, |
| 133 | + categories: control ? [CellCategory.CONTROL] : [], |
| 134 | + }) |
| 135 | + } |
| 136 | + } else { |
| 137 | + errors.value.push(t('widgetBrapiTrialImportErrorNoPlotInformation', { germplasm: ou.germplasmName || ou.observationUnitDbId })) |
| 138 | + } |
| 139 | + }) |
| 140 | +
|
| 141 | + if (rows.size > 0 && columns.size > 0 && cells.value.length > 0) { |
| 142 | + layout.value = { |
| 143 | + rows: rows.size, |
| 144 | + columns: columns.size, |
| 145 | + rowLabels: [...rows].sort((a, b) => a - b), |
| 146 | + columnLabels: [...columns].sort((a, b) => a - b), |
| 147 | + columnOrder: DisplayOrder.LEFT_TO_RIGHT, |
| 148 | + rowOrder: DisplayOrder.TOP_TO_BOTTOM, |
| 149 | + } |
| 150 | + } |
| 151 | + }) |
| 152 | + .catch(brapiDefaultCatchHandler) |
| 153 | + .finally(() => emitter.emit('show-loading', false)) |
| 154 | + } |
| 155 | + } |
| 156 | +
|
34 | 157 | function getPrograms () { |
35 | 158 | brapiStudySelect.value?.updatePrograms() |
36 | 159 | } |
|
42 | 165 | dialog.value = false |
43 | 166 | } |
44 | 167 | function save () { |
45 | | - hide() |
| 168 | + const ll = layout.value |
| 169 | + if (trial.value && study.value && ll) { |
| 170 | + trial.value.name = study.value.studyName |
| 171 | + trial.value.description = study.value.studyDescription |
| 172 | + trial.value.layout = JSON.parse(JSON.stringify(ll)) |
| 173 | +
|
| 174 | + const data: { [index: string]: Cell } = {} |
| 175 | +
|
| 176 | + cells.value.forEach(c => { |
| 177 | + const row = getRowIndex(ll, c.row) |
| 178 | + const column = getColumnIndex(ll, c.column) |
| 179 | + data[`${row}|${column}`] = { |
| 180 | + germplasm: c.germplasm, |
| 181 | + categories: c.categories || [], |
| 182 | + isMarked: false, |
| 183 | + brapiId: c.brapiId, |
| 184 | + measurements: {}, |
| 185 | + comments: [], |
| 186 | + } |
| 187 | + }) |
| 188 | +
|
| 189 | + trial.value.data = data |
| 190 | +
|
| 191 | + hide() |
| 192 | + } |
46 | 193 | } |
47 | 194 |
|
48 | 195 | defineExpose({ |
|
0 commit comments