1
0
mirror of https://github.com/pcvolkmer/grz-metadata-processor.git synced 2025-07-01 20:12:54 +00:00

feat: add lab data profiles

This commit is contained in:
2025-06-09 14:44:18 +02:00
parent 74870b58e3
commit 844717e2ce
7 changed files with 241 additions and 9 deletions

View File

@ -1,6 +1,7 @@
package dev.pcvolkmer.onco.grzmetadataprocessor.data
import org.springframework.data.annotation.Id
import org.springframework.data.annotation.Transient
import org.springframework.data.relational.core.mapping.Table
import org.springframework.data.repository.CrudRepository
@ -15,6 +16,7 @@ data class LabData(
val sequenceType: SequenceType? = null,
val sequenceSubtype: SequenceSubtype? = null,
val fragmentationMethod: FragmentationMethod? = null,
val profile: Long? = null,
val libraryType: LibraryType? = null,
val libraryPrepKit: String = "",
val libraryPrepKitManufacturer: String = "",
@ -30,7 +32,10 @@ data class LabData(
val bioinformaticsPipelineName: String = "",
val bioinformaticsPipelineVersion: String = "",
val referenceGenome: ReferenceGenome? = null,
)
) {
@Transient
var profileData: LabDataProfile? = null
}
enum class SampleConservation(val value: String) {
FRESH_TISSUE("fresh-tissue"),

View File

@ -0,0 +1,22 @@
package dev.pcvolkmer.onco.grzmetadataprocessor.data
import org.springframework.data.annotation.Id
import org.springframework.data.relational.core.mapping.Table
import org.springframework.data.repository.CrudRepository
@Table("tbl_lab_data_profile")
data class LabDataProfile(
@Id val id: Long? = null,
val profileName: String = "",
val libraryType: LibraryType? = null,
val libraryPrepKit: String = "",
val libraryPrepKitManufacturer: String = "",
val sequencerModel: String = "",
val sequencerManufacturer: String = "",
val kitName: String = "",
val kitManufacturer: String = "",
val enrichmentKit: String = "",
val enrichmentKitManufacturer: EnrichmentKitManufacturer? = null
)
interface LabDataProfileRepository : CrudRepository<LabDataProfile, Long>

View File

@ -1,6 +1,7 @@
package dev.pcvolkmer.onco.grzmetadataprocessor.web
import dev.pcvolkmer.onco.grzmetadataprocessor.data.LabData
import dev.pcvolkmer.onco.grzmetadataprocessor.data.LabDataProfileRepository
import dev.pcvolkmer.onco.grzmetadataprocessor.data.LabDataRepository
import org.springframework.stereotype.Controller
import org.springframework.ui.Model
@ -9,34 +10,44 @@ import org.springframework.web.bind.annotation.*
@Controller
@RequestMapping("/donors/{donorId}/labdatas")
class LabDataController(
private val repository: LabDataRepository
private val labDataRepository: LabDataRepository,
private val labDataProfileRepository: LabDataProfileRepository
) {
@GetMapping
fun getAllLabData(@PathVariable donorId: Long, model: Model): String {
model.addAttribute("labdatas", repository.findByDonorId(donorId))
model.addAttribute("labdatas", allLabDatasByDonorId(donorId))
model.addAttribute("labdataprofiles", labDataProfileRepository.findAll())
return "labdatas"
}
@PostMapping
fun postLabData(@PathVariable donorId: Long, model: Model): String {
repository.save(LabData(donorId = donorId))
model.addAttribute("labdatas", repository.findByDonorId(donorId))
labDataRepository.save(LabData(donorId = donorId))
model.addAttribute("labdatas", allLabDatasByDonorId(donorId))
model.addAttribute("labdataprofiles", labDataProfileRepository.findAll())
return "labdatas"
}
@PutMapping(path = ["{labdataId}"])
fun putLabData(@PathVariable donorId: Long, labData: LabData, model: Model): String {
repository.save(labData)
model.addAttribute("labdatas", repository.findByDonorId(donorId))
labDataRepository.save(labData)
model.addAttribute("labdatas", allLabDatasByDonorId(donorId))
model.addAttribute("labdataprofiles", labDataProfileRepository.findAll())
return "labdatas"
}
@DeleteMapping(path = ["{labdataId}"])
fun deleteLabData(@PathVariable donorId: Long, @PathVariable labdataId: Long, model: Model): String {
repository.deleteById(labdataId)
model.addAttribute("labdatas", repository.findByDonorId(donorId))
labDataRepository.deleteById(labdataId)
model.addAttribute("labdatas", allLabDatasByDonorId(donorId))
model.addAttribute("labdataprofiles", labDataProfileRepository.findAll())
return "labdatas"
}
private fun allLabDatasByDonorId(donorId: Long): List<LabData> {
return labDataRepository.findByDonorId(donorId)
.map { it.apply { labDataProfileRepository.findById(this.profile ?: 0).ifPresent { profileData = it } } }
}
}

View File

@ -0,0 +1,43 @@
package dev.pcvolkmer.onco.grzmetadataprocessor.web
import dev.pcvolkmer.onco.grzmetadataprocessor.data.LabDataProfile
import dev.pcvolkmer.onco.grzmetadataprocessor.data.LabDataProfileRepository
import org.springframework.stereotype.Controller
import org.springframework.ui.Model
import org.springframework.web.bind.annotation.*
@Controller
@RequestMapping("/labdataprofiles")
class LabDataProfileController(
private val repository: LabDataProfileRepository
) {
@GetMapping
fun getAllLabDataProfiles(model: Model): String {
println(repository.findAll().sortedByDescending { it.id })
model.addAttribute("labdataprofiles", repository.findAll().sortedByDescending { it.id })
return "labdataprofiles"
}
@PostMapping
fun postLabDataProfile(model: Model): String {
repository.save(LabDataProfile(profileName = "Neues Sequenzierprofil"))
model.addAttribute("labdataprofiles", repository.findAll().sortedByDescending { it.id })
return "labdataprofiles"
}
@PutMapping(path = ["{labdataProfileId}"])
fun putLabData(@PathVariable labdataProfileId: Long, labDataProfile: LabDataProfile, model: Model): String {
repository.save(labDataProfile)
model.addAttribute("labdataprofiles", repository.findAll().sortedByDescending { it.id })
return "labdataprofiles"
}
@DeleteMapping(path = ["{labdataProfileId}"])
fun deleteLabData(@PathVariable labdataProfileId: Long, model: Model): String {
repository.deleteById(labdataProfileId)
model.addAttribute("labdataprofiles", repository.findAll().sortedByDescending { it.id })
return "labdataprofiles"
}
}

View File

@ -0,0 +1,16 @@
CREATE TABLE IF NOT EXISTS tbl_lab_data_profile
(
id int auto_increment primary key,
profile_name varchar(255),
library_type varchar(255),
library_prep_kit varchar(255) not null,
library_prep_kit_manufacturer varchar(255) not null,
sequencer_model varchar(255) not null,
sequencer_manufacturer varchar(255) not null,
kit_name varchar(255) not null,
kit_manufacturer varchar(255) not null,
enrichment_kit varchar(255) not null,
enrichment_kit_manufacturer varchar(255)
);
ALTER TABLE tbl_lab_data ADD COLUMN profile int;

View File

@ -1,6 +1,7 @@
<div class="title">GRZ-Metadaten</div>
<nav>
<b>Falldaten</b>
<ul>
<li>
<a th:href="@{/}">
@ -21,5 +22,13 @@
</a>
</li>
</ul>
<b>Profile</b>
<ul>
<li>
<a th:href="@{/labdataprofiles}">
<span>Sequenzierprofile</span>
</a>
</li>
</ul>
</nav>

View File

@ -0,0 +1,126 @@
<!DOCTYPE html>
<html lang="de" xmlns="http://www.w3.org/1999/html" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link th:href="@{/main.css}" rel="stylesheet" />
</head>
<body>
<aside th:hx-get="@{/cases/menu}" hx-trigger="load"></aside>
<main>
<div>
<div th:if="${labdataprofiles.isEmpty()}">
<h3>Probe</h3>
<form class="lab-data" th:hx-post="@{/labdataprofiles}">
<div>Keine Sequenzierprofile gefunden</div>
<button>Neues Sequenzierprofil hinzufügen</button>
</form>
</div>
<div th:each="profile : ${labdataprofiles}">
<h3>
Sequenzierprofil
<tt>"[[ ${ profile.profileName } ]]"</tt>
</h3>
<form class="lab-data">
<input type="hidden" name="id" th:value="${profile.id}" />
<div>
<label>
Profilname
<input type="text" name="profileName" th:value="${profile.profileName}" />
</label>
</div>
<div>
<label>
Library Type
<select name="libraryType">
<option th:selected="${profile.libraryType != null and profile.libraryType.value == 'panel'}" value="PANEL">panel</option>
<option th:selected="${profile.libraryType != null and profile.libraryType.value == 'panel_lr'}" value="PANEL_LR">panel_lr</option>
<option th:selected="${profile.libraryType != null and profile.libraryType.value == 'wes'}" value="WES">wes</option>
<option th:selected="${profile.libraryType != null and profile.libraryType.value == 'wes_lr'}" value="WES_LR">wes_lr</option>
<option th:selected="${profile.libraryType != null and profile.libraryType.value == 'wgs'}" value="WGS">wgs</option>
<option th:selected="${profile.libraryType != null and profile.libraryType.value == 'wgs_lr'}" value="WGS_LR">wgs_lr</option>
<option th:selected="${profile.libraryType != null and profile.libraryType.value == 'wxs'}" value="WXS">wxs</option>
<option th:selected="${profile.libraryType != null and profile.libraryType.value == 'wxs_lr'}" value="WXS_LR">wxs_lr</option>
<option th:selected="${profile.libraryType != null and profile.libraryType.value == 'other'}" value="OTHER">other</option>
<option th:selected="${profile.libraryType != null and profile.libraryType.value == 'unknown'}" value="UNKNOWN">unknown</option>
</select>
</label>
</div>
<div>
<label>
Preparation Kit - Name
<input type="text" name="libraryPrepKit" th:value="${profile.libraryPrepKit}" />
</label>
<label>
Hersteller
<input type="text" name="libraryPrepKitManufacturer" th:value="${profile.libraryPrepKitManufacturer}" />
</label>
</div>
<div>
<label>
Sequencer - Modell
<input type="text" name="sequencerModel" th:value="${profile.sequencerModel}" />
</label>
<label>
Hersteller
<input type="text" name="sequencerManufacturer" th:value="${profile.sequencerManufacturer}" />
</label>
</div>
<div>
<label>
Kit - Name/Version
<input type="text" name="kitName" th:value="${profile.kitName}" />
</label>
<label>
Hersteller
<input type="text" name="kitManufacturer" th:value="${profile.kitManufacturer}" />
</label>
</div>
<div>
<label>
Enrichment Kit - Name und Version
<input type="text" name="enrichmentKit" th:value="${profile.enrichmentKit}" />
</label>
<label>
Hersteller
<select name="enrichmentKitManufacturer">
<option th:selected="${profile.enrichmentKitManufacturer != null and profile.enrichmentKitManufacturer.value == 'Illumuna'}" value="ILLUMINA">Illumina</option>
<option th:selected="${profile.enrichmentKitManufacturer != null and profile.enrichmentKitManufacturer.value == 'Agilent'}" value="AGILENT">Agilent</option>
<option th:selected="${profile.enrichmentKitManufacturer != null and profile.enrichmentKitManufacturer.value == 'Twist'}" value="TIST">Twist</option>
<option th:selected="${profile.enrichmentKitManufacturer != null and profile.enrichmentKitManufacturer.value == 'NEB'}" value="NEB">NEB</option>
<option th:selected="${profile.enrichmentKitManufacturer != null and profile.enrichmentKitManufacturer.value == 'other'}" value="OTHER">other</option>
<option th:selected="${profile.enrichmentKitManufacturer != null and profile.enrichmentKitManufacturer.value == 'unknown'}" value="UNKNOWN">unknown</option>
<option th:selected="${profile.enrichmentKitManufacturer != null and profile.enrichmentKitManufacturer.value == 'none'}" value="NONE">none</option>
</select>
</label>
</div>
<div>
<button class="save" th:hx-put="@{/labdataprofiles/{profileId}(profileId=${profile.id})}" hx-target="body">Änderungen übernehmen</button>
<button class="new" th:hx-post="@{/labdataprofiles}" hx-target="body">Neu</button>
<button class="delete" th:hx-delete="@{/labdataprofiles/{profileId}(profileId=${profile.id})}" hx-target="body">Löschen</button>
</div>
</form>
</div>
</div>
</main>
<script th:src="@{/main.js}"></script>
</body>
</html>