Skip to content

Commit

Permalink
Merge pull request #1327 from deepsidhu85/sample_details_refactor/_de…
Browse files Browse the repository at this point in the history
…fault_assembly

Sample details refactor/ default assembly
  • Loading branch information
joshsadam committed Jul 4, 2022
2 parents e1eb233 + aabc9d4 commit 5e26af3
Show file tree
Hide file tree
Showing 17 changed files with 5,424 additions and 191 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import ca.corefacility.bioinformatics.irida.model.IridaRepresentationModel;
import ca.corefacility.bioinformatics.irida.model.MutableIridaThing;
import ca.corefacility.bioinformatics.irida.model.assembly.GenomeAssembly;
import ca.corefacility.bioinformatics.irida.model.event.SampleAddedProjectEvent;
import ca.corefacility.bioinformatics.irida.model.joins.impl.ProjectSampleJoin;
import ca.corefacility.bioinformatics.irida.model.joins.impl.SampleGenomeAssemblyJoin;
Expand Down Expand Up @@ -149,6 +150,10 @@ public class Sample extends IridaRepresentationModel
@JoinColumn(name = "default_sequencing_object")
private SequencingObject defaultSequencingObject;

@OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinColumn(name = "default_genome_assembly")
private GenomeAssembly defaultGenomeAssembly;

@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.REMOVE, mappedBy = "sample")
private List<ProjectSampleJoin> projects;

Expand Down Expand Up @@ -359,4 +364,10 @@ public SequencingObject getDefaultSequencingObject() {
public void setDefaultSequencingObject(SequencingObject sequencingObject) {
this.defaultSequencingObject = sequencingObject;
}

public GenomeAssembly getDefaultGenomeAssembly() { return defaultGenomeAssembly; }

public void setDefaultGenomeAssembly(GenomeAssembly genomeAssembly) {
this.defaultGenomeAssembly = genomeAssembly;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,26 @@ public ResponseEntity<AjaxResponse> updateDefaultSequencingObjectForSample(@Path
}
}

/**
* Update the default genome assembly for the sample
*
* @param id {@link Long} identifier for the sample
* @param genomeAssemblyId The genome assembly identifier
* @param locale {@link Locale} for the currently logged in user
* @return {@link ResponseEntity} explaining to the user the results of the update.
*/
@PutMapping(value = "/{id}/default-genome-assembly")
public ResponseEntity<AjaxResponse> updateDefaultGenomeAssemblyForSample(@PathVariable Long id,
@RequestParam Long genomeAssemblyId, Locale locale) {
try {
return ResponseEntity.ok(new AjaxSuccessResponse(
uiSampleService.updateDefaultGenomeAssemblyForSample(id, genomeAssemblyId, locale)));
} catch (EntityNotFoundException e) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
.body(new AjaxErrorResponse(e.getMessage()));
}
}

