Skip to content

Commit

Permalink
Merge pull request #1891 from sanger/move-ont-pools-to-fetch
Browse files Browse the repository at this point in the history
Y24-345 - Ont Pools store migration from axios to native fetch to reduce dependencies and increase maintainability.
  • Loading branch information
stevieing authored Oct 18, 2024
2 parents 7282c58 + 984ab75 commit 6410f26
Show file tree
Hide file tree
Showing 39 changed files with 14,538 additions and 18,294 deletions.
74 changes: 74 additions & 0 deletions src/api/JsonApi.js
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,78 @@ const splitDataByParent = ({
}, {})
}

/**
* Extract the includes from the relationships
* If the relationship is an array, then extract all the includes
* If the relationship is an object, then extract the include
* If the includes have their own relationships, then extract those
* @param {Object} relationships - the list of relationships to be extracted
* @param {Array} included - the list of included resources
* @param {Number} depth - the depth of the extraction
* @param {Number} maximumDepth - the maximum depth of the extraction. This is to prevent stack overflow error. Default is 3 (enough to get all data out for standard response). Othwerwise it gets stuck in an endless loop e.g. tags and tag sets.
* @returns {Array} - the list of extracted includes
*/
const extractIncludes = ({ relationships, included, depth = 1, maximumDepth = 3 }) => {
if (depth > maximumDepth) {
return []
}

const rawIncludes = Object.values(relationships).reduce((result, { data }) => {
// prevents failure with empty relationships
if (!data) {
return [...result]
}

if (Array.isArray(data)) {
return [...result, ...data.map((item) => findIncluded(item, included))]
} else {
return [...result, findIncluded(data, included)]
}
}, [])

// we need to run through it again as includes can also have relationships
// this is a recursive function
// we could do this in findIncluded but that is used elsewhere
const includes = rawIncludes.flatMap((includes) => {
if (includes.relationships) {
return [
includes,
...extractIncludes({ relationships: includes.relationships, included, depth: depth + 1 }),
]
} else {
return includes
}
})

// we need to remove includes with no id as this indicates it is part of the data
return includes.filter((item) => item.id)
}

/**
* Find the first n items in the data and return them
* Also extract the includes related to the found data
* @param {Object} data - the data object to be searched
* @param {Number} first - the number of items to return
* @param {Boolean} all - return all the data
* @param {Boolean} get - is this a get request? find returns data as an object and get returns an array
* @returns {Object} - the found data and the included resources
*/
const find = ({ data, all = false, first = 1, get = false } = {}) => {
const foundData = all ? data.data : data.data.slice(0, first)

// we need to extract the includes from the found data
const included = foundData.flatMap(({ relationships }) => {
return extractIncludes({ relationships, included: data.included })
})

// we need to remove the duplicates from included
// if we are only extracting a single record and find is used data needs to be an object
return {
data: foundData.length === 1 && !get ? foundData[0] : foundData,
included: [...new Set(included)],
}
}

