-
{activeProject.name}
+ {activeExperiment.name}
- {`Project ID: ${activeProjectUuid}`}
+ {`Project ID: ${activeExperimentId}`}
@@ -66,11 +65,10 @@ const ProjectDetails = ({ width, height }) => {
Description:
{
- if (text !== activeProject.description) {
- dispatch(updateProject(activeProjectUuid, { description: text }));
- dispatch(updateExperiment(activeProject.experiments[0], { description: text }));
+ if (text !== activeExperiment.description) {
+ dispatch(updateExperiment(activeExperimentId, { description: text }));
}
}}
/>
diff --git a/src/components/data-management/ProjectMenu.jsx b/src/components/data-management/ProjectMenu.jsx
index 66911094dc..e3bf6ac969 100644
--- a/src/components/data-management/ProjectMenu.jsx
+++ b/src/components/data-management/ProjectMenu.jsx
@@ -13,13 +13,14 @@ import ShareExperimentModal from './ShareExperimentModal';
const ProjectMenu = () => {
const dispatch = useDispatch();
const samples = useSelector((state) => state.samples);
- const activeProjectUuid = useSelector((state) => state.projects.meta.activeProjectUuid);
+ const activeExperimentId = useSelector((state) => state.experiments.meta.activeExperimentId);
+ const activeExperiment = useSelector((state) => state.experiments[activeExperimentId]);
+
const [uploadModalVisible, setUploadModalVisible] = useState(false);
const [shareExperimentModalVisible, setShareExperimentModalVisible] = useState(false);
- const activeProject = useSelector((state) => state.projects[activeProjectUuid]);
const uploadFiles = (filesList, sampleType) => {
- processUpload(filesList, sampleType, samples, activeProjectUuid, dispatch);
+ processUpload(filesList, sampleType, samples, activeExperimentId, dispatch);
setUploadModalVisible(false);
};
@@ -42,7 +43,7 @@ const ProjectMenu = () => {
{shareExperimentModalVisible && (
setShareExperimentModalVisible(false)}
- activeProject={activeProject}
+ experiment={activeExperiment}
/>
)}
diff --git a/src/components/data-management/ProjectsList.jsx b/src/components/data-management/ProjectsList.jsx
index 3b0b49bd84..8722a3f2f7 100644
--- a/src/components/data-management/ProjectsList.jsx
+++ b/src/components/data-management/ProjectsList.jsx
@@ -13,14 +13,14 @@ const windowMargin = 130; // px
const ProjectsList = (props) => {
const { height, filter } = props;
- const projects = useSelector((state) => state.projects);
+ const experiments = useSelector((state) => state.experiments);
- if (projects.meta.loading) {
+ if (experiments.meta.loading) {
return [...Array(5)].map((_, idx) => );
}
// if there are no element return an emtpy one so that the tests know the list has been loaded
- if (projects.ids.length === 0) {
+ if (experiments.ids.length === 0) {
return (
);
@@ -33,19 +33,17 @@ const ProjectsList = (props) => {
style={{ height: height - windowMargin, overflowY: 'auto' }}
>
{
- projects.ids.map((projectUuid) => {
- const project = projects[projectUuid];
+ experiments.ids.map((experimentId) => {
+ const experiment = experiments[experimentId];
- const matchFilter = project.name.match(filter)
- || project.experiments.some((experimentId) => experimentId.match(filter))
- || projectUuid.match(filter);
+ const matchFilter = experiment.name.match(filter) || experimentId.match(filter);
if (!matchFilter) return <>>;
return (
);
})
diff --git a/src/components/data-management/SamplesTable.jsx b/src/components/data-management/SamplesTable.jsx
index 4696e3be41..43aaef777a 100644
--- a/src/components/data-management/SamplesTable.jsx
+++ b/src/components/data-management/SamplesTable.jsx
@@ -18,13 +18,11 @@ import MetadataColumnTitle from 'components/data-management/MetadataColumn';
import { UploadCell, SampleNameCell, EditableFieldCell } from 'components/data-management/SamplesTableCells';
import {
- updateProject,
deleteMetadataTrack,
createMetadataTrack,
updateValueInMetadataTrack,
-} from 'redux/actions/projects';
-import { DEFAULT_NA } from 'redux/reducers/projects/initialState';
-import { reorderSamples } from 'redux/actions/experiments';
+ reorderSamples,
+} from 'redux/actions/experiments';
import { loadSamples } from 'redux/actions/samples';
@@ -38,6 +36,7 @@ import 'utils/css/data-management.css';
import { ClipLoader } from 'react-spinners';
import useConditionalEffect from 'utils/customHooks/useConditionalEffect';
+import { METADATA_DEFAULT_VALUE } from 'redux/reducers/experiments/initialState';
const { Text } = Typography;
@@ -45,12 +44,12 @@ const SamplesTable = forwardRef((props, ref) => {
const dispatch = useDispatch();
const [tableData, setTableData] = useState([]);
- const projects = useSelector((state) => state.projects);
+ const experiments = useSelector((state) => state.experiments);
const samples = useSelector((state) => state.samples);
const areSamplesLoading = useSelector((state) => state.samples.meta.loading);
- const { activeProjectUuid } = useSelector((state) => state.projects.meta) || false;
- const activeProject = useSelector((state) => state.projects[activeProjectUuid]) || false;
+ const activeExperimentId = useSelector((state) => state.experiments.meta.activeExperimentId);
+ const activeExperiment = useSelector((state) => state.experiments[activeExperimentId]);
const [sampleNames, setSampleNames] = useState(new Set());
const DragHandle = sortableHandle(() => );
@@ -99,10 +98,10 @@ const SamplesTable = forwardRef((props, ref) => {
const [tableColumns, setTableColumns] = useState(initialTableColumns);
useEffect(() => {
- if (activeProject.samples.length > 0) {
+ if (activeExperiment.sampleIds.length > 0) {
// if there are samples - build the table columns
- setSampleNames(new Set(activeProject.samples.map((id) => samples[id]?.name.trim())));
- const metadataColumns = activeProject.metadataKeys.map(
+ setSampleNames(new Set(activeExperiment.sampleIds.map((id) => samples[id]?.name.trim())));
+ const metadataColumns = activeExperiment.metadataKeys.map(
(metadataKey) => createInitializedMetadataColumn(metadataKeyToName(metadataKey)),
) || [];
setTableColumns([...initialTableColumns, ...metadataColumns]);
@@ -110,14 +109,14 @@ const SamplesTable = forwardRef((props, ref) => {
setTableColumns([]);
setSampleNames(new Set());
}
- }, [samples, activeProject]);
+ }, [samples, activeExperiment]);
useConditionalEffect(() => {
- dispatch(loadSamples(activeProjectUuid));
- }, [activeProject.samples], { lazy: true });
+ dispatch(loadSamples(activeExperimentId));
+ }, [activeExperiment?.sampleIds], { lazy: true });
const deleteMetadataColumn = (name) => {
- dispatch(deleteMetadataTrack(name, activeProjectUuid));
+ dispatch(deleteMetadataTrack(name, activeExperimentId));
};
const createInitializedMetadataColumn = (name) => {
@@ -131,7 +130,7 @@ const SamplesTable = forwardRef((props, ref) => {
sampleNames={sampleNames}
setCells={setCells}
deleteMetadataColumn={deleteMetadataColumn}
- activeProjectUuid={activeProjectUuid}
+ activeExperimentId={activeExperimentId}
/>
),
width: 200,
@@ -142,7 +141,7 @@ const SamplesTable = forwardRef((props, ref) => {
dataIndex={key}
rowIdx={rowIdx}
onAfterSubmit={(newValue) => {
- dispatch(updateValueInMetadataTrack(activeProjectUuid, record.uuid, key, newValue));
+ dispatch(updateValueInMetadataTrack(activeExperimentId, record.uuid, key, newValue));
}}
/>
),
@@ -150,7 +149,7 @@ const SamplesTable = forwardRef((props, ref) => {
};
const onMetadataCreate = (name) => {
- dispatch(createMetadataTrack(name, activeProjectUuid));
+ dispatch(createMetadataTrack(name, activeExperimentId));
};
useImperativeHandle(ref, () => ({
@@ -162,7 +161,7 @@ const SamplesTable = forwardRef((props, ref) => {
fixed: 'right',
title: () => (
{
onMetadataCreate(name);
}}
@@ -197,28 +196,28 @@ const SamplesTable = forwardRef((props, ref) => {
const isMetadataEmpty = (uuid) => (
!samples[uuid].metadata[metadataKey]
- || samples[uuid].metadata[metadataKey] === DEFAULT_NA
+ || samples[uuid].metadata[metadataKey] === METADATA_DEFAULT_VALUE
);
return isMetadataEmpty(sampleUuid);
};
- activeProject.samples.forEach(
+ activeExperiment.sampleIds.forEach(
(sampleUuid) => {
if (canUpdateCell(sampleUuid, actionType)) {
- dispatch(updateValueInMetadataTrack(activeProjectUuid, sampleUuid, metadataKey, value));
+ dispatch(updateValueInMetadataTrack(activeExperimentId, sampleUuid, metadataKey, value));
}
},
);
};
useEffect(() => {
- if (activeProject.samples.length === 0) {
+ if (activeExperiment.sampleIds.length === 0) {
setTableData([]);
return;
}
- const newData = activeProject.samples.map((sampleUuid, idx) => {
+ const newData = activeExperiment.sampleIds.map((sampleUuid, idx) => {
// upload problems sometimes lead to partial updates and incosistent states
// in this situation it's possible that the sampleUuid does not exist
// this a temporary fix so that the whole UI doesn't crash preventing the
@@ -244,7 +243,7 @@ const SamplesTable = forwardRef((props, ref) => {
};
});
setTableData(newData);
- }, [projects, samples, activeProjectUuid]);
+ }, [experiments, samples, activeExperimentId]);
const noDataComponent = (
{
const newData = arrayMoveImmutable(tableData, oldIndex, newIndex).filter((el) => !!el);
const newSampleOrder = newData.map((sample) => sample.uuid);
- dispatch(updateProject(activeProjectUuid, { samples: newSampleOrder }));
-
try {
- await dispatch(reorderSamples(activeProjectUuid, oldIndex, newIndex, newSampleOrder));
+ await dispatch(reorderSamples(activeExperimentId, oldIndex, newIndex, newSampleOrder));
} catch (e) {
// If the fetch fails, avoid doing setTableData(newData)
return;
diff --git a/src/components/data-management/ShareExperimentModal.jsx b/src/components/data-management/ShareExperimentModal.jsx
index 93b1315a0d..0624312130 100644
--- a/src/components/data-management/ShareExperimentModal.jsx
+++ b/src/components/data-management/ShareExperimentModal.jsx
@@ -12,20 +12,17 @@ import revokeRole from 'utils/data-management/experimentSharing/revokeRole';
const { Text } = Typography;
const ShareExperimentModal = (props) => {
- const { onCancel, activeProject } = props;
+ const { onCancel, experiment } = props;
const [usersWithAccess, setUsersWithAccess] = useState([]);
- const experimentId = activeProject.experiments[0];
- const experimentName = activeProject.name;
- const activeProjectUuid = activeProject.uuid;
const [addedUsers, setAddedUsers] = useState([]);
- const [role, setRole] = useState('explorer');
const [currentUser, setCurrentUser] = useState(null);
+ const [role, setRole] = useState('explorer');
const fetchRoles = async () => {
const getCurrentUser = await Auth.currentAuthenticatedUser();
setCurrentUser(getCurrentUser.attributes.email);
- const userRole = await loadRoles(experimentId);
+ const userRole = await loadRoles(experiment.id);
setUsersWithAccess(userRole);
};
@@ -55,9 +52,8 @@ const ShareExperimentModal = (props) => {
await sendInvites(
addedUsers,
{
- experimentId,
- experimentName,
- activeProjectUuid,
+ experimentId: experiment.id,
+ experimentName: experiment.name,
role,
},
);
@@ -81,7 +77,7 @@ const ShareExperimentModal = (props) => {
>
- {experimentName}
+ {experiment.name}
@@ -135,7 +131,11 @@ const ShareExperimentModal = (props) => {
type='primary'
danger
onClick={() => {
- revokeRole(user.email, { experimentId, experimentName });
+ revokeRole(
+ user.email,
+ { experimentId: experiment.id, experimentName: experiment.name },
+ );
+
onCancel();
}}
disabled={user.email === currentUser}
@@ -163,7 +163,7 @@ const ShareExperimentModal = (props) => {
ShareExperimentModal.propTypes = {
onCancel: PropTypes.func.isRequired,
- activeProject: PropTypes.object.isRequired,
+ experiment: PropTypes.object.isRequired,
};
export default ShareExperimentModal;
diff --git a/src/components/data-management/UploadDetailsModal.jsx b/src/components/data-management/UploadDetailsModal.jsx
index 684513d335..f3dacac0be 100644
--- a/src/components/data-management/UploadDetailsModal.jsx
+++ b/src/components/data-management/UploadDetailsModal.jsx
@@ -31,8 +31,9 @@ const UploadDetailsModal = (props) => {
const inputFileRef = useRef(null);
const [replacementFileObject, setReplacementFileObject] = useState(null);
- const { activeProjectUuid } = useSelector((state) => state.projects.meta) || false;
+ const { activeExperimentId } = useSelector((state) => state.experiments.meta);
const samples = useSelector((state) => state.samples);
+
const sampleName = samples[uploadDetailsModalDataRef.current?.sampleUuid]?.name;
useEffect(() => {
@@ -68,7 +69,7 @@ const UploadDetailsModal = (props) => {
return;
}
- createAndUploadSingleFile(newFile, activeProjectUuid, sampleUuid, dispatch);
+ createAndUploadSingleFile(newFile, activeExperimentId, sampleUuid, dispatch);
onCancel();
};
@@ -126,7 +127,7 @@ const UploadDetailsModal = (props) => {
key='retry'
block
onClick={() => {
- downloadSingleFile(activeProjectUuid, sampleUuid, file.name);
+ downloadSingleFile(activeExperimentId, sampleUuid, file.name);
}}
style={{ width: '140px', marginBottom: '10px' }}
>
diff --git a/src/pages/data-management/index.jsx b/src/pages/data-management/index.jsx
index a524215ed7..67168eba5f 100644
--- a/src/pages/data-management/index.jsx
+++ b/src/pages/data-management/index.jsx
@@ -4,7 +4,6 @@ import { useDispatch, useSelector } from 'react-redux';
import { Space } from 'antd';
import { ClipLoader } from 'react-spinners';
-import { loadProjects } from 'redux/actions/projects';
import { loadExperiments } from 'redux/actions/experiments';
import Header from 'components/Header';
@@ -19,53 +18,36 @@ import ExampleExperimentsSpace from 'components/data-management/ExampleExperimen
const DataManagementPage = () => {
const dispatch = useDispatch();
- const projectsList = useSelector(((state) => state.projects));
- const {
- saving: projectSaving,
- } = projectsList.meta;
+ const samples = useSelector((state) => state.samples);
- const sampleSaving = useSelector((state) => state.samples.meta.saving);
+ const { activeExperimentId } = useSelector((state) => state.experiments.meta);
+ const experiments = useSelector(((state) => state.experiments));
- const { activeProjectUuid } = useSelector((state) => state.projects.meta);
+ const activeExperiment = experiments[activeExperimentId];
+ const { saving: experimentsSaving } = experiments.meta;
+ const { saving: samplesSaving } = samples.meta;
- const experiments = useSelector((state) => state.experiments);
const [newProjectModalVisible, setNewProjectModalVisible] = useState(false);
- const activeProject = projectsList[activeProjectUuid];
- const loadedSamples = useSelector((state) => state.samples);
-
- const experimentIds = new Set(experiments.ids);
- const experimentsAreLoaded = activeProject?.experiments
- .every((experimentId) => experimentIds.has(experimentId));
useEffect(() => {
- if (projectsList.ids.length === 0) dispatch(loadProjects());
+ if (experiments.ids.length === 0) dispatch(loadExperiments());
}, []);
- const updateRunStatus = (experimentId) => {
- dispatch(loadBackendStatus(experimentId));
+ const samplesAreLoaded = () => {
+ const loadedSampleIds = Object.keys(samples);
+ return activeExperiment.sampleIds.every((sampleId) => loadedSampleIds.includes(sampleId));
};
- const samplesAreLoaded = () => !activeProject.samples.length
- || activeProject.samples.every((sample) => Object.keys(loadedSamples).includes(sample));
-
useEffect(() => {
- if (!activeProjectUuid) return;
-
- // Right now we have one experiment per project, so we can just load the experiment
- // This has to be changed when we have more than one experiment
- const activeExperimentId = projectsList[activeProjectUuid].experiments[0];
+ if (!activeExperimentId) return;
dispatch(loadProcessingSettings(activeExperimentId));
- if (!samplesAreLoaded()) dispatch(loadSamples(activeProjectUuid));
-
- if (!experimentsAreLoaded) {
- dispatch(loadExperiments(activeProjectUuid)).then(() => updateRunStatus(activeExperimentId));
- }
+ if (!samplesAreLoaded()) dispatch(loadSamples(activeExperimentId));
- if (experiments[activeExperimentId]) updateRunStatus(activeExperimentId);
- }, [activeProjectUuid]);
+ dispatch(loadBackendStatus(activeExperimentId));
+ }, [activeExperimentId]);
const PROJECTS_LIST = 'Projects';
const PROJECT_DETAILS = 'Project Details';
@@ -83,7 +65,7 @@ const DataManagementPage = () => {
[PROJECT_DETAILS]: {
toolbarControls: [],
component: (width, height) => {
- if (!activeProjectUuid) {
+ if (!activeExperimentId) {
return ;
}
@@ -107,7 +89,7 @@ const DataManagementPage = () => {
return (
<>
- {projectSaving || sampleSaving ? (
+ {experimentsSaving || samplesSaving ? (
async (dispatch) => {
- const createdDate = moment().toISOString();
- const experimentId = hash.MD5(createdDate);
+ const createdAt = moment().toISOString();
+ const experimentId = hash.MD5(createdAt);
const newExperimentProperties = {
id: experimentId,
@@ -43,11 +43,11 @@ const createExperiment = (
dispatch({
type: EXPERIMENTS_CREATED,
payload: {
- // TODO We don't really need to send this createdDate to redux, the real createdAt
+ // TODO We don't really need to send this createdAt to redux, the real createdAt
// is being generated in the api
// We should make the POST to create the experiment return the new experiment and
// Take the createdAt from there
- experiment: { createdDate, ...newExperimentProperties },
+ experiment: { createdAt, ...newExperimentProperties },
},
});
} catch (e) {
@@ -59,8 +59,6 @@ const createExperiment = (
error: errorMessage,
},
});
-
- throw e;
}
return Promise.resolve(experimentId);
diff --git a/src/redux/actions/projects/createMetadataTrack.js b/src/redux/actions/experiments/createMetadataTrack.js
similarity index 61%
rename from src/redux/actions/projects/createMetadataTrack.js
rename to src/redux/actions/experiments/createMetadataTrack.js
index df5aadf330..18bc2b3e1f 100644
--- a/src/redux/actions/projects/createMetadataTrack.js
+++ b/src/redux/actions/experiments/createMetadataTrack.js
@@ -1,34 +1,32 @@
import _ from 'lodash';
import {
- PROJECTS_METADATA_CREATE,
-} from 'redux/actionTypes/projects';
+ EXPERIMENTS_METADATA_CREATE,
+} from 'redux/actionTypes/experiments';
import {
SAMPLES_UPDATE,
} from 'redux/actionTypes/samples';
-import {
- DEFAULT_NA,
-} from 'redux/reducers/projects/initialState';
import fetchAPI from 'utils/http/fetchAPI';
import handleError from 'utils/http/handleError';
import endUserMessages from 'utils/endUserMessages';
import { metadataNameToKey } from 'utils/data-management/metadataUtils';
+import { METADATA_DEFAULT_VALUE } from 'redux/reducers/experiments/initialState';
const createMetadataTrack = (
- name, projectUuid,
+ name, experimentId,
) => async (dispatch, getState) => {
- const project = getState().projects[projectUuid];
+ const experiment = getState().experiments[experimentId];
const { samples } = getState();
const metadataKey = metadataNameToKey(name);
- const newProject = _.cloneDeep(project);
- newProject.metadataKeys.push(metadataKey);
+ const newExperiment = _.cloneDeep(experiment);
+ newExperiment.metadataKeys.push(metadataKey);
try {
await fetchAPI(
- `/v2/experiments/${projectUuid}/metadataTracks/${metadataKey}`,
+ `/v2/experiments/${experimentId}/metadataTracks/${metadataKey}`,
{
method: 'POST',
headers: {
@@ -38,28 +36,26 @@ const createMetadataTrack = (
);
dispatch({
- type: PROJECTS_METADATA_CREATE,
+ type: EXPERIMENTS_METADATA_CREATE,
payload: {
- projectUuid,
+ experimentId,
key: metadataKey,
},
});
- await Promise.all(project.samples.map((sampleUuid) => dispatch({
+ await Promise.all(experiment.sampleIds.map((sampleUuid) => dispatch({
type: SAMPLES_UPDATE,
payload: {
sampleUuid,
sample: {
metadata: {
[metadataKey]: (
- samples[sampleUuid].metadata[metadataKey] || DEFAULT_NA
+ samples[sampleUuid].metadata[metadataKey] || METADATA_DEFAULT_VALUE
),
},
},
},
})));
-
- // Get updated samples in an object
} catch (e) {
handleError(e, endUserMessages.ERROR_SAVING);
}
diff --git a/src/redux/actions/projects/deleteProject.js b/src/redux/actions/experiments/deleteExperiment.js
similarity index 50%
rename from src/redux/actions/projects/deleteProject.js
rename to src/redux/actions/experiments/deleteExperiment.js
index cabdad8ddd..995b9f976c 100644
--- a/src/redux/actions/projects/deleteProject.js
+++ b/src/redux/actions/experiments/deleteExperiment.js
@@ -3,28 +3,20 @@ import handleError from 'utils/http/handleError';
import endUserMessages from 'utils/endUserMessages';
import {
- PROJECTS_DELETE,
- PROJECTS_SET_ACTIVE,
- PROJECTS_ERROR,
- PROJECTS_SAVING,
- PROJECTS_SAVED,
-} from 'redux/actionTypes/projects';
-
-import {
- EXPERIMENTS_DELETED,
+ EXPERIMENTS_SET_ACTIVE, EXPERIMENTS_DELETED, EXPERIMENTS_ERROR, EXPERIMENTS_SAVING,
} from 'redux/actionTypes/experiments';
import { SAMPLES_DELETE } from 'redux/actionTypes/samples';
-const deleteProject = (
- projectUuid,
+const deleteExperiment = (
+ experimentId,
) => async (dispatch, getState) => {
// Delete samples
- const { projects } = getState();
- const { activeProjectUuid } = projects.meta;
+ const { experiments } = getState();
+ const { activeExperimentId } = experiments.meta;
dispatch({
- type: PROJECTS_SAVING,
+ type: EXPERIMENTS_SAVING,
payload: {
message: endUserMessages.DELETING_PROJECT,
},
@@ -32,7 +24,7 @@ const deleteProject = (
try {
await fetchAPI(
- `/v2/experiments/${projectUuid}`,
+ `/v2/experiments/${experimentId}`,
{
method: 'DELETE',
headers: {
@@ -42,48 +34,39 @@ const deleteProject = (
);
// If deleted project is the same as the active project, choose another project
- if (projectUuid === activeProjectUuid) {
- const leftoverProjectIds = projects.ids.filter((uuid) => uuid !== activeProjectUuid);
+ if (experimentId === activeExperimentId) {
+ const leftoverProjectIds = experiments.ids.filter((uuid) => uuid !== activeExperimentId);
dispatch({
- type: PROJECTS_SET_ACTIVE,
- payload: { projectUuid: leftoverProjectIds.length ? leftoverProjectIds[0] : null },
+ type: EXPERIMENTS_SET_ACTIVE,
+ payload: { experimentId: leftoverProjectIds.length ? leftoverProjectIds[0] : null },
});
}
dispatch({
type: SAMPLES_DELETE,
payload: {
- experimentId: projectUuid,
- sampleIds: projects[projectUuid].samples,
+ experimentId,
+ sampleIds: experiments[experimentId].sampleIds,
},
});
dispatch({
type: EXPERIMENTS_DELETED,
payload: {
- experimentIds: projects[projectUuid].experiments,
+ experimentIds: [experimentId],
},
});
-
- dispatch({
- type: PROJECTS_DELETE,
- payload: { projectUuid },
- });
-
- dispatch({
- type: PROJECTS_SAVED,
- });
} catch (e) {
const errorMessage = handleError(e, endUserMessages.ERROR_DELETING_PROJECT);
dispatch({
- type: PROJECTS_ERROR,
+ type: EXPERIMENTS_ERROR,
payload: {
- error: errorMessage,
+ message: errorMessage,
},
});
}
};
-export default deleteProject;
+export default deleteExperiment;
diff --git a/src/redux/actions/projects/deleteMetadataTrack.js b/src/redux/actions/experiments/deleteMetadataTrack.js
similarity index 59%
rename from src/redux/actions/projects/deleteMetadataTrack.js
rename to src/redux/actions/experiments/deleteMetadataTrack.js
index f88fe922c2..0701e77df6 100644
--- a/src/redux/actions/projects/deleteMetadataTrack.js
+++ b/src/redux/actions/experiments/deleteMetadataTrack.js
@@ -1,11 +1,7 @@
import _ from 'lodash';
-import {
- PROJECTS_METADATA_DELETE,
-} from 'redux/actionTypes/projects';
-import {
- SAMPLES_METADATA_DELETE,
-} from 'redux/actionTypes/samples';
+import { EXPERIMENTS_METADATA_DELETE } from 'redux/actionTypes/experiments';
+import { SAMPLES_METADATA_DELETE } from 'redux/actionTypes/samples';
import fetchAPI from 'utils/http/fetchAPI';
import handleError from 'utils/http/handleError';
@@ -14,18 +10,18 @@ import endUserMessages from 'utils/endUserMessages';
import { metadataNameToKey } from 'utils/data-management/metadataUtils';
const deleteMetadataTrack = (
- name, projectUuid,
+ name, experimentId,
) => async (dispatch, getState) => {
- const project = getState().projects[projectUuid];
+ const experiment = getState().experiments[experimentId];
const metadataKey = metadataNameToKey(name);
- const newProject = _.cloneDeep(project);
- newProject.metadataKeys = project.metadataKeys.filter((key) => key !== metadataKey);
+ const newExperiment = _.cloneDeep(experiment);
+ newExperiment.metadataKeys = experiment.metadataKeys.filter((key) => key !== metadataKey);
try {
await fetchAPI(
- `/v2/experiments/${projectUuid}/metadataTracks/${metadataKey}`,
+ `/v2/experiments/${experimentId}/metadataTracks/${metadataKey}`,
{
method: 'DELETE',
headers: {
@@ -35,14 +31,14 @@ const deleteMetadataTrack = (
);
dispatch({
- type: PROJECTS_METADATA_DELETE,
+ type: EXPERIMENTS_METADATA_DELETE,
payload: {
key: metadataKey,
- projectUuid,
+ experimentId,
},
});
- project.samples.forEach((sampleUuid) => dispatch({
+ experiment.sampleIds.forEach((sampleUuid) => dispatch({
type: SAMPLES_METADATA_DELETE,
payload: {
sampleUuid,
diff --git a/src/redux/actions/experiments/index.js b/src/redux/actions/experiments/index.js
index 3414318a18..a4f76d71ef 100644
--- a/src/redux/actions/experiments/index.js
+++ b/src/redux/actions/experiments/index.js
@@ -1,13 +1,25 @@
import createExperiment from './createExperiment';
+import deleteExperiment from './deleteExperiment';
import updateExperiment from './updateExperiment';
import loadExperiments from './loadExperiments';
+import setActiveExperiment from './setActiveExperiment';
import switchExperiment from './switchExperiment';
import reorderSamples from './reorderSamples';
+import createMetadataTrack from './createMetadataTrack';
+import updateMetadataTrack from './updateMetadataTrack';
+import deleteMetadataTrack from './deleteMetadataTrack';
+import updateValueInMetadataTrack from './updateValueInMetadataTrack';
export {
createExperiment,
+ deleteExperiment,
updateExperiment,
loadExperiments,
+ setActiveExperiment,
switchExperiment,
reorderSamples,
+ createMetadataTrack,
+ updateMetadataTrack,
+ deleteMetadataTrack,
+ updateValueInMetadataTrack,
};
diff --git a/src/redux/actions/experiments/loadExperiments.js b/src/redux/actions/experiments/loadExperiments.js
index e6944a519f..40b8dfb61f 100644
--- a/src/redux/actions/experiments/loadExperiments.js
+++ b/src/redux/actions/experiments/loadExperiments.js
@@ -1,65 +1,32 @@
import fetchAPI from 'utils/http/fetchAPI';
import handleError from 'utils/http/handleError';
+import endUserMessages from 'utils/endUserMessages';
-import {
- EXPERIMENTS_LOADED,
- EXPERIMENTS_ERROR,
- EXPERIMENTS_LOADING,
-} from 'redux/actionTypes/experiments';
+import { EXPERIMENTS_ERROR, EXPERIMENTS_LOADED, EXPERIMENTS_LOADING } from 'redux/actionTypes/experiments';
-const toApiV1 = (experimentV2) => {
- const {
- id,
- name,
- description,
- samplesOrder,
- notifyByEmail,
- processingConfig,
- createdAt,
- pipelines,
- } = experimentV2;
-
- const experimentV1 = {
- experimentId: id,
- projectId: id,
- description,
- experimentName: name,
- processingConfig,
- createdDate: createdAt,
- notifyByEmail,
- sampleIds: samplesOrder,
- meta: {
- // This is always 10x and organism so we can just generate them here
- organism: null,
- type: '10x',
- gem2s: pipelines.gem2s ?? undefined,
- pipeline: pipelines.qc ?? undefined,
- },
- };
-
- return experimentV1;
-};
-
-const loadExperiments = (
- projectUuid,
-) => async (dispatch) => {
+const loadExperiments = () => async (dispatch) => {
dispatch({
type: EXPERIMENTS_LOADING,
});
try {
- let data = await fetchAPI(`/v2/experiments/${projectUuid}`);
+ const experiments = await fetchAPI('/v2/experiments');
- data = [toApiV1(data)];
+ experiments.forEach((experiment) => {
+ // eslint-disable-next-line no-param-reassign
+ experiment.sampleIds = experiment.samplesOrder;
+ // eslint-disable-next-line no-param-reassign
+ delete experiment.samplesOrder;
+ });
dispatch({
type: EXPERIMENTS_LOADED,
payload: {
- experiments: data,
+ experiments,
},
});
} catch (e) {
- const errorMessage = handleError(e);
+ const errorMessage = handleError(e, endUserMessages.ERROR_LOADING_PROJECT);
dispatch({
type: EXPERIMENTS_ERROR,
@@ -69,5 +36,4 @@ const loadExperiments = (
});
}
};
-
export default loadExperiments;
diff --git a/src/redux/actions/experiments/setActiveExperiment.js b/src/redux/actions/experiments/setActiveExperiment.js
new file mode 100644
index 0000000000..01b1e9920b
--- /dev/null
+++ b/src/redux/actions/experiments/setActiveExperiment.js
@@ -0,0 +1,20 @@
+import {
+ EXPERIMENTS_SET_ACTIVE,
+} from 'redux/actionTypes/experiments';
+
+const setActiveExperiment = (
+ experimentId,
+) => async (dispatch, getState) => {
+ const {
+ activeExperimentId,
+ } = getState().experiments.meta;
+
+ if (activeExperimentId === experimentId) return null;
+
+ dispatch({
+ type: EXPERIMENTS_SET_ACTIVE,
+ payload: { experimentId },
+ });
+};
+
+export default setActiveExperiment;
diff --git a/src/redux/actions/projects/updateMetadataTrack.js b/src/redux/actions/experiments/updateMetadataTrack.js
similarity index 73%
rename from src/redux/actions/projects/updateMetadataTrack.js
rename to src/redux/actions/experiments/updateMetadataTrack.js
index e01489be59..45147301ba 100644
--- a/src/redux/actions/projects/updateMetadataTrack.js
+++ b/src/redux/actions/experiments/updateMetadataTrack.js
@@ -1,8 +1,6 @@
import _ from 'lodash';
-import {
- PROJECTS_METADATA_UPDATE,
-} from 'redux/actionTypes/projects';
+import { EXPERIMENTS_METADATA_UPDATE } from 'redux/actionTypes/experiments';
import {
SAMPLES_UPDATE,
SAMPLES_METADATA_DELETE,
@@ -15,25 +13,25 @@ import endUserMessages from 'utils/endUserMessages';
import pushNotificationMessage from 'utils/pushNotificationMessage';
const updateMetadataTrack = (
- oldName, newName, projectUuid,
+ oldName, newName, experimentId,
) => async (dispatch, getState) => {
const { samples } = getState();
- const project = getState().projects[projectUuid];
+ const experiment = getState().experiments[experimentId];
const oldMetadataKey = metadataNameToKey(oldName);
const newMetadataKey = metadataNameToKey(newName);
- const newProject = _.cloneDeep(project);
- newProject.metadataKeys = newProject.metadataKeys
+ const newExperiment = _.cloneDeep(experiment);
+ newExperiment.metadataKeys = newExperiment.metadataKeys
.filter((key) => key !== oldMetadataKey);
- newProject.metadataKeys.push(newMetadataKey);
+ newExperiment.metadataKeys.push(newMetadataKey);
try {
const body = { key: newMetadataKey };
await fetchAPI(
- `/v2/experiments/${projectUuid}/metadataTracks/${oldMetadataKey}`,
+ `/v2/experiments/${experimentId}/metadataTracks/${oldMetadataKey}`,
{
method: 'PATCH',
headers: {
@@ -44,15 +42,15 @@ const updateMetadataTrack = (
);
dispatch({
- type: PROJECTS_METADATA_UPDATE,
+ type: EXPERIMENTS_METADATA_UPDATE,
payload: {
oldKey: oldMetadataKey,
newKey: newMetadataKey,
- projectUuid,
+ experimentId,
},
});
- project.samples.forEach((sampleUuid) => {
+ experiment.sampleIds.forEach((sampleUuid) => {
dispatch({
type: SAMPLES_UPDATE,
payload: {
diff --git a/src/redux/actions/projects/updateValueInMetadataTrack.js b/src/redux/actions/experiments/updateValueInMetadataTrack.js
similarity index 100%
rename from src/redux/actions/projects/updateValueInMetadataTrack.js
rename to src/redux/actions/experiments/updateValueInMetadataTrack.js
diff --git a/src/redux/actions/projects/createProject.js b/src/redux/actions/projects/createProject.js
deleted file mode 100644
index 7751cd88bd..0000000000
--- a/src/redux/actions/projects/createProject.js
+++ /dev/null
@@ -1,57 +0,0 @@
-import moment from 'moment';
-
-import {
- PROJECTS_CREATE,
- PROJECTS_ERROR,
- PROJECTS_SAVING,
-} from 'redux/actionTypes/projects';
-
-import { projectTemplate } from 'redux/reducers/projects/initialState';
-import createExperiment from 'redux/actions/experiments/createExperiment';
-import endUserMessages from 'utils/endUserMessages';
-import handleError from 'utils/http/handleError';
-
-const createProject = (
- projectName,
- projectDescription,
- newExperimentName,
-) => async (dispatch) => {
- const createdDate = moment().toISOString();
-
- try {
- dispatch({
- type: PROJECTS_SAVING,
- payload: {
- message: endUserMessages.SAVING_PROJECT,
- },
- });
-
- const experimentId = await dispatch(createExperiment(newExperimentName, projectDescription));
-
- const newProject = {
- ...projectTemplate,
- name: projectName,
- description: projectDescription,
- uuid: experimentId,
- experiments: [experimentId],
- createdDate,
- lastModified: createdDate,
- };
-
- dispatch({
- type: PROJECTS_CREATE,
- payload: { project: newProject },
- });
- } catch (e) {
- const errorMessage = handleError(e, endUserMessages.ERROR_CREATING_PROJECT);
-
- dispatch({
- type: PROJECTS_ERROR,
- payload: {
- error: errorMessage,
- },
- });
- }
-};
-
-export default createProject;
diff --git a/src/redux/actions/projects/index.js b/src/redux/actions/projects/index.js
deleted file mode 100644
index adfe6bce51..0000000000
--- a/src/redux/actions/projects/index.js
+++ /dev/null
@@ -1,21 +0,0 @@
-import loadProjects from './loadProjects';
-import createProject from './createProject';
-import updateProject from './updateProject';
-import deleteProject from './deleteProject';
-import setActiveProject from './setActiveProject';
-import createMetadataTrack from './createMetadataTrack';
-import updateMetadataTrack from './updateMetadataTrack';
-import deleteMetadataTrack from './deleteMetadataTrack';
-import updateValueInMetadataTrack from './updateValueInMetadataTrack';
-
-export {
- loadProjects,
- createProject,
- updateProject,
- deleteProject,
- setActiveProject,
- createMetadataTrack,
- updateMetadataTrack,
- deleteMetadataTrack,
- updateValueInMetadataTrack,
-};
diff --git a/src/redux/actions/projects/loadProjects.js b/src/redux/actions/projects/loadProjects.js
deleted file mode 100644
index fce64b2e30..0000000000
--- a/src/redux/actions/projects/loadProjects.js
+++ /dev/null
@@ -1,62 +0,0 @@
-import fetchAPI from 'utils/http/fetchAPI';
-import handleError from 'utils/http/handleError';
-import endUserMessages from 'utils/endUserMessages';
-import { PROJECTS_ERROR, PROJECTS_LOADED, PROJECTS_LOADING } from 'redux/actionTypes/projects';
-
-const toApiV1 = (experimentListV2) => {
- const projectsListV1 = experimentListV2.map((experimentData) => {
- const {
- createdAt,
- updatedAt,
- id,
- samplesOrder,
- ...restOfExperimentData
- } = experimentData;
-
- // Not assigning "lastAnalyzed" because that is no longer used anywhere
- const experimentDataV1 = {
- createdDate: createdAt,
- lastModified: updatedAt,
- experiments: [id],
- uuid: id,
- samples: samplesOrder,
- ...restOfExperimentData,
- };
-
- return experimentDataV1;
- });
-
- return projectsListV1;
-};
-
-const loadProjects = () => async (dispatch) => {
- dispatch({
- type: PROJECTS_LOADING,
- });
-
- try {
- let data = await fetchAPI('/v2/experiments');
-
- data = toApiV1(data);
-
- const ids = data.map((project) => project.uuid);
-
- dispatch({
- type: PROJECTS_LOADED,
- payload: {
- projects: data,
- ids,
- },
- });
- } catch (e) {
- const errorMessage = handleError(e, endUserMessages.ERROR_LOADING_PROJECT);
-
- dispatch({
- type: PROJECTS_ERROR,
- payload: {
- error: errorMessage,
- },
- });
- }
-};
-export default loadProjects;
diff --git a/src/redux/actions/projects/setActiveProject.js b/src/redux/actions/projects/setActiveProject.js
deleted file mode 100644
index e37a1058c7..0000000000
--- a/src/redux/actions/projects/setActiveProject.js
+++ /dev/null
@@ -1,20 +0,0 @@
-import {
- PROJECTS_SET_ACTIVE,
-} from '../../actionTypes/projects';
-
-const setActiveProject = (
- projectUuid,
-) => async (dispatch, getState) => {
- const {
- activeProjectUuid,
- } = getState().projects.meta;
-
- if (activeProjectUuid === projectUuid) return null;
-
- dispatch({
- type: PROJECTS_SET_ACTIVE,
- payload: { projectUuid },
- });
-};
-
-export default setActiveProject;
diff --git a/src/redux/actions/projects/updateProject.js b/src/redux/actions/projects/updateProject.js
deleted file mode 100644
index 9514b3af87..0000000000
--- a/src/redux/actions/projects/updateProject.js
+++ /dev/null
@@ -1,39 +0,0 @@
-import moment from 'moment';
-import _ from 'lodash';
-
-import endUserMessages from 'utils/endUserMessages';
-import mergeObjectReplacingArrays from 'utils/mergeObjectReplacingArrays';
-import handleError from 'utils/http/handleError';
-
-import {
- PROJECTS_UPDATE,
-} from '../../actionTypes/projects';
-
-const updateProject = (
- projectUuid,
- diff,
-) => async (dispatch, getState) => {
- const currentProject = _.cloneDeep(getState().projects[projectUuid]);
-
- // eslint-disable-next-line no-param-reassign
- diff.lastModified = moment().toISOString();
-
- const newProject = mergeObjectReplacingArrays(currentProject, diff);
-
- try {
- // With api.V2 dont do any fetch
- // updating the project is all we need from this action creator
-
- dispatch({
- type: PROJECTS_UPDATE,
- payload: {
- projectUuid,
- project: newProject,
- },
- });
- } catch (e) {
- handleError(e, endUserMessages.ERROR_SAVING);
- }
-};
-
-export default updateProject;
diff --git a/src/redux/actions/samples/createSample.js b/src/redux/actions/samples/createSample.js
index 0ececab89b..0b6dbcd548 100644
--- a/src/redux/actions/samples/createSample.js
+++ b/src/redux/actions/samples/createSample.js
@@ -5,27 +5,25 @@ import {
SAMPLES_CREATE, SAMPLES_ERROR, SAMPLES_SAVED, SAMPLES_SAVING,
} from 'redux/actionTypes/samples';
-import {
- DEFAULT_NA,
-} from 'redux/reducers/projects/initialState';
import fetchAPI from 'utils/http/fetchAPI';
import handleError from 'utils/http/handleError';
import endUserMessages from 'utils/endUserMessages';
+import { METADATA_DEFAULT_VALUE } from 'redux/reducers/experiments/initialState';
import { sampleTemplate } from 'redux/reducers/samples/initialState';
import UploadStatus from 'utils/upload/UploadStatus';
const createSample = (
- projectUuid,
+ experimentId,
name,
type,
filesToUpload,
) => async (dispatch, getState) => {
- const project = getState().projects[projectUuid];
- const createdDate = moment().toISOString();
- const experimentId = project.experiments[0];
+ const experiment = getState().experiments[experimentId];
+
const newSampleUuid = uuidv4();
+ const createdDate = moment().toISOString();
dispatch({
type: SAMPLES_SAVING,
@@ -38,12 +36,12 @@ const createSample = (
..._.cloneDeep(sampleTemplate),
name,
type,
- projectUuid,
+ experimentId,
uuid: newSampleUuid,
createdDate,
lastModified: createdDate,
- metadata: project?.metadataKeys
- .reduce((acc, curr) => ({ ...acc, [curr]: DEFAULT_NA }), {}) || {},
+ metadata: experiment?.metadataKeys
+ .reduce((acc, curr) => ({ ...acc, [curr]: METADATA_DEFAULT_VALUE }), {}) || {},
};
const url = `/v2/experiments/${experimentId}/samples/${newSampleUuid}`;
diff --git a/src/redux/actions/samples/deleteSamples.js b/src/redux/actions/samples/deleteSamples.js
index 6a59af1883..29c2dbce6a 100644
--- a/src/redux/actions/samples/deleteSamples.js
+++ b/src/redux/actions/samples/deleteSamples.js
@@ -25,21 +25,21 @@ const cancelUploads = async (files) => {
const deleteSamples = (
sampleIds,
) => async (dispatch, getState) => {
- const { samples, projects } = getState();
+ const { samples } = getState();
const projectSamples = await sampleIds.reduce(async (acc, sampleUuid) => {
- const { projectUuid, files } = samples[sampleUuid];
+ const { experimentId, files } = samples[sampleUuid];
- if (!_.has(acc, samples[sampleUuid].projectUuid)) {
- acc[samples[sampleUuid].projectUuid] = [];
+ if (!_.has(acc, samples[sampleUuid].experimentId)) {
+ acc[samples[sampleUuid].experimentId] = [];
}
await cancelUploads(files);
return {
...acc,
- [projectUuid]: [
- ...acc[projectUuid],
+ [experimentId]: [
+ ...acc[experimentId],
sampleUuid,
],
};
@@ -54,9 +54,7 @@ const deleteSamples = (
try {
const deleteSamplesPromise = Object.entries(projectSamples).map(
- async ([projectUuid, samplesToDelete]) => {
- const experimentId = projects[projectUuid].experiments[0];
-
+ async ([experimentId, samplesToDelete]) => {
await Promise.all(sampleIds.map(async (sampleUuid) => {
await fetchAPI(
`/v2/experiments/${experimentId}/samples/${sampleUuid}`,
diff --git a/src/redux/actions/samples/loadSamples.js b/src/redux/actions/samples/loadSamples.js
index 654b26a246..aecb106334 100644
--- a/src/redux/actions/samples/loadSamples.js
+++ b/src/redux/actions/samples/loadSamples.js
@@ -49,7 +49,7 @@ const toApiV1 = (samples, experimentId) => {
samples.forEach((sample) => {
const { apiV1Files, fileNames } = buildApiv1Files(sample.files);
apiV1Samples[sample.id] = {
- projectUuid: experimentId,
+ experimentId,
metadata: sample.metadata,
createdDate: sample.createdAt,
name: sample.name,
diff --git a/src/redux/actions/samples/updateSample.js b/src/redux/actions/samples/updateSample.js
index cc0489e8cd..4961ab47b6 100644
--- a/src/redux/actions/samples/updateSample.js
+++ b/src/redux/actions/samples/updateSample.js
@@ -10,8 +10,8 @@ import handleError from 'utils/http/handleError';
import fetchAPI from 'utils/http/fetchAPI';
const updateSample = (sampleUuid, diff) => async (dispatch, getState) => {
- // In api v2 projectUuid and experimentId are the same
- const experimentId = getState().samples[sampleUuid].projectUuid;
+ // In api v2 experimentId and experimentId are the same
+ const { experimentId } = getState().samples[sampleUuid];
if (_.isNil(diff.name) || diff.metadata) {
throw new Error('This action can be used to update only the name in sample');
diff --git a/src/redux/reducers/experiments/experimentsCreate.js b/src/redux/reducers/experiments/experimentsCreate.js
index ab959303db..20252902e9 100644
--- a/src/redux/reducers/experiments/experimentsCreate.js
+++ b/src/redux/reducers/experiments/experimentsCreate.js
@@ -3,7 +3,7 @@ import { experimentTemplate } from 'redux/reducers/experiments/initialState';
const experimentCreate = (state, action) => {
const {
experiment: {
- id, name, description, createdDate,
+ id, name, description, createdAt,
},
} = action.payload;
@@ -12,8 +12,7 @@ const experimentCreate = (state, action) => {
id,
name,
description,
- projectUuid: id,
- createdDate,
+ createdAt,
};
return {
@@ -22,6 +21,7 @@ const experimentCreate = (state, action) => {
[newExperiment.id]: newExperiment,
meta: {
...state.meta,
+ activeExperimentId: newExperiment.id,
saving: false,
},
};
diff --git a/src/redux/reducers/experiments/experimentsDelete.js b/src/redux/reducers/experiments/experimentsDelete.js
index 0c05351b9d..c19909bf3a 100644
--- a/src/redux/reducers/experiments/experimentsDelete.js
+++ b/src/redux/reducers/experiments/experimentsDelete.js
@@ -14,6 +14,10 @@ const experimentsDelete = (state, action) => {
return {
ids: newIds,
...remainingExperiments,
+ meta: {
+ ...state.meta,
+ saving: false,
+ },
};
};
diff --git a/src/redux/reducers/experiments/experimentsLoaded.js b/src/redux/reducers/experiments/experimentsLoaded.js
index 23bf4c1043..7d22da19fc 100644
--- a/src/redux/reducers/experiments/experimentsLoaded.js
+++ b/src/redux/reducers/experiments/experimentsLoaded.js
@@ -1,40 +1,29 @@
-const convertedToUIModel = (experiment) => ({
- ...experiment,
- id: experiment.experimentId,
- name: experiment.experimentName,
- projectUuid: experiment.projectId,
-});
+/* eslint-disable no-param-reassign */
+import produce, { original } from 'immer';
+
+import _ from 'lodash';
-const experimentsLoaded = (state, action) => {
+const experimentsLoaded = produce((draft, action) => {
const { experiments } = action.payload;
- const newExperiments = experiments.reduce((acc, curr) => {
- if (!acc.ids.includes(curr.experimentId)) acc.ids.push(curr.experimentId);
-
- const uiModelExp = convertedToUIModel(curr);
-
- acc[curr.experimentId] = {
- projectUuid: uiModelExp.projectUuid,
- name: uiModelExp.name,
- description: uiModelExp.description,
- id: uiModelExp.id,
- createdDate: uiModelExp.createdDate,
- meta: uiModelExp.meta,
- sampleIds: uiModelExp.sampleIds,
- notifyByEmail: curr.notifyByEmail,
- };
-
- return acc;
- }, { ids: [...state.ids] });
-
- return {
- ...state,
- ...newExperiments,
- meta: {
- ...state.meta,
- loading: false,
- },
- };
-};
+ const originalState = original(draft);
+
+ let newActiveExperimentId = originalState.meta.activeExperimentId;
+
+ // If the current active experiment no longer exists, change it
+ if (!Object.keys(originalState).includes(newActiveExperimentId)) {
+ newActiveExperimentId = experiments[0]?.id;
+ }
+
+ const ids = _.map(experiments, 'id');
+
+ draft.meta.activeExperimentId = experiments[0].id;
+ draft.meta.loading = false;
+ draft.ids = ids;
+
+ experiments.forEach((experiment) => {
+ draft[experiment.id] = experiment;
+ });
+});
export default experimentsLoaded;
diff --git a/src/redux/reducers/experiments/experimentsMetadataCreate.js b/src/redux/reducers/experiments/experimentsMetadataCreate.js
new file mode 100644
index 0000000000..4e2eccbbbc
--- /dev/null
+++ b/src/redux/reducers/experiments/experimentsMetadataCreate.js
@@ -0,0 +1,16 @@
+const experimentsMetadataCreate = (state, action) => {
+ const { key, experimentId } = action.payload;
+
+ return {
+ ...state,
+ [experimentId]: {
+ ...state[experimentId],
+ metadataKeys: [
+ ...state[experimentId].metadataKeys,
+ key,
+ ],
+ },
+ };
+};
+
+export default experimentsMetadataCreate;
diff --git a/src/redux/reducers/experiments/experimentsMetadataDelete.js b/src/redux/reducers/experiments/experimentsMetadataDelete.js
new file mode 100644
index 0000000000..4609efca3e
--- /dev/null
+++ b/src/redux/reducers/experiments/experimentsMetadataDelete.js
@@ -0,0 +1,15 @@
+const projectsMetadataDelete = (state, action) => {
+ const { key, experimentId } = action.payload;
+
+ return {
+ ...state,
+ [experimentId]: {
+ ...state[experimentId],
+ metadataKeys: [
+ ...state[experimentId].metadataKeys.filter((value) => value !== key),
+ ],
+ },
+ };
+};
+
+export default projectsMetadataDelete;
diff --git a/src/redux/reducers/experiments/experimentsMetadataUpdate.js b/src/redux/reducers/experiments/experimentsMetadataUpdate.js
new file mode 100644
index 0000000000..be4e401073
--- /dev/null
+++ b/src/redux/reducers/experiments/experimentsMetadataUpdate.js
@@ -0,0 +1,16 @@
+const projectsMetadataUpdate = (state, action) => {
+ const { oldKey, newKey, experimentId } = action.payload;
+
+ return {
+ ...state,
+ [experimentId]: {
+ ...state[experimentId],
+ metadataKeys: [
+ ...state[experimentId].metadataKeys.filter((value) => value !== oldKey),
+ newKey,
+ ],
+ },
+ };
+};
+
+export default projectsMetadataUpdate;
diff --git a/src/redux/reducers/experiments/experimentsSaving.js b/src/redux/reducers/experiments/experimentsSaving.js
index 008a537af3..bffac2363b 100644
--- a/src/redux/reducers/experiments/experimentsSaving.js
+++ b/src/redux/reducers/experiments/experimentsSaving.js
@@ -2,7 +2,7 @@ const experimentSaving = (state) => ({
...state,
meta: {
...state.meta,
- saving: false,
+ saving: true,
error: false,
},
});
diff --git a/src/redux/reducers/projects/projectsSetActive.js b/src/redux/reducers/experiments/experimentsSetActive.js
similarity index 65%
rename from src/redux/reducers/projects/projectsSetActive.js
rename to src/redux/reducers/experiments/experimentsSetActive.js
index a2a7bdf90a..ab86b1b9f6 100644
--- a/src/redux/reducers/projects/projectsSetActive.js
+++ b/src/redux/reducers/experiments/experimentsSetActive.js
@@ -1,10 +1,10 @@
const projectsSetActive = (state, action) => {
- const { projectUuid } = action.payload;
+ const { experimentId } = action.payload;
return {
...state,
meta: {
...state.meta,
- activeProjectUuid: projectUuid,
+ activeExperimentId: experimentId,
},
};
};
diff --git a/src/redux/reducers/experiments/index.js b/src/redux/reducers/experiments/index.js
index 0db1fd671c..2dc5fd5e75 100644
--- a/src/redux/reducers/experiments/index.js
+++ b/src/redux/reducers/experiments/index.js
@@ -1,4 +1,4 @@
-import initialState from './initialState';
+import initialState from 'redux/reducers/experiments/initialState';
import {
EXPERIMENTS_CREATED,
EXPERIMENTS_UPDATED,
@@ -7,19 +7,27 @@ import {
EXPERIMENTS_ERROR,
EXPERIMENTS_SAVING,
EXPERIMENTS_DELETED,
-} from '../../actionTypes/experiments';
+ EXPERIMENTS_METADATA_CREATE,
+ EXPERIMENTS_METADATA_DELETE,
+ EXPERIMENTS_METADATA_UPDATE,
+ EXPERIMENTS_SET_ACTIVE,
+} from 'redux/actionTypes/experiments';
import {
SAMPLES_CREATE, SAMPLES_DELETE,
-} from '../../actionTypes/samples';
+} from 'redux/actionTypes/samples';
import experimentsCreate from './experimentsCreate';
import experimentsUpdate from './experimentsUpdate';
import experimentsDelete from './experimentsDelete';
+import experimentsSetActive from './experimentsSetActive';
import experimentsLoading from './experimentsLoading';
import experimentsLoaded from './experimentsLoaded';
import experimentsError from './experimentsError';
import experimentsSaving from './experimentsSaving';
+import experimentsMetadataCreate from './experimentsMetadataCreate';
+import experimentsMetadataUpdate from './experimentsMetadataUpdate';
+import experimentsMetadataDelete from './experimentsMetadataDelete';
import samplesCreate from './samplesCreate';
import samplesDelete from './samplesDelete';
@@ -38,6 +46,10 @@ const experimentsReducer = (state = initialState, action) => {
return experimentsDelete(state, action);
}
+ case EXPERIMENTS_SET_ACTIVE: {
+ return experimentsSetActive(state, action);
+ }
+
case EXPERIMENTS_LOADING: {
return experimentsLoading(state, action);
}
@@ -62,6 +74,18 @@ const experimentsReducer = (state = initialState, action) => {
return samplesDelete(state, action);
}
+ case EXPERIMENTS_METADATA_CREATE: {
+ return experimentsMetadataCreate(state, action);
+ }
+
+ case EXPERIMENTS_METADATA_UPDATE: {
+ return experimentsMetadataUpdate(state, action);
+ }
+
+ case EXPERIMENTS_METADATA_DELETE: {
+ return experimentsMetadataDelete(state, action);
+ }
+
default: {
return state;
}
diff --git a/src/redux/reducers/experiments/initialState.js b/src/redux/reducers/experiments/initialState.js
index fd85388cd1..e07e2ef61e 100644
--- a/src/redux/reducers/experiments/initialState.js
+++ b/src/redux/reducers/experiments/initialState.js
@@ -1,12 +1,13 @@
const experimentTemplate = {
- projectUuid: null,
name: null,
description: 'Analysis description',
id: null,
- createdDate: null,
+ createdAt: null,
+ updatedAt: null,
notifyByEmail: true,
meta: { organism: null, type: '10x' },
sampleIds: [],
+ metadataKeys: [],
};
const initialState = {
@@ -14,9 +15,12 @@ const initialState = {
loading: false,
error: false,
saving: false,
+ activeExperimentId: null,
},
ids: [],
};
+const METADATA_DEFAULT_VALUE = 'N.A.';
+
export default initialState;
-export { experimentTemplate };
+export { experimentTemplate, METADATA_DEFAULT_VALUE };
diff --git a/src/redux/reducers/index.js b/src/redux/reducers/index.js
index 13fee1e232..40fed75593 100644
--- a/src/redux/reducers/index.js
+++ b/src/redux/reducers/index.js
@@ -10,7 +10,6 @@ import experimentsReducer from './experiments';
import experimentSettingsReducer from './experimentSettings';
import genesReducer from './genes';
import layoutReducer from './layout';
-import projectsReducer from './projects';
import sampleReducer from './samples';
import networkResourcesReducer from './networkResources';
import backendStatusReducer from './backendStatus';
@@ -28,7 +27,6 @@ const appReducers = combineReducers({
backendStatus: backendStatusReducer,
genes: genesReducer,
layout: layoutReducer,
- projects: projectsReducer,
samples: sampleReducer,
networkResources: networkResourcesReducer,
});
diff --git a/src/redux/reducers/projects/index.js b/src/redux/reducers/projects/index.js
deleted file mode 100644
index 6b27f1dd8d..0000000000
--- a/src/redux/reducers/projects/index.js
+++ /dev/null
@@ -1,101 +0,0 @@
-import {
- PROJECTS_CREATE,
- PROJECTS_UPDATE,
- PROJECTS_SET_ACTIVE,
- PROJECTS_DELETE,
- PROJECTS_SAVING,
- PROJECTS_SAVED,
- PROJECTS_ERROR,
- PROJECTS_METADATA_CREATE,
- PROJECTS_METADATA_UPDATE,
- PROJECTS_METADATA_DELETE,
- PROJECTS_LOADED,
- PROJECTS_LOADING,
-} from '../../actionTypes/projects';
-
-import initialState from './initialState';
-import projectsCreate from './projectsCreate';
-import projectsUpdate from './projectsUpdate';
-import projectsDelete from './projectsDelete';
-import projectsSetActive from './projectsSetActive';
-import projectsSaving from './projectsSaving';
-import projectsSaved from './projectsSaved';
-import projectsError from './projectsError';
-import projectsMetadataCreate from './projectsMetadataCreate';
-import projectsMetadataUpdate from './projectsMetadataUpdate';
-import projectsMetadataDelete from './projectsMetadataDelete';
-import projectsLoaded from './projectsLoaded';
-import projectsLoading from './projectsLoading';
-
-import {
- SAMPLES_CREATE, SAMPLES_DELETE,
-} from '../../actionTypes/samples';
-
-import samplesCreate from './samplesCreate';
-import samplesDelete from './samplesDelete';
-
-const projectsReducer = (state = initialState, action) => {
- switch (action.type) {
- case PROJECTS_CREATE: {
- return projectsCreate(state, action);
- }
-
- case PROJECTS_UPDATE: {
- return projectsUpdate(state, action);
- }
-
- case PROJECTS_SET_ACTIVE: {
- return projectsSetActive(state, action);
- }
-
- case PROJECTS_DELETE: {
- return projectsDelete(state, action);
- }
-
- case PROJECTS_SAVING: {
- return projectsSaving(state, action);
- }
-
- case PROJECTS_SAVED: {
- return projectsSaved(state);
- }
-
- case PROJECTS_ERROR: {
- return projectsError(state, action);
- }
-
- case PROJECTS_METADATA_CREATE: {
- return projectsMetadataCreate(state, action);
- }
-
- case PROJECTS_METADATA_UPDATE: {
- return projectsMetadataUpdate(state, action);
- }
-
- case PROJECTS_METADATA_DELETE: {
- return projectsMetadataDelete(state, action);
- }
-
- case PROJECTS_LOADED: {
- return projectsLoaded(state, action);
- }
-
- case PROJECTS_LOADING: {
- return projectsLoading(state);
- }
-
- case SAMPLES_CREATE: {
- return samplesCreate(state, action);
- }
-
- case SAMPLES_DELETE: {
- return samplesDelete(state, action);
- }
-
- default: {
- return state;
- }
- }
-};
-
-export default projectsReducer;
diff --git a/src/redux/reducers/projects/initialState.js b/src/redux/reducers/projects/initialState.js
deleted file mode 100644
index 1e3792af6d..0000000000
--- a/src/redux/reducers/projects/initialState.js
+++ /dev/null
@@ -1,26 +0,0 @@
-const projectTemplate = {
- name: null,
- description: null,
- metadataKeys: [],
- uuid: null,
- experiments: [],
- createdDate: null,
- lastModified: null,
- samples: [],
- lastAnalyzed: null,
-};
-
-const initialState = {
- ids: [],
- meta: {
- activeProjectUuid: null,
- loading: true,
- error: false,
- saving: false,
- },
-};
-
-const DEFAULT_NA = 'N.A.';
-
-export default initialState;
-export { projectTemplate, DEFAULT_NA };
diff --git a/src/redux/reducers/projects/projectsCreate.js b/src/redux/reducers/projects/projectsCreate.js
deleted file mode 100644
index b9a9270638..0000000000
--- a/src/redux/reducers/projects/projectsCreate.js
+++ /dev/null
@@ -1,15 +0,0 @@
-const projectsCreate = (state, action) => {
- const { project } = action.payload;
- return {
- ...state,
- ids: [...state.ids, project.uuid],
- meta: {
- ...state.meta,
- activeProjectUuid: project.uuid,
- saving: false,
- },
- [project.uuid]: project,
- };
-};
-
-export default projectsCreate;
diff --git a/src/redux/reducers/projects/projectsDelete.js b/src/redux/reducers/projects/projectsDelete.js
deleted file mode 100644
index 25b690177d..0000000000
--- a/src/redux/reducers/projects/projectsDelete.js
+++ /dev/null
@@ -1,18 +0,0 @@
-import _ from 'lodash';
-
-const projectsDelete = (state, action) => {
- const { projectUuid } = action.payload;
-
- let updatedObject = null;
-
- if (!_.has(state, projectUuid)) {
- return state;
- }
-
- updatedObject = _.omit(state, projectUuid);
- updatedObject.ids = updatedObject.ids.filter((p) => p !== projectUuid);
-
- return updatedObject;
-};
-
-export default projectsDelete;
diff --git a/src/redux/reducers/projects/projectsError.js b/src/redux/reducers/projects/projectsError.js
deleted file mode 100644
index 08d9afd232..0000000000
--- a/src/redux/reducers/projects/projectsError.js
+++ /dev/null
@@ -1,16 +0,0 @@
-import initialState from './initialState';
-
-const projectsError = (state, action) => {
- const { error } = action.payload;
- return {
- ...initialState,
- ...state,
- meta: {
- ...state.meta,
- saving: false,
- error,
- },
- };
-};
-
-export default projectsError;
diff --git a/src/redux/reducers/projects/projectsLoaded.js b/src/redux/reducers/projects/projectsLoaded.js
deleted file mode 100644
index 3b42a7a33c..0000000000
--- a/src/redux/reducers/projects/projectsLoaded.js
+++ /dev/null
@@ -1,26 +0,0 @@
-const projectsLoaded = (state, action) => {
- const { projects, ids } = action.payload;
-
- const newProjects = {};
- projects.forEach((project) => {
- newProjects[project.uuid] = project;
- });
-
- let activeProjectId = state.meta.activeProjectUuid;
-
- // If the current active project no longer exists, change it
- if (!Object.keys(state).includes(activeProjectId)) {
- activeProjectId = projects[0]?.uuid;
- }
-
- return {
- ...state,
- ids,
- loading: false,
- ...newProjects,
- meta: {
- activeProjectUuid: activeProjectId,
- },
- };
-};
-export default projectsLoaded;
diff --git a/src/redux/reducers/projects/projectsLoading.js b/src/redux/reducers/projects/projectsLoading.js
deleted file mode 100644
index b7bd588868..0000000000
--- a/src/redux/reducers/projects/projectsLoading.js
+++ /dev/null
@@ -1,5 +0,0 @@
-const projectsLoading = (state) => ({
- ...state,
- loading: true,
-});
-export default projectsLoading;
diff --git a/src/redux/reducers/projects/projectsMetadataCreate.js b/src/redux/reducers/projects/projectsMetadataCreate.js
deleted file mode 100644
index f99b0c4f50..0000000000
--- a/src/redux/reducers/projects/projectsMetadataCreate.js
+++ /dev/null
@@ -1,16 +0,0 @@
-const projectsMetadataCreate = (state, action) => {
- const { key, projectUuid } = action.payload;
-
- return {
- ...state,
- [projectUuid]: {
- ...state[projectUuid],
- metadataKeys: [
- ...state[projectUuid].metadataKeys,
- key,
- ],
- },
- };
-};
-
-export default projectsMetadataCreate;
diff --git a/src/redux/reducers/projects/projectsMetadataDelete.js b/src/redux/reducers/projects/projectsMetadataDelete.js
deleted file mode 100644
index c3629e810f..0000000000
--- a/src/redux/reducers/projects/projectsMetadataDelete.js
+++ /dev/null
@@ -1,15 +0,0 @@
-const projectsMetadataDelete = (state, action) => {
- const { key, projectUuid } = action.payload;
-
- return {
- ...state,
- [projectUuid]: {
- ...state[projectUuid],
- metadataKeys: [
- ...state[projectUuid].metadataKeys.filter((value) => value !== key),
- ],
- },
- };
-};
-
-export default projectsMetadataDelete;
diff --git a/src/redux/reducers/projects/projectsMetadataUpdate.js b/src/redux/reducers/projects/projectsMetadataUpdate.js
deleted file mode 100644
index c18d82b881..0000000000
--- a/src/redux/reducers/projects/projectsMetadataUpdate.js
+++ /dev/null
@@ -1,16 +0,0 @@
-const projectsMetadataUpdate = (state, action) => {
- const { oldKey, newKey, projectUuid } = action.payload;
-
- return {
- ...state,
- [projectUuid]: {
- ...state[projectUuid],
- metadataKeys: [
- ...state[projectUuid].metadataKeys.filter((value) => value !== oldKey),
- newKey,
- ],
- },
- };
-};
-
-export default projectsMetadataUpdate;
diff --git a/src/redux/reducers/projects/projectsSaved.js b/src/redux/reducers/projects/projectsSaved.js
deleted file mode 100644
index f2ba0cef6b..0000000000
--- a/src/redux/reducers/projects/projectsSaved.js
+++ /dev/null
@@ -1,12 +0,0 @@
-import initialState from './initialState';
-
-const projectsSaved = (state) => ({
- ...initialState,
- ...state,
- meta: {
- ...state.meta,
- saving: false,
- },
-});
-
-export default projectsSaved;
diff --git a/src/redux/reducers/projects/projectsSaving.js b/src/redux/reducers/projects/projectsSaving.js
deleted file mode 100644
index f633271809..0000000000
--- a/src/redux/reducers/projects/projectsSaving.js
+++ /dev/null
@@ -1,17 +0,0 @@
-import initialState from './initialState';
-
-const projectsSaving = (state, action) => {
- const { message } = action.payload;
-
- return {
- ...initialState,
- ...state,
- meta: {
- ...state.meta,
- saving: message,
- error: false,
- },
- };
-};
-
-export default projectsSaving;
diff --git a/src/redux/reducers/projects/projectsUpdate.js b/src/redux/reducers/projects/projectsUpdate.js
deleted file mode 100644
index 40bd62a6d4..0000000000
--- a/src/redux/reducers/projects/projectsUpdate.js
+++ /dev/null
@@ -1,13 +0,0 @@
-const projectsUpdate = (state, action) => {
- const { projectUuid, project } = action.payload;
-
- return {
- ...state,
- [projectUuid]: {
- ...state[projectUuid],
- ...project,
- },
- };
-};
-
-export default projectsUpdate;
diff --git a/src/redux/reducers/projects/samplesCreate.js b/src/redux/reducers/projects/samplesCreate.js
deleted file mode 100644
index c19b8672ad..0000000000
--- a/src/redux/reducers/projects/samplesCreate.js
+++ /dev/null
@@ -1,13 +0,0 @@
-import produce from 'immer';
-
-import initialState from './initialState';
-
-const samplesCreate = produce((draft, action) => {
- const { sample } = action.payload;
-
- const { projectUuid, uuid: newSampleUuid } = sample;
-
- draft[projectUuid].samples.push(newSampleUuid);
-}, initialState);
-
-export default samplesCreate;
diff --git a/src/redux/reducers/projects/samplesDelete.js b/src/redux/reducers/projects/samplesDelete.js
deleted file mode 100644
index 8a6887feb8..0000000000
--- a/src/redux/reducers/projects/samplesDelete.js
+++ /dev/null
@@ -1,12 +0,0 @@
-import _ from 'lodash';
-import produce from 'immer';
-
-import initialState from './initialState';
-
-const samplesDelete = produce((draft, action) => {
- const { experimentId, sampleIds } = action.payload;
-
- _.pullAll(draft[experimentId].samples, sampleIds);
-}, initialState);
-
-export default samplesDelete;
diff --git a/src/redux/reducers/samples/initialState.js b/src/redux/reducers/samples/initialState.js
index 289f8eb8cf..2b83ad2c68 100644
--- a/src/redux/reducers/samples/initialState.js
+++ b/src/redux/reducers/samples/initialState.js
@@ -1,6 +1,6 @@
const sampleTemplate = {
name: null,
- projectUuid: null,
+ experimentId: null,
uuid: null,
type: null,
createdDate: null,
diff --git a/src/utils/AppRouteProvider.jsx b/src/utils/AppRouteProvider.jsx
index b155ba9046..9ef5d7d4a8 100644
--- a/src/utils/AppRouteProvider.jsx
+++ b/src/utils/AppRouteProvider.jsx
@@ -85,7 +85,7 @@ const AppRouteProvider = (props) => {
}
if (previousRoute.match(PATH_STUBS.DATA_MANAGEMENT)) {
- // Update active project and experiment id when navigating from Data Management
+ // Update active experiment id when navigating from Data Management
const { experimentId } = params;
updateExperimentInfoOnNavigate(experimentId);
}
diff --git a/src/utils/data-management/calculateGem2sRerunStatus.js b/src/utils/data-management/calculateGem2sRerunStatus.js
index a0d1df795f..cd95d26c07 100644
--- a/src/utils/data-management/calculateGem2sRerunStatus.js
+++ b/src/utils/data-management/calculateGem2sRerunStatus.js
@@ -2,15 +2,14 @@ import pipelineStatus from 'utils/pipelineStatusValues';
import generateGem2sParamsHash from './generateGem2sParamsHash';
const calculateGem2sRerunStatus = (
- gem2sBackendStatus, activeProject, samples, experiment,
+ gem2sBackendStatus, activeExperiment, samples,
) => {
const gem2sStatus = gem2sBackendStatus?.status;
const existingParamsHash = gem2sBackendStatus?.paramsHash;
const newParamsHash = generateGem2sParamsHash(
- activeProject,
+ activeExperiment,
samples,
- experiment,
);
const projectHashEqual = existingParamsHash === newParamsHash;
diff --git a/src/utils/data-management/downloadSingleFile.js b/src/utils/data-management/downloadSingleFile.js
index 8fe5164ffd..f7011b7dd8 100644
--- a/src/utils/data-management/downloadSingleFile.js
+++ b/src/utils/data-management/downloadSingleFile.js
@@ -3,10 +3,10 @@ import fetchAPI from 'utils/http/fetchAPI';
import getFileTypeV2 from 'utils/getFileTypeV2';
-const downloadSingleFile = async (activeProjectUuid, sampleUuid, fileName) => {
+const downloadSingleFile = async (experimentId, sampleUuid, fileName) => {
const fileType = getFileTypeV2(fileName);
- const requestUrl = `/v2/experiments/${activeProjectUuid}/samples/${sampleUuid}/files/${fileType}/downloadUrl`;
+ const requestUrl = `/v2/experiments/${experimentId}/samples/${sampleUuid}/files/${fileType}/downloadUrl`;
const downloadUrl = await fetchAPI(requestUrl);
downloadFromUrl(downloadUrl);
diff --git a/src/utils/data-management/experimentSharing/sendInvites.js b/src/utils/data-management/experimentSharing/sendInvites.js
index 24e8ef9f72..02c08af0dd 100644
--- a/src/utils/data-management/experimentSharing/sendInvites.js
+++ b/src/utils/data-management/experimentSharing/sendInvites.js
@@ -4,7 +4,7 @@ import handleError from 'utils/http/handleError';
const sendInvites = async (addedUsers, experimentInfo) => {
const {
- experimentId, experimentName, activeProjectUuid, role,
+ experimentId, experimentName, role,
} = experimentInfo;
const requests = addedUsers.map(async (user) => {
@@ -17,7 +17,9 @@ const sendInvites = async (addedUsers, experimentInfo) => {
'Content-Type': 'application/json',
},
body: JSON.stringify({
- projectUuid: activeProjectUuid,
+ // TODO nothing in the api v2 should use a reference to project,
+ // so we'll need a ticket to fix this in this api endpoint
+ projectUuid: experimentId,
role,
userEmail: user,
}),
diff --git a/src/utils/data-management/generateGem2sParamsHash.js b/src/utils/data-management/generateGem2sParamsHash.js
index 1c8f494b24..6724af751c 100644
--- a/src/utils/data-management/generateGem2sParamsHash.js
+++ b/src/utils/data-management/generateGem2sParamsHash.js
@@ -1,35 +1,34 @@
import objectHash from 'object-hash';
+import { METADATA_DEFAULT_VALUE } from 'redux/reducers/experiments/initialState';
-import { DEFAULT_NA } from 'redux/reducers/projects/initialState';
-
-const generateGem2sParamsHash = (project, samples, experiment) => {
- if (!project || !samples || !experiment) {
+const generateGem2sParamsHash = (experiment, samples) => {
+ if (!experiment || !samples) {
return false;
}
const projectSamples = Object.entries(samples)
.sort()
- .filter(([key]) => project?.samples?.includes(key));
+ .filter(([key]) => experiment?.sampleIds?.includes(key));
const existingSampleIds = projectSamples.map(([, sample]) => sample.uuid);
// Different sample order should not change the hash.
const orderInvariantSampleIds = [...existingSampleIds].sort();
const hashParams = {
- organism: experiment.meta.organism,
- input: { type: experiment.meta.type },
+ organism: null,
+ input: { type: '10x' },
sampleIds: orderInvariantSampleIds,
sampleNames: orderInvariantSampleIds.map((sampleId) => samples[sampleId].name),
};
- if (project.metadataKeys.length) {
- const orderInvariantProjectMetadataKeys = [...project.metadataKeys].sort();
+ if (experiment.metadataKeys.length) {
+ const orderInvariantProjectMetadataKeys = [...experiment.metadataKeys].sort();
hashParams.metadata = orderInvariantProjectMetadataKeys.reduce((acc, key) => {
// Make sure the key does not contain '-' as it will cause failure in GEM2S
const sanitizedKey = key.replace(/-+/g, '_');
acc[sanitizedKey] = projectSamples.map(
- ([, sample]) => sample.metadata[key] || DEFAULT_NA,
+ ([, sample]) => sample.metadata[key] || METADATA_DEFAULT_VALUE,
);
return acc;
}, {});
diff --git a/src/utils/upload/processUpload.js b/src/utils/upload/processUpload.js
index 00e506885a..7a80ac82e7 100644
--- a/src/utils/upload/processUpload.js
+++ b/src/utils/upload/processUpload.js
@@ -94,12 +94,12 @@ const createAndUploadSingleFile = async (file, projectId, sampleId, dispatch) =>
await prepareAndUploadFileToS3(projectId, sampleId, fileType, file, signedUrl, dispatch);
};
-const createAndUpload = async (sample, activeProjectUuid, dispatch) => (
+const createAndUpload = async (sample, experimentId, dispatch) => (
Object.values(sample.files).map(
- (file) => createAndUploadSingleFile(file, activeProjectUuid, sample.uuid, dispatch),
+ (file) => createAndUploadSingleFile(file, experimentId, sample.uuid, dispatch),
));
-const processUpload = async (filesList, sampleType, samples, activeProjectUuid, dispatch) => {
+const processUpload = async (filesList, sampleType, samples, experimentId, dispatch) => {
const samplesMap = filesList.reduce((acc, file) => {
const pathToArray = file.name.trim().replace(/[\s]{2,}/ig, ' ').split('/');
@@ -112,7 +112,7 @@ const processUpload = async (filesList, sampleType, samples, activeProjectUuid,
const sampleUuid = Object.values(samples).filter(
(s) => s.name === sampleName
- && s.projectUuid === activeProjectUuid,
+ && s.experimentId === experimentId,
)[0]?.uuid;
return {
@@ -134,14 +134,14 @@ const processUpload = async (filesList, sampleType, samples, activeProjectUuid,
// Create sample if not exists.
try {
sample.uuid ??= await dispatch(
- createSample(activeProjectUuid, name, sampleType, filesToUploadForSample),
+ createSample(experimentId, name, sampleType, filesToUploadForSample),
);
} catch (e) {
// If sample creation fails, sample should not be created
return;
}
- createAndUpload(sample, activeProjectUuid, dispatch);
+ createAndUpload(sample, experimentId, dispatch);
});
};