/**
* Get analyses for sample
*
Expand Down

Large diffs are not rendered by default.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">

<changeSet id="add-default-genome-assembly-to-sample" author="deep">
<addColumn tableName="sample">
<column name="default_genome_assembly" type="bigint(20)">
<constraints foreignKeyName="FK_SAMPLE_GENOME_ASSEMBLY"
referencedColumnNames="id" referencedTableName="genome_assembly" />
</column>
</addColumn>

<addColumn tableName="sample_AUD">
<column name="default_genome_assembly" type="bigint(20)" />
</addColumn>

</changeSet>
</databaseChangeLog>
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
<include file="user-account-drop-phone-constraint.xml" relativeToChangelogFile="true" />
<include file="add-default-sequencing-object-to-sample.xml" relativeToChangelogFile="true" />
<include file="add-default-genome-assembly-to-sample.xml" relativeToChangelogFile="true" />
</databaseChangeLog>
3 changes: 3 additions & 0 deletions src/main/resources/i18n/messages.properties
Original file line number Diff line number Diff line change
Expand Up @@ -2273,13 +2273,16 @@ SampleFilesList.download=Download
SampleFilesList.removeGenomeAssembly=Are you sure you want to delete this genome assembly from the sample?
SampleFilesList.removeSequencingObject=Are you sure you want to delete this sequencing object from the sample?
SampleFilesList.tooltip.setAsDefault=Set this paired end sequencing object as the default for the sample. The sequencing object will be selected by default when running a pipeline.
SampleFilesList.tooltip.setAsDefaultAssembly=Set this genome assembly as the default for the sample. The genome assembly will be selected by default when running a pipeline which accepts assemblies.
SampleFilesList.tooltip.remove=This will remove this complete sequencing object (paired end, single end, fast5) from the sample.
SampleFilesList.default=Default
SampleFilesList.setAsDefault=Set as Default
SampleFilesList.defaultSelected=Default paired end sequencing object to be selected when running a pipeline
SampleFilesList.defaultSelectedAssembly=Default genome assembly to be selected when running a pipeline

server.SampleFilesList.successfully.set.default.seq.object=Successfully set default sequencing object for sample
server.SampleFilesList.unable.to.update.sample=Unable to update sample as it was not found
server.SampleFilesList.successfully.set.default.genome.assembly=Successfully set default genome assembly for sample

# ========================================================================================== #
# SAMPLE FILES CONCATENATE COMPONENT #
Expand Down
11 changes: 11 additions & 0 deletions src/main/webapp/resources/css/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,17 @@
--grey-11: #1f1f1f;
--grey-12: #141414;
--grey-13: #000000;

--blue-1: #e6f7ff;
--blue-2: #bae7ff;
--blue-3: #91d5ff;
--blue-4: #69c0ff;
--blue-5: #40a9ff;
--blue-6: #1890ff;
--blue-7: #096dd9;
--blue-8: #0050b3;
--blue-9: #003a8c;
--blue-10: #002766;
}

html,
Expand Down
8 changes: 8 additions & 0 deletions src/main/webapp/resources/js/apis/samples/samples.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,13 @@ export const sampleApi = createApi({
}),
invalidatesTags: ["SampleDetails"],
}),
updateDefaultSampleGenomeAssembly: build.mutation({
query: ({ sampleId, genomeAssemblyId }) => ({
url: `/${sampleId}/default-genome-assembly?genomeAssemblyId=${genomeAssemblyId}`,
method: "PUT",
}),
invalidatesTags: ["SampleDetails"],
}),
}),
});

Expand All @@ -116,6 +123,7 @@ export const {
useUpdateSampleMetadataMutation,
useRemoveSampleFilesMutation,
useConcatenateSequencingObjectsMutation,
useUpdateDefaultSampleGenomeAssemblyMutation,
useUpdateDefaultSampleSequencingObjectMutation,
} = sampleApi;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import React from "react";
import { Button, notification, Popconfirm } from "antd";
import { useSelector } from "react-redux";
import { Button, notification, Popconfirm, Tag, Tooltip } from "antd";
import { useDispatch, useSelector } from "react-redux";

import { SequenceFileTypeRenderer } from "./SequenceFileTypeRenderer";
import { downloadGenomeAssemblyFile } from "../../../apis/samples/samples";
import { GenomeAssemblyListItem } from "../../sequence-files/GenomeAssemblyListItem";
import { DEFAULT_ACTION_WIDTH } from "../sampleFilesSlice";
import { useUpdateDefaultSampleGenomeAssemblyMutation } from "../../../apis/samples/samples";
import { setDefaultGenomeAssembly } from "../sampleSlice";

/**
* React component to display, remove, download genome assemblies
Expand All @@ -14,11 +16,14 @@ import { DEFAULT_ACTION_WIDTH } from "../sampleFilesSlice";
* @constructor
*/
export function GenomeAssemblyList({ removeSampleFiles = () => {} }) {
const [updateSampleDefaultGenomeAssembly] =
useUpdateDefaultSampleGenomeAssemblyMutation();
const { sample, modifiable: isModifiable } = useSelector(
(state) => state.sampleReducer
);
const { files } = useSelector((state) => state.sampleFilesReducer);
const ACTION_MARGIN_RIGHT = isModifiable ? 0 : 5;
const dispatch = useDispatch();

/*
Download genome assembly files
Expand All @@ -30,20 +35,86 @@ export function GenomeAssemblyList({ removeSampleFiles = () => {} }) {
downloadGenomeAssemblyFile({ sampleId, genomeAssemblyId });
};

/*
Set default genome assembly for sample to be used for analyses
*/
const updateDefaultGenomeAssembly = (genomeAssembly) => {
const { fileInfo: genomeAssemblyObj } = genomeAssembly;

updateSampleDefaultGenomeAssembly({
sampleId: sample.identifier,
genomeAssemblyId: genomeAssemblyObj.identifier,
})
.then(({ data }) => {
dispatch(setDefaultGenomeAssembly(genomeAssemblyObj));
notification.success({ message: data.message });
})
.catch((error) => {
notification.error({ message: error });
});
};

/*
Get the actions required for a Genome Assembly
*/
const getActionsForGenomeAssembly = (genomeAssembly) => {
let actions = [
const getActionsForGenomeAssembly = (genomeAssembly, index) => {
const { fileInfo: genomeAssemblyObj } = genomeAssembly;
let actions = [];

if (isModifiable) {
if (
(sample.defaultGenomeAssembly !== null &&
genomeAssemblyObj.identifier ===
sample.defaultGenomeAssembly.identifier) ||
(sample.defaultGenomeAssembly === null && index === 0)
) {
actions.push(
<Tooltip
title={i18n("SampleFilesList.defaultSelectedAssembly")}
placement="top"
key={`default-tag-tooltip-ga-${genomeAssemblyObj.identifier}`}
>
<Tag
color={`var(--blue-6)`}
key={`default-tag-ga-${genomeAssemblyObj.identifier}`}
className="t-default-genome-assembly-tag"
>
{i18n("SampleFilesList.default")}
</Tag>
</Tooltip>
);
} else {
actions.push(
<Tooltip
title={i18n("SampleFilesList.tooltip.setAsDefaultAssembly")}
placement="top"
key={`set-default-tooltip-ga-${genomeAssemblyObj.identifier}`}
>
<Button
size="small"
key={`set-default-ga-${genomeAssemblyObj.identifier}`}
onClick={() => updateDefaultGenomeAssembly(genomeAssembly)}
type="link"
className="t-set-default-genome-assembly-button"
style={{ width: 100 }}
>
{i18n("SampleFilesList.setAsDefault")}
</Button>
</Tooltip>
);
}
}

actions.push(
<span
key={`${genomeAssembly.fileInfo.identifier}-file-size`}
key={`${genomeAssemblyObj.identifier}-file-size`}
className="t-file-size"
>
{genomeAssembly.firstFileSize}
</span>,
<Button
type="link"
key={`${genomeAssembly.fileInfo.identifier}-download-btn`}
key={`${genomeAssemblyObj.identifier}-download-btn`}
style={{
padding: 0,
width: DEFAULT_ACTION_WIDTH,
Expand All @@ -53,13 +124,13 @@ export function GenomeAssemblyList({ removeSampleFiles = () => {} }) {
onClick={() => {
downloadAssemblyFile({
sampleId: sample.identifier,
genomeAssemblyId: genomeAssembly.fileInfo.identifier,
genomeAssemblyId: genomeAssemblyObj.identifier,
});
}}
>
{i18n("SampleFilesList.download")}
</Button>,
];
</Button>
);

if (isModifiable) {
actions.push(
Expand All @@ -74,7 +145,7 @@ export function GenomeAssemblyList({ removeSampleFiles = () => {} }) {
}}
onConfirm={() => {
removeSampleFiles({
fileObjectId: genomeAssembly.fileInfo.identifier,
fileObjectId: genomeAssemblyObj.identifier,
type: "assembly",
});
}}
Expand All @@ -83,7 +154,7 @@ export function GenomeAssemblyList({ removeSampleFiles = () => {} }) {
type="link"
className="t-remove-file-btn"
style={{ padding: 0, width: DEFAULT_ACTION_WIDTH }}
key={`${genomeAssembly.fileInfo.identifier}-remove-btn`}
key={`${genomeAssemblyObj.identifier}-remove-btn`}
>
{i18n("SampleFilesList.remove")}
</Button>
Expand All @@ -96,11 +167,11 @@ export function GenomeAssemblyList({ removeSampleFiles = () => {} }) {

return (
<SequenceFileTypeRenderer title={i18n("SampleFiles.assemblies")}>
{files.assemblies.map((assembly) => (
{files.assemblies.map((assembly, index) => (
<GenomeAssemblyListItem
key={`assembly-${assembly.fileInfo.identifier}`}
genomeAssembly={assembly}
actions={getActionsForGenomeAssembly(assembly)}
actions={getActionsForGenomeAssembly(assembly, index)}
/>
))}
</SequenceFileTypeRenderer>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import React from "react";
import { notification, Space } from "antd";
import { useDispatch, useSelector } from "react-redux";
import { useRemoveSampleFilesMutation } from "../../../apis/samples/samples";
import { removeFileObjectFromSample } from "../sampleFilesSlice";
import { useDispatch, useSelector } from "react-redux";
import { setDefaultSequencingObject } from "../sampleSlice";
import { GenomeAssemblyList } from "./GenomeAssemblyList";
import { SequencingObjectList } from "./SequencingObjectList";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,6 @@ import { SequenceObjectListItem } from "../../sequence-files/SequenceObjectListI
import { primaryColour } from "../../../utilities/theme-utilities";
import { SPACE_XS } from "../../../styles/spacing";

const fileProcessTranslations = {
UNPROCESSED: i18n("SampleFilesList.fileProcessingState.UNPROCESSED"),
QUEUED: i18n("SampleFilesList.fileProcessingState.QUEUED"),
PROCESSING: i18n("SampleFilesList.fileProcessingState.PROCESSING"),
FINISHED: i18n("SampleFilesList.fileProcessingState.FINISHED"),
ERROR: i18n("SampleFilesList.fileProcessingState.ERROR"),
};

import {
addToConcatenateSelected,
DEFAULT_ACTION_WIDTH,
Expand All @@ -43,6 +35,14 @@ import {
useUpdateDefaultSampleSequencingObjectMutation,
} from "../../../apis/samples/samples";

const fileProcessTranslations = {
UNPROCESSED: i18n("SampleFilesList.fileProcessingState.UNPROCESSED"),
QUEUED: i18n("SampleFilesList.fileProcessingState.QUEUED"),
PROCESSING: i18n("SampleFilesList.fileProcessingState.PROCESSING"),
FINISHED: i18n("SampleFilesList.fileProcessingState.FINISHED"),
ERROR: i18n("SampleFilesList.fileProcessingState.ERROR"),
};

/**
* React component to display, remove, download sequencing objects
* @param {function} removeSampleFiles The function to remove sequencing objects
Expand Down Expand Up @@ -204,7 +204,7 @@ export function SequencingObjectList({ removeSampleFiles = () => {} }) {
key={`default-tag-tooltip-${obj.identifier}`}
>
<Tag
color="#108ee9"
color={`var(--blue-6)`}
key={`default-tag-${obj.identifier}`}
className="t-default-seq-obj-tag"
>
Expand Down
14 changes: 14 additions & 0 deletions src/main/webapp/resources/js/components/samples/sampleSlice.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,16 @@ export const setDefaultSequencingObject = createAction(
})
);

/**
* Action to set the default genome assembly for a sample
*/
export const setDefaultGenomeAssembly = createAction(
`sample/setDefaultGenomeAssembly`,
(genomeAssembly) => ({
payload: { genomeAssembly },
})
);

/**
* Action to update sample details
*/
Expand Down Expand Up @@ -142,6 +152,10 @@ const sampleSlice = createSlice({
state.sample.defaultSequencingObject = action.payload.sequencingObject;
});

builder.addCase(setDefaultGenomeAssembly, (state, action) => {
state.sample.defaultGenomeAssembly = action.payload.genomeAssembly;
});

builder.addCase(setProjectDetails, (state, action) => {
state.projectId = action.payload.projectId;
state.projectName = action.payload.projectName;
Expand Down
Loading

0 comments on commit 5e26af3

Please sign in to comment.