export {
extractAttributes,
mapRelationships,
Expand All @@ -324,6 +396,8 @@ export {
populateBy,
splitDataByParent,
dataToObjectByPlateNumber,
extractIncludes,
find,
}

export default deserialize
50 changes: 26 additions & 24 deletions src/store/traction/ont/pools/actions.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { handleResponse } from '@/api/v1/ResponseHelper'
import { handleResponse as handleResponseV2 } from '@/api/v2/ResponseHelper'
import { handleResponse } from '@/api/v2/ResponseHelper'
import { groupIncludedByResource } from '@/api/JsonApi'
import { wellFor, wellToIndex } from './wellHelpers'
import { validate, valid, payload } from './pool'
Expand Down Expand Up @@ -152,15 +151,15 @@ export default {
return { success: true, errors: [] }
}

const request = rootState.api.v1.traction.ont.pools
const request = rootState.api.v2.traction.ont.pools
const promise = request.find({
id: id,
include:
'libraries.tag.tag_set,libraries.source_plate.wells.requests,libraries.source_tube.requests,libraries.request,tube',
})
const response = await handleResponse(promise)

const { success, data: { data, included = [] } = {}, errors = [] } = response
const { success, body: { data, included = [] } = {}, errors = [] } = response

if (success) {
const {
Expand Down Expand Up @@ -205,10 +204,11 @@ export default {
}
}

const request = rootState.api.v1.traction.ont.plates
const promise = request.get({ filter: filter, include: 'wells.requests' })
const request = rootState.api.v2.traction.ont.plates
const promise = request.get({ filter, include: 'wells.requests' })
const response = await handleResponse(promise)
let { success, data: { data, included = [] } = {}, errors = [] } = response

let { success, body: { data, included = [] } = {}, errors = [] } = response
const { wells, requests } = groupIncludedByResource(included)

// We will be return a successful empty list if no plates match the filter
Expand Down Expand Up @@ -245,10 +245,10 @@ export default {
}
}

const request = rootState.api.v1.traction.ont.tubes
const promise = request.get({ filter: filter, include: 'requests' })
const request = rootState.api.v2.traction.ont.tubes
const promise = request.get({ filter, include: 'requests' })
const response = await handleResponse(promise)
let { success, data: { data, included = [] } = {}, errors = [] } = response
let { success, body: { data, included = [] } = {}, errors = [] } = response
const { requests } = groupIncludedByResource(included)

// We will be return a successful empty list if no tubes match the filter
Expand Down Expand Up @@ -290,12 +290,12 @@ export default {
* @param rootState the vuex rootState object. Provides access to the current state
* @param commit the vuex commit object. Provides access to mutations
*/
fetchOntRequests: async ({ commit, rootState }, filter, page) => {
const request = rootState.api.v1.traction.ont.requests
fetchOntRequests: async ({ commit, rootState }, filter = {}, page = {}) => {
const request = rootState.api.v2.traction.ont.requests
const promise = request.get({ page, filter })
const response = await handleResponse(promise)

const { success, data: { data, meta = {} } = {}, errors = [] } = response
const { success, body: { data, meta = {} } = {}, errors = [] } = response

if (success) {
commit('setRequests', data)
Expand All @@ -308,6 +308,7 @@ export default {
* Validate a pool for the given barcode exists
* @param rootState the vuex state object. Provides access to current state
* @param barcode the barcode applied to the pool search
* There doesn't seem to be a test for this. Maybe e2e?
*/
validatePoolBarcode: async ({ rootState }, barcode) => {
// Here we want to make sure the barcode exists
Expand All @@ -318,10 +319,10 @@ export default {
}
}

const request = rootState.api.v1.traction.ont.pools
const request = rootState.api.v2.traction.ont.pools
const promise = request.get({ filter: { barcode } })
const response = await handleResponse(promise)
let { success, data: { data } = {} } = response
let { success, body: { data } = {} } = response

// We will be returned a successful empty list if no pools match the barcode
// Therefore we want to return success false, if we don't have any pools
Expand All @@ -336,16 +337,16 @@ export default {
* @param rootState the vuex rootState object. Provides access to the current state
* @param commit the vuex commit object. Provides access to mutations
*/
fetchOntPools: async ({ commit, rootState }, filter, page) => {
const request = rootState.api.v1.traction.ont.pools
fetchOntPools: async ({ commit, rootState }, filter = {}, page = {}) => {
const request = rootState.api.v2.traction.ont.pools
const promise = request.get({
page,
filter,
include: 'tube,libraries.tag,libraries.request',
})
const response = await handleResponse(promise)

const { success, data: { data, included = [], meta = {} } = {}, errors = [] } = response
const { success, body: { data, included = [], meta = {} } = {}, errors = [] } = response
const { tubes, libraries, tags, requests } = groupIncludedByResource(included)

if (success) {
Expand All @@ -367,15 +368,16 @@ export default {
*/
// For the component, the included relationships are not required
// However, the functionality does not appear to work without them
// no unit tests?
populateOntPools: async ({ commit, rootState }, filter) => {
const request = rootState.api.v1.traction.ont.pools
const request = rootState.api.v2.traction.ont.pools
const promise = request.get({
filter: filter,
include: 'tube,libraries.tag,libraries.request',
})
const response = await handleResponse(promise)

const { success, data: { data, included = [] } = {}, errors = [] } = response
const { success, body: { data, included = [] } = {}, errors = [] } = response
const { tubes, libraries, tags, requests } = groupIncludedByResource(included)

if (success) {
Expand All @@ -397,7 +399,7 @@ export default {
fetchOntTagSets: async ({ commit, rootState }) => {
const request = rootState.api.v2.traction.ont.tag_sets
const promise = request.get({ include: 'tags' })
const response = await handleResponseV2(promise)
const response = await handleResponse(promise)

const { success, body: { data, included = [] } = {}, errors = [] } = response

Expand All @@ -421,9 +423,9 @@ export default {
}) => {
validate({ libraries })
if (!valid({ libraries })) return { success: false, errors: 'The pool is invalid' }
const request = rootState.api.v1.traction.ont.pools
const request = rootState.api.v2.traction.ont.pools
const promise = request.create({ data: payload({ libraries, pool }), include: 'tube' })
const { success, data: { included = [] } = {}, errors } = await handleResponse(promise)
const { success, body: { included = [] } = {}, errors } = await handleResponse(promise)
const { tubes: [tube = {}] = [] } = groupIncludedByResource(included)
const { attributes: { barcode = '' } = {} } = tube
return { success, barcode, errors }
Expand All @@ -440,7 +442,7 @@ export default {
}) => {
validate({ libraries })
if (!valid({ libraries })) return { success: false, errors: 'The pool is invalid' }
const request = rootState.api.v1.traction.ont.pools
const request = rootState.api.v2.traction.ont.pools
const promise = request.update(payload({ libraries, pool }))
const { success, errors } = await handleResponse(promise)
return { success, errors }
Expand Down
1 change: 1 addition & 0 deletions src/store/traction/ont/pools/mutations.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ export default {
* Populated the result with the response
* @param {Object} state The VueXState object
* @param {Object} Response A response object
* I am wondering why we need to do this. Refactor needed.
**/
populatePoolingLibraries: (state, data) => {
const newLibraries = dataToObjectById({ data, includeRelationships: true })
Expand Down
20 changes: 0 additions & 20 deletions tests/data/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import Enzymes from './enzymes'
import Libraries from './libraries'
import Requests from './requests'
import RunNoLibrary from './runNoLibrary'
Expand Down Expand Up @@ -31,27 +30,17 @@ import PacbioSequencingPlate from './pacbioSequencingPlate'
import PacbioWell from './pacbioWell'
import PacbioWells from './pacbioWells'
import PacbioWellLibrary from './pacbioWellLibrary'
import TractionOntRequests from './tractionOntRequests'
import TractionTubeWithContainerMaterials from './tractionTubeWithContainerMaterials'
import TractionTubesWithPacbioPools from './tractionTubesWithPacbioPools'
import TractionPlates from './tractionPlates'
import AutoTagStore from './autoTagStore.json'
import OntAutoTagStore from './ontAutoTagStore.json'
import OntPlatesRequest from './ontPlatesRequest.json'
import OntTubesRequest from './ontTubesRequest.json'
import OntPlates from './ontPlates.json'
import OntPlateRequest from './ontPlateRequest.json'
import OntRequestsRequest from './ontRequestsRequest'
import OntTubeRequest from './ontTubeRequest.json'
import OntRun from './ontRun.json'
import tractionOntLibraries from './tractionOntLibraries'
import TractionOntPool from './tractionOntPool.json'
import TractionOntPools from './tractionOntPools.json'
import PacbioRunWithWellDefaults from './pacbioRunWithWellDefaults'
import StorePools from './StorePools.json'

export default {
Enzymes,
Libraries,
Requests,
RunNoLibrary,
Expand Down Expand Up @@ -84,22 +73,13 @@ export default {
PacbioWell,
PacbioWells,
PacbioWellLibrary,
tractionOntLibraries,
TractionOntRequests,
TractionOntPool,
TractionOntPools,
TractionTubeWithContainerMaterials,
TractionTubesWithPacbioPools,
TractionPlates,
AutoTagStore,
OntAutoTagStore,
OntPlatesRequest,
OntPlates,
OntPlateRequest,
OntRequestsRequest,
OntRun,
OntTubeRequest,
OntTubesRequest,
PacbioRunWithWellDefaults,
StorePools,
}
Loading

0 comments on commit 6410f26

Please sign in to comment.