diff --git a/docs/data/bioentities.md b/docs/data/bioentities.md new file mode 100644 index 0000000000000000000000000000000000000000..e17f46d1e1a4f32acfaa41a877fb8b4768514e9b --- /dev/null +++ b/docs/data/bioentities.md @@ -0,0 +1,116 @@ +### Data / BioEntities + +The methods contained within 'Data / BioEntities' are used to access/modify data on content/drugs/chemicals entities, as well as pin and surface markers. + +Below is a description of the methods, as well as the types they return. A description of the object types can be found in folder `/docs/types/`. + +**Available data access methods include:** + +- `getAllChemicals` + - gets list of searched chemicals + - returns array of `Chemical` +- `getAllContent` + - gets list of searched content + - returns array of `BioEntity` +- `getAllDrugs` + - gets list of searched drugs + - returns array of `Drug` +- `getAllMarkers` + - gets list of added markers + - returns array of `Marker` +- `getShownElements` + - gets list of all currently shown content/chemicals/drugs bioentities + markers + - returns object of + ``` + { + content: BioEntity[] + drugs: BioEntity[] + chemicals: BioEntity[] + markers: Marker[] + } + ``` + +**Available data modify methods include:** + +##### `clearAllElements` + +- accepts single argument + - array of `string` which includes one or more of: `'drugs'`, `'chemicals'`, `'content'`, `'marker'` +- clears **all** elements of provided type(s) +- returns nothing +- example: + ```ts + window.minerva.data.bioEntities.clearAllElements(['drugs', 'chemicals']); + ``` + +##### `addSingleMarker` + +- accepts single argument of object below + - **object:** + ``` + { + type: 'pin' OR 'surface' + id: string [optional] + color: string + opacity: number + x: number + y: number + width: number [optional] + height: number [optional] + number: number [optional] + modelId: number [optional] + } + ``` + - **id** - optional, if not provided uuidv4 is generated + - **color** - should be provided in hex format with hash (example: `#FF0000`) + - **opacity** - should be a float between `0` and `1` (example: `0.54`) + - **x** - x coord on the map + - **y** - y coord on the map + - **width** - width of surface [surface marker only] + - **height** - width of height [surface marker only] + - **number** - number presented on the pin [pin marker only] + - **modelId** - if marker should be visible only on single map, modelId should be provided +- adds one marker to markers list +- returns created `Marker` +- examples: + ```ts + window.minerva.data.bioEntities.addSingleMarker({ + type: 'surface', + color: '#106AD7', + opacity: 0.67, + x: 4438, + y: 1124, + width: 200, + height: 300, + modelId: 52, + }); + ``` + ```ts + window.minerva.data.bioEntities.addSingleMarker({ + type: 'pin', + color: '#106AD7', + opacity: 1, + x: 8723, + y: 4322, + number: 43, + }); + ``` + +##### `removeSingleMarker` + +- accepts single argument of `string` which represents marker `id` +- removes one marker from markers list +- returns nothing +- example: + ```ts + window.minerva.data.bioEntities.removeSingleMarker('f4c068d1-9695-4f1b-928c-d0cff92164b2'); + ``` + +##### `removeAllMarkers` + +- removes all markers from markers list +- returns nothing +- example: + ```ts + window.minerva.data.bioEntities.removeAllMarkers(); + ``` diff --git a/docs/types/BioEntity.md b/docs/types/BioEntity.md new file mode 100644 index 0000000000000000000000000000000000000000..faba904a6d2d79970ad823787f8cdfcaf8dcf40e --- /dev/null +++ b/docs/types/BioEntity.md @@ -0,0 +1,623 @@ +```json +{ + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "stringType": { + "type": "string" + }, + "name": { + "type": "string" + }, + "elementId": { + "type": "string" + }, + "model": { + "type": "number" + }, + "references": { + "type": "array", + "items": { + "type": "object", + "properties": { + "link": { + "anyOf": [ + { + "type": "string", + "format": "uri" + }, + { + "type": "null" + } + ] + }, + "article": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "authors": { + "type": "array", + "items": { + "type": "string" + } + }, + "journal": { + "type": "string" + }, + "year": { + "type": "number" + }, + "link": { + "type": "string" + }, + "pubmedId": { + "type": "string" + }, + "citationCount": { + "type": "number" + } + }, + "required": [ + "title", + "authors", + "journal", + "year", + "link", + "pubmedId", + "citationCount" + ], + "additionalProperties": false + }, + "type": { + "type": "string" + }, + "resource": { + "type": "string" + }, + "id": { + "type": "number" + }, + "annotatorClassName": { + "type": "string" + } + }, + "required": ["link", "type", "resource", "id", "annotatorClassName"], + "additionalProperties": false + } + }, + "z": { + "type": "number" + }, + "notes": { + "type": "string" + }, + "symbol": { + "type": ["string", "null"] + }, + "homodimer": { + "type": "number" + }, + "nameX": { + "type": "number" + }, + "nameY": { + "type": "number" + }, + "nameWidth": { + "type": "number" + }, + "nameHeight": { + "type": "number" + }, + "nameVerticalAlign": { + "type": "string" + }, + "nameHorizontalAlign": { + "type": "string" + }, + "width": { + "type": "number" + }, + "height": { + "type": "number" + }, + "visibilityLevel": { + "type": "string" + }, + "transparencyLevel": { + "type": "string" + }, + "synonyms": { + "type": "array", + "items": { + "type": "string" + } + }, + "formerSymbols": { + "type": "array", + "items": { + "type": "string" + } + }, + "fullName": { + "type": ["string", "null"] + }, + "compartmentName": { + "type": ["string", "null"] + }, + "abbreviation": { + "type": ["string", "null"] + }, + "formula": { + "type": ["string", "null"] + }, + "glyph": { + "anyOf": [ + { + "type": "object", + "properties": { + "file": { + "type": "number" + } + }, + "required": ["file"], + "additionalProperties": false + }, + { + "type": "null" + } + ] + }, + "activity": { + "type": "boolean" + }, + "structuralState": { + "anyOf": [ + { + "type": "object", + "properties": { + "value": { + "type": "string" + }, + "position": { + "type": "object", + "properties": { + "x": { + "type": "number" + }, + "y": { + "type": "number" + } + }, + "required": ["x", "y"], + "additionalProperties": false + }, + "z": { + "type": "number" + }, + "width": { + "type": "number" + }, + "height": { + "type": "number" + }, + "fontSize": { + "type": "number" + }, + "size": { + "type": "number" + }, + "center": { + "$ref": "#/properties/structuralState/anyOf/0/properties/position" + }, + "borderColor": { + "type": "object", + "properties": { + "alpha": { + "type": "number" + }, + "rgb": { + "type": "number" + } + }, + "required": ["alpha", "rgb"], + "additionalProperties": false + }, + "elementId": { + "type": "string" + } + }, + "required": [ + "value", + "position", + "z", + "width", + "height", + "fontSize", + "size", + "center", + "borderColor", + "elementId" + ], + "additionalProperties": false + }, + { + "type": "null" + } + ] + }, + "hypothetical": { + "type": ["boolean", "null"] + }, + "boundaryCondition": { + "type": "boolean" + }, + "constant": { + "type": "boolean" + }, + "initialAmount": { + "type": ["number", "null"] + }, + "initialConcentration": { + "type": ["number", "null"] + }, + "charge": { + "type": ["number", "null"] + }, + "substanceUnits": { + "type": ["string", "null"] + }, + "onlySubstanceUnits": { + "type": "boolean" + }, + "modificationResidues": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "idModificationResidue": { + "type": "string" + }, + "name": { + "type": "string" + }, + "position": { + "$ref": "#/properties/structuralState/anyOf/0/properties/position" + }, + "z": { + "type": "number" + }, + "borderColor": { + "$ref": "#/properties/structuralState/anyOf/0/properties/borderColor" + }, + "state": { + "anyOf": [ + { + "type": ["string", "number"] + }, + { + "type": "null" + } + ] + }, + "size": { + "type": "number" + }, + "elementId": { + "type": "string" + } + }, + "required": [ + "id", + "idModificationResidue", + "name", + "z", + "borderColor", + "size", + "elementId" + ], + "additionalProperties": false + } + }, + "complex": { + "type": ["number", "null"] + }, + "compartment": { + "type": ["number", "null"] + }, + "submodel": { + "anyOf": [ + { + "type": "object", + "properties": { + "mapId": { + "type": "number" + }, + "type": { + "type": "string" + } + }, + "required": ["mapId", "type"], + "additionalProperties": false + }, + { + "type": "null" + } + ] + }, + "x": { + "type": "number" + }, + "y": { + "type": "number" + }, + "lineWidth": { + "type": "number" + }, + "fontColor": { + "$ref": "#/properties/structuralState/anyOf/0/properties/borderColor" + }, + "fontSize": { + "type": "number" + }, + "fillColor": { + "$ref": "#/properties/structuralState/anyOf/0/properties/borderColor" + }, + "borderColor": { + "$ref": "#/properties/structuralState/anyOf/0/properties/borderColor" + }, + "smiles": { + "anyOf": [ + { + "anyOf": [ + { + "not": {} + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ] + }, + "inChI": { + "type": ["string", "null"] + }, + "inChIKey": { + "type": ["string", "null"] + }, + "thickness": { + "type": "number" + }, + "outerWidth": { + "type": "number" + }, + "innerWidth": { + "type": "number" + }, + "idReaction": { + "type": "string" + }, + "reversible": { + "type": "boolean" + }, + "mechanicalConfidenceScore": { + "type": "boolean" + }, + "lowerBound": { + "type": "boolean" + }, + "upperBound": { + "type": "boolean" + }, + "subsystem": { + "type": "string" + }, + "geneProteinReaction": { + "type": "string" + }, + "kinetics": { + "type": "null" + }, + "products": { + "type": "array", + "items": { + "type": "object", + "properties": { + "aliasId": { + "type": "number" + }, + "stoichiometry": { + "type": ["number", "null"] + }, + "type": { + "type": "string" + } + }, + "required": ["aliasId", "stoichiometry"], + "additionalProperties": false + } + }, + "reactants": { + "type": "array", + "items": { + "$ref": "#/properties/products/items" + } + }, + "modifiers": { + "type": "array", + "items": { + "$ref": "#/properties/products/items" + } + }, + "processCoordinates": { + "type": "null" + }, + "line": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "width": { + "type": "number" + }, + "color": { + "$ref": "#/properties/structuralState/anyOf/0/properties/borderColor" + }, + "z": { + "type": "number" + }, + "segments": { + "type": "array", + "items": { + "type": "object", + "properties": { + "x1": { + "type": "number" + }, + "y1": { + "type": "number" + }, + "x2": { + "type": "number" + }, + "y2": { + "type": "number" + } + }, + "required": ["x1", "y1", "x2", "y2"], + "additionalProperties": false + } + }, + "startArrow": { + "type": "object", + "properties": { + "arrowType": { + "type": "string" + }, + "angle": { + "type": "number" + }, + "lineType": { + "type": "string" + }, + "length": { + "type": "number" + } + }, + "required": ["arrowType", "angle", "lineType", "length"], + "additionalProperties": false + }, + "endArrow": { + "$ref": "#/properties/line/properties/startArrow" + }, + "lineType": { + "type": "string" + } + }, + "required": ["id", "width", "color", "z", "segments", "startArrow", "endArrow", "lineType"], + "additionalProperties": false + }, + "operators": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "line": { + "$ref": "#/properties/line" + }, + "inputs": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + } + }, + "required": ["id"], + "additionalProperties": false + } + }, + "outputs": { + "not": {} + }, + "operatorText": { + "type": "string" + }, + "reactantOperator": { + "type": "boolean" + }, + "productOperator": { + "type": "boolean" + }, + "modifierOperator": { + "type": "boolean" + } + }, + "required": [ + "id", + "line", + "inputs", + "operatorText", + "reactantOperator", + "productOperator", + "modifierOperator" + ], + "additionalProperties": false + } + } + }, + "required": [ + "id", + "stringType", + "name", + "elementId", + "model", + "references", + "z", + "notes", + "symbol", + "nameX", + "nameY", + "nameWidth", + "nameHeight", + "nameVerticalAlign", + "nameHorizontalAlign", + "width", + "height", + "visibilityLevel", + "transparencyLevel", + "synonyms", + "formerSymbols", + "fullName", + "abbreviation", + "formula", + "glyph", + "compartment", + "submodel", + "x", + "y", + "fontColor", + "fontSize", + "fillColor", + "borderColor" + ], + "additionalProperties": false, + "$schema": "http://json-schema.org/draft-07/schema#" +} +``` diff --git a/docs/types/Chemical.md b/docs/types/Chemical.md new file mode 100644 index 0000000000000000000000000000000000000000..61add5938186e8ca9789714a847e79f08c99e6b0 --- /dev/null +++ b/docs/types/Chemical.md @@ -0,0 +1,744 @@ +```json +{ + "type": "object", + "properties": { + "id": { + "type": "object", + "properties": { + "annotatorClassName": { + "type": "string" + }, + "id": { + "type": "number" + }, + "link": { + "type": "string" + }, + "resource": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "required": ["annotatorClassName", "id", "link", "resource", "type"], + "additionalProperties": false + }, + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "directEvidence": { + "type": ["string", "null"] + }, + "directEvidenceReferences": { + "type": "array", + "items": { + "type": "object", + "properties": { + "link": { + "anyOf": [ + { + "type": "string", + "format": "uri" + }, + { + "type": "null" + } + ] + }, + "article": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "authors": { + "type": "array", + "items": { + "type": "string" + } + }, + "journal": { + "type": "string" + }, + "year": { + "type": "number" + }, + "link": { + "type": "string" + }, + "pubmedId": { + "type": "string" + }, + "citationCount": { + "type": "number" + } + }, + "required": [ + "title", + "authors", + "journal", + "year", + "link", + "pubmedId", + "citationCount" + ], + "additionalProperties": false + }, + "type": { + "type": "string" + }, + "resource": { + "type": "string" + }, + "id": { + "type": "number" + }, + "annotatorClassName": { + "type": "string" + } + }, + "required": ["link", "type", "resource", "id", "annotatorClassName"], + "additionalProperties": false + } + }, + "synonyms": { + "type": "array", + "items": { + "type": "string" + } + }, + "references": { + "type": "array", + "items": { + "$ref": "#/properties/directEvidenceReferences/items" + } + }, + "targets": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "references": { + "type": "array", + "items": { + "$ref": "#/properties/directEvidenceReferences/items" + } + }, + "targetElements": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "stringType": { + "type": "string" + }, + "name": { + "type": "string" + }, + "elementId": { + "type": "string" + }, + "model": { + "type": "number" + }, + "references": { + "type": "array", + "items": { + "$ref": "#/properties/directEvidenceReferences/items" + } + }, + "z": { + "type": "number" + }, + "notes": { + "type": "string" + }, + "symbol": { + "type": ["string", "null"] + }, + "homodimer": { + "type": "number" + }, + "nameX": { + "type": "number" + }, + "nameY": { + "type": "number" + }, + "nameWidth": { + "type": "number" + }, + "nameHeight": { + "type": "number" + }, + "nameVerticalAlign": { + "type": "string" + }, + "nameHorizontalAlign": { + "type": "string" + }, + "width": { + "type": "number" + }, + "height": { + "type": "number" + }, + "visibilityLevel": { + "type": "string" + }, + "transparencyLevel": { + "type": "string" + }, + "synonyms": { + "type": "array", + "items": { + "type": "string" + } + }, + "formerSymbols": { + "type": "array", + "items": { + "type": "string" + } + }, + "fullName": { + "type": ["string", "null"] + }, + "compartmentName": { + "type": ["string", "null"] + }, + "abbreviation": { + "type": ["string", "null"] + }, + "formula": { + "type": ["string", "null"] + }, + "glyph": { + "anyOf": [ + { + "type": "object", + "properties": { + "file": { + "type": "number" + } + }, + "required": ["file"], + "additionalProperties": false + }, + { + "type": "null" + } + ] + }, + "activity": { + "type": "boolean" + }, + "structuralState": { + "anyOf": [ + { + "type": "object", + "properties": { + "value": { + "type": "string" + }, + "position": { + "type": "object", + "properties": { + "x": { + "type": "number" + }, + "y": { + "type": "number" + } + }, + "required": ["x", "y"], + "additionalProperties": false + }, + "z": { + "type": "number" + }, + "width": { + "type": "number" + }, + "height": { + "type": "number" + }, + "fontSize": { + "type": "number" + }, + "size": { + "type": "number" + }, + "center": { + "$ref": "#/properties/targets/items/properties/targetElements/items/properties/structuralState/anyOf/0/properties/position" + }, + "borderColor": { + "type": "object", + "properties": { + "alpha": { + "type": "number" + }, + "rgb": { + "type": "number" + } + }, + "required": ["alpha", "rgb"], + "additionalProperties": false + }, + "elementId": { + "type": "string" + } + }, + "required": [ + "value", + "position", + "z", + "width", + "height", + "fontSize", + "size", + "center", + "borderColor", + "elementId" + ], + "additionalProperties": false + }, + { + "type": "null" + } + ] + }, + "hypothetical": { + "type": ["boolean", "null"] + }, + "boundaryCondition": { + "type": "boolean" + }, + "constant": { + "type": "boolean" + }, + "initialAmount": { + "type": ["number", "null"] + }, + "initialConcentration": { + "type": ["number", "null"] + }, + "charge": { + "type": ["number", "null"] + }, + "substanceUnits": { + "type": ["string", "null"] + }, + "onlySubstanceUnits": { + "type": "boolean" + }, + "modificationResidues": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "idModificationResidue": { + "type": "string" + }, + "name": { + "type": "string" + }, + "position": { + "$ref": "#/properties/targets/items/properties/targetElements/items/properties/structuralState/anyOf/0/properties/position" + }, + "z": { + "type": "number" + }, + "borderColor": { + "$ref": "#/properties/targets/items/properties/targetElements/items/properties/structuralState/anyOf/0/properties/borderColor" + }, + "state": { + "anyOf": [ + { + "type": ["string", "number"] + }, + { + "type": "null" + } + ] + }, + "size": { + "type": "number" + }, + "elementId": { + "type": "string" + } + }, + "required": [ + "id", + "idModificationResidue", + "name", + "z", + "borderColor", + "size", + "elementId" + ], + "additionalProperties": false + } + }, + "complex": { + "type": ["number", "null"] + }, + "compartment": { + "type": ["number", "null"] + }, + "submodel": { + "anyOf": [ + { + "type": "object", + "properties": { + "mapId": { + "type": "number" + }, + "type": { + "type": "string" + } + }, + "required": ["mapId", "type"], + "additionalProperties": false + }, + { + "type": "null" + } + ] + }, + "x": { + "type": "number" + }, + "y": { + "type": "number" + }, + "lineWidth": { + "type": "number" + }, + "fontColor": { + "$ref": "#/properties/targets/items/properties/targetElements/items/properties/structuralState/anyOf/0/properties/borderColor" + }, + "fontSize": { + "type": "number" + }, + "fillColor": { + "$ref": "#/properties/targets/items/properties/targetElements/items/properties/structuralState/anyOf/0/properties/borderColor" + }, + "borderColor": { + "$ref": "#/properties/targets/items/properties/targetElements/items/properties/structuralState/anyOf/0/properties/borderColor" + }, + "smiles": { + "anyOf": [ + { + "anyOf": [ + { + "not": {} + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ] + }, + "inChI": { + "type": ["string", "null"] + }, + "inChIKey": { + "type": ["string", "null"] + }, + "thickness": { + "type": "number" + }, + "outerWidth": { + "type": "number" + }, + "innerWidth": { + "type": "number" + }, + "idReaction": { + "type": "string" + }, + "reversible": { + "type": "boolean" + }, + "mechanicalConfidenceScore": { + "type": "boolean" + }, + "lowerBound": { + "type": "boolean" + }, + "upperBound": { + "type": "boolean" + }, + "subsystem": { + "type": "string" + }, + "geneProteinReaction": { + "type": "string" + }, + "kinetics": { + "type": "null" + }, + "products": { + "type": "array", + "items": { + "type": "object", + "properties": { + "aliasId": { + "type": "number" + }, + "stoichiometry": { + "type": ["number", "null"] + }, + "type": { + "type": "string" + } + }, + "required": ["aliasId", "stoichiometry"], + "additionalProperties": false + } + }, + "reactants": { + "type": "array", + "items": { + "$ref": "#/properties/targets/items/properties/targetElements/items/properties/products/items" + } + }, + "modifiers": { + "type": "array", + "items": { + "$ref": "#/properties/targets/items/properties/targetElements/items/properties/products/items" + } + }, + "processCoordinates": { + "type": "null" + }, + "line": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "width": { + "type": "number" + }, + "color": { + "$ref": "#/properties/targets/items/properties/targetElements/items/properties/structuralState/anyOf/0/properties/borderColor" + }, + "z": { + "type": "number" + }, + "segments": { + "type": "array", + "items": { + "type": "object", + "properties": { + "x1": { + "type": "number" + }, + "y1": { + "type": "number" + }, + "x2": { + "type": "number" + }, + "y2": { + "type": "number" + } + }, + "required": ["x1", "y1", "x2", "y2"], + "additionalProperties": false + } + }, + "startArrow": { + "type": "object", + "properties": { + "arrowType": { + "type": "string" + }, + "angle": { + "type": "number" + }, + "lineType": { + "type": "string" + }, + "length": { + "type": "number" + } + }, + "required": ["arrowType", "angle", "lineType", "length"], + "additionalProperties": false + }, + "endArrow": { + "$ref": "#/properties/targets/items/properties/targetElements/items/properties/line/properties/startArrow" + }, + "lineType": { + "type": "string" + } + }, + "required": [ + "id", + "width", + "color", + "z", + "segments", + "startArrow", + "endArrow", + "lineType" + ], + "additionalProperties": false + }, + "operators": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "line": { + "$ref": "#/properties/targets/items/properties/targetElements/items/properties/line" + }, + "inputs": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + } + }, + "required": ["id"], + "additionalProperties": false + } + }, + "outputs": { + "not": {} + }, + "operatorText": { + "type": "string" + }, + "reactantOperator": { + "type": "boolean" + }, + "productOperator": { + "type": "boolean" + }, + "modifierOperator": { + "type": "boolean" + } + }, + "required": [ + "id", + "line", + "inputs", + "operatorText", + "reactantOperator", + "productOperator", + "modifierOperator" + ], + "additionalProperties": false + } + } + }, + "required": [ + "id", + "stringType", + "name", + "elementId", + "model", + "references", + "z", + "notes", + "symbol", + "nameX", + "nameY", + "nameWidth", + "nameHeight", + "nameVerticalAlign", + "nameHorizontalAlign", + "width", + "height", + "visibilityLevel", + "transparencyLevel", + "synonyms", + "formerSymbols", + "fullName", + "abbreviation", + "formula", + "glyph", + "compartment", + "submodel", + "x", + "y", + "fontColor", + "fontSize", + "fillColor", + "borderColor" + ], + "additionalProperties": false + } + }, + "targetParticipants": { + "type": "array", + "items": { + "type": "object", + "properties": { + "link": { + "type": "string" + }, + "type": { + "type": "string" + }, + "resource": { + "type": "string" + }, + "id": { + "type": "number" + }, + "annotatorClassName": { + "type": "string" + } + }, + "required": ["link", "type", "resource", "id", "annotatorClassName"], + "additionalProperties": false + } + } + }, + "required": ["name", "references", "targetElements", "targetParticipants"], + "additionalProperties": false + } + } + }, + "required": [ + "id", + "name", + "description", + "directEvidence", + "directEvidenceReferences", + "synonyms", + "references", + "targets" + ], + "additionalProperties": false, + "$schema": "http://json-schema.org/draft-07/schema#" +} +``` diff --git a/docs/types/Drug.md b/docs/types/Drug.md new file mode 100644 index 0000000000000000000000000000000000000000..f7b21990191335c10d63a42f6a8a9fd0e75e1a81 --- /dev/null +++ b/docs/types/Drug.md @@ -0,0 +1,725 @@ +```json +{ + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "description": { + "type": ["string", "null"] + }, + "synonyms": { + "type": "array", + "items": { + "type": "string" + } + }, + "brandNames": { + "type": "array", + "items": { + "type": "string" + } + }, + "bloodBrainBarrier": { + "type": "string" + }, + "references": { + "type": "array", + "items": { + "type": "object", + "properties": { + "link": { + "anyOf": [ + { + "type": "string", + "format": "uri" + }, + { + "type": "null" + } + ] + }, + "article": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "authors": { + "type": "array", + "items": { + "type": "string" + } + }, + "journal": { + "type": "string" + }, + "year": { + "type": "number" + }, + "link": { + "type": "string" + }, + "pubmedId": { + "type": "string" + }, + "citationCount": { + "type": "number" + } + }, + "required": [ + "title", + "authors", + "journal", + "year", + "link", + "pubmedId", + "citationCount" + ], + "additionalProperties": false + }, + "type": { + "type": "string" + }, + "resource": { + "type": "string" + }, + "id": { + "type": "number" + }, + "annotatorClassName": { + "type": "string" + } + }, + "required": ["link", "type", "resource", "id", "annotatorClassName"], + "additionalProperties": false + } + }, + "targets": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "references": { + "type": "array", + "items": { + "$ref": "#/properties/references/items" + } + }, + "targetElements": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "stringType": { + "type": "string" + }, + "name": { + "type": "string" + }, + "elementId": { + "type": "string" + }, + "model": { + "type": "number" + }, + "references": { + "type": "array", + "items": { + "$ref": "#/properties/references/items" + } + }, + "z": { + "type": "number" + }, + "notes": { + "type": "string" + }, + "symbol": { + "type": ["string", "null"] + }, + "homodimer": { + "type": "number" + }, + "nameX": { + "type": "number" + }, + "nameY": { + "type": "number" + }, + "nameWidth": { + "type": "number" + }, + "nameHeight": { + "type": "number" + }, + "nameVerticalAlign": { + "type": "string" + }, + "nameHorizontalAlign": { + "type": "string" + }, + "width": { + "type": "number" + }, + "height": { + "type": "number" + }, + "visibilityLevel": { + "type": "string" + }, + "transparencyLevel": { + "type": "string" + }, + "synonyms": { + "type": "array", + "items": { + "type": "string" + } + }, + "formerSymbols": { + "type": "array", + "items": { + "type": "string" + } + }, + "fullName": { + "type": ["string", "null"] + }, + "compartmentName": { + "type": ["string", "null"] + }, + "abbreviation": { + "type": ["string", "null"] + }, + "formula": { + "type": ["string", "null"] + }, + "glyph": { + "anyOf": [ + { + "type": "object", + "properties": { + "file": { + "type": "number" + } + }, + "required": ["file"], + "additionalProperties": false + }, + { + "type": "null" + } + ] + }, + "activity": { + "type": "boolean" + }, + "structuralState": { + "anyOf": [ + { + "type": "object", + "properties": { + "value": { + "type": "string" + }, + "position": { + "type": "object", + "properties": { + "x": { + "type": "number" + }, + "y": { + "type": "number" + } + }, + "required": ["x", "y"], + "additionalProperties": false + }, + "z": { + "type": "number" + }, + "width": { + "type": "number" + }, + "height": { + "type": "number" + }, + "fontSize": { + "type": "number" + }, + "size": { + "type": "number" + }, + "center": { + "$ref": "#/properties/targets/items/properties/targetElements/items/properties/structuralState/anyOf/0/properties/position" + }, + "borderColor": { + "type": "object", + "properties": { + "alpha": { + "type": "number" + }, + "rgb": { + "type": "number" + } + }, + "required": ["alpha", "rgb"], + "additionalProperties": false + }, + "elementId": { + "type": "string" + } + }, + "required": [ + "value", + "position", + "z", + "width", + "height", + "fontSize", + "size", + "center", + "borderColor", + "elementId" + ], + "additionalProperties": false + }, + { + "type": "null" + } + ] + }, + "hypothetical": { + "type": ["boolean", "null"] + }, + "boundaryCondition": { + "type": "boolean" + }, + "constant": { + "type": "boolean" + }, + "initialAmount": { + "type": ["number", "null"] + }, + "initialConcentration": { + "type": ["number", "null"] + }, + "charge": { + "type": ["number", "null"] + }, + "substanceUnits": { + "type": ["string", "null"] + }, + "onlySubstanceUnits": { + "type": "boolean" + }, + "modificationResidues": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "idModificationResidue": { + "type": "string" + }, + "name": { + "type": "string" + }, + "position": { + "$ref": "#/properties/targets/items/properties/targetElements/items/properties/structuralState/anyOf/0/properties/position" + }, + "z": { + "type": "number" + }, + "borderColor": { + "$ref": "#/properties/targets/items/properties/targetElements/items/properties/structuralState/anyOf/0/properties/borderColor" + }, + "state": { + "anyOf": [ + { + "type": ["string", "number"] + }, + { + "type": "null" + } + ] + }, + "size": { + "type": "number" + }, + "elementId": { + "type": "string" + } + }, + "required": [ + "id", + "idModificationResidue", + "name", + "z", + "borderColor", + "size", + "elementId" + ], + "additionalProperties": false + } + }, + "complex": { + "type": ["number", "null"] + }, + "compartment": { + "type": ["number", "null"] + }, + "submodel": { + "anyOf": [ + { + "type": "object", + "properties": { + "mapId": { + "type": "number" + }, + "type": { + "type": "string" + } + }, + "required": ["mapId", "type"], + "additionalProperties": false + }, + { + "type": "null" + } + ] + }, + "x": { + "type": "number" + }, + "y": { + "type": "number" + }, + "lineWidth": { + "type": "number" + }, + "fontColor": { + "$ref": "#/properties/targets/items/properties/targetElements/items/properties/structuralState/anyOf/0/properties/borderColor" + }, + "fontSize": { + "type": "number" + }, + "fillColor": { + "$ref": "#/properties/targets/items/properties/targetElements/items/properties/structuralState/anyOf/0/properties/borderColor" + }, + "borderColor": { + "$ref": "#/properties/targets/items/properties/targetElements/items/properties/structuralState/anyOf/0/properties/borderColor" + }, + "smiles": { + "anyOf": [ + { + "anyOf": [ + { + "not": {} + }, + { + "type": "string" + } + ] + }, + { + "type": "null" + } + ] + }, + "inChI": { + "type": ["string", "null"] + }, + "inChIKey": { + "type": ["string", "null"] + }, + "thickness": { + "type": "number" + }, + "outerWidth": { + "type": "number" + }, + "innerWidth": { + "type": "number" + }, + "idReaction": { + "type": "string" + }, + "reversible": { + "type": "boolean" + }, + "mechanicalConfidenceScore": { + "type": "boolean" + }, + "lowerBound": { + "type": "boolean" + }, + "upperBound": { + "type": "boolean" + }, + "subsystem": { + "type": "string" + }, + "geneProteinReaction": { + "type": "string" + }, + "kinetics": { + "type": "null" + }, + "products": { + "type": "array", + "items": { + "type": "object", + "properties": { + "aliasId": { + "type": "number" + }, + "stoichiometry": { + "type": ["number", "null"] + }, + "type": { + "type": "string" + } + }, + "required": ["aliasId", "stoichiometry"], + "additionalProperties": false + } + }, + "reactants": { + "type": "array", + "items": { + "$ref": "#/properties/targets/items/properties/targetElements/items/properties/products/items" + } + }, + "modifiers": { + "type": "array", + "items": { + "$ref": "#/properties/targets/items/properties/targetElements/items/properties/products/items" + } + }, + "processCoordinates": { + "type": "null" + }, + "line": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "width": { + "type": "number" + }, + "color": { + "$ref": "#/properties/targets/items/properties/targetElements/items/properties/structuralState/anyOf/0/properties/borderColor" + }, + "z": { + "type": "number" + }, + "segments": { + "type": "array", + "items": { + "type": "object", + "properties": { + "x1": { + "type": "number" + }, + "y1": { + "type": "number" + }, + "x2": { + "type": "number" + }, + "y2": { + "type": "number" + } + }, + "required": ["x1", "y1", "x2", "y2"], + "additionalProperties": false + } + }, + "startArrow": { + "type": "object", + "properties": { + "arrowType": { + "type": "string" + }, + "angle": { + "type": "number" + }, + "lineType": { + "type": "string" + }, + "length": { + "type": "number" + } + }, + "required": ["arrowType", "angle", "lineType", "length"], + "additionalProperties": false + }, + "endArrow": { + "$ref": "#/properties/targets/items/properties/targetElements/items/properties/line/properties/startArrow" + }, + "lineType": { + "type": "string" + } + }, + "required": [ + "id", + "width", + "color", + "z", + "segments", + "startArrow", + "endArrow", + "lineType" + ], + "additionalProperties": false + }, + "operators": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + }, + "line": { + "$ref": "#/properties/targets/items/properties/targetElements/items/properties/line" + }, + "inputs": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "number" + } + }, + "required": ["id"], + "additionalProperties": false + } + }, + "outputs": { + "not": {} + }, + "operatorText": { + "type": "string" + }, + "reactantOperator": { + "type": "boolean" + }, + "productOperator": { + "type": "boolean" + }, + "modifierOperator": { + "type": "boolean" + } + }, + "required": [ + "id", + "line", + "inputs", + "operatorText", + "reactantOperator", + "productOperator", + "modifierOperator" + ], + "additionalProperties": false + } + } + }, + "required": [ + "id", + "stringType", + "name", + "elementId", + "model", + "references", + "z", + "notes", + "symbol", + "nameX", + "nameY", + "nameWidth", + "nameHeight", + "nameVerticalAlign", + "nameHorizontalAlign", + "width", + "height", + "visibilityLevel", + "transparencyLevel", + "synonyms", + "formerSymbols", + "fullName", + "abbreviation", + "formula", + "glyph", + "compartment", + "submodel", + "x", + "y", + "fontColor", + "fontSize", + "fillColor", + "borderColor" + ], + "additionalProperties": false + } + }, + "targetParticipants": { + "type": "array", + "items": { + "type": "object", + "properties": { + "link": { + "type": "string" + }, + "type": { + "type": "string" + }, + "resource": { + "type": "string" + }, + "id": { + "type": "number" + }, + "annotatorClassName": { + "type": "string" + } + }, + "required": ["link", "type", "resource", "id", "annotatorClassName"], + "additionalProperties": false + } + } + }, + "required": ["name", "references", "targetElements", "targetParticipants"], + "additionalProperties": false + } + } + }, + "required": [ + "id", + "name", + "description", + "synonyms", + "brandNames", + "bloodBrainBarrier", + "references", + "targets" + ], + "additionalProperties": false, + "$schema": "http://json-schema.org/draft-07/schema#" +} +``` diff --git a/docs/types/Marker.md b/docs/types/Marker.md new file mode 100644 index 0000000000000000000000000000000000000000..c9aa40ede58c0f60b847d451a6e2bc6bc5213bb7 --- /dev/null +++ b/docs/types/Marker.md @@ -0,0 +1,12 @@ +```ts +interface MarkerBase { + type: 'pin' | 'surface'; + id: string; + color: string; + opacity: number; + x: number; + y: number; + number?: number; + modelId?: number; +} +``` diff --git a/index.d.ts b/index.d.ts index 248f6f8ecb2d8aa13e21e2859fbfafacc263eba2..dcca7b123d13f373326a60c0142682cc3a4739b2 100644 --- a/index.d.ts +++ b/index.d.ts @@ -22,6 +22,9 @@ declare global { plugins: { registerPlugin: RegisterPlugin; }; + data: { + bioEntities: BioEntitiesMethods; + }; }; } } diff --git a/package-lock.json b/package-lock.json index f03034da82f849c388f0ea38401273ee54e4d1ca..016ad6996bbef60abdeef8fe404277e991e7dca9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -38,7 +38,9 @@ "tailwindcss": "3.3.3", "ts-deepmerge": "^6.2.0", "use-debounce": "^9.0.4", - "zod": "^3.22.2" + "uuid": "^9.0.1", + "zod": "^3.22.2", + "zod-to-json-schema": "^3.22.4" }, "devDependencies": { "@commitlint/cli": "^17.7.1", @@ -50,6 +52,7 @@ "@types/jest": "^29.5.5", "@types/react-redux": "^7.1.26", "@types/redux-mock-store": "^1.0.6", + "@types/uuid": "^9.0.8", "@typescript-eslint/eslint-plugin": "^6.7.0", "@typescript-eslint/parser": "^6.7.0", "axios-mock-adapter": "^1.22.0", @@ -1180,6 +1183,15 @@ "node": ">= 0.12" } }, + "node_modules/@cypress/request/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/@cypress/xvfb": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/@cypress/xvfb/-/xvfb-1.2.4.tgz", @@ -2495,6 +2507,12 @@ "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz", "integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA==" }, + "node_modules/@types/uuid": { + "version": "9.0.8", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz", + "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==", + "dev": true + }, "node_modules/@types/yargs": { "version": "17.0.32", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", @@ -8532,6 +8550,15 @@ "node": ">=8" } }, + "node_modules/jest-junit/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/jest-leak-detector": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", @@ -13457,10 +13484,13 @@ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, "node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true, + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], "bin": { "uuid": "dist/bin/uuid" } @@ -14004,6 +14034,14 @@ "zod": ">=3.0.0" } }, + "node_modules/zod-to-json-schema": { + "version": "3.22.4", + "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.22.4.tgz", + "integrity": "sha512-2Ed5dJ+n/O3cU383xSY28cuVi0BCQhF8nYqWU5paEpl7fVdqdAmiLdqLyfblbNdfOFwFfi/mqU4O1pwc60iBhQ==", + "peerDependencies": { + "zod": "^3.22.4" + } + }, "node_modules/zstddec": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/zstddec/-/zstddec-0.1.0.tgz", @@ -14850,6 +14888,12 @@ "combined-stream": "^1.0.6", "mime-types": "^2.1.12" } + }, + "uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true } } }, @@ -15861,6 +15905,12 @@ "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz", "integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA==" }, + "@types/uuid": { + "version": "9.0.8", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz", + "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==", + "dev": true + }, "@types/yargs": { "version": "17.0.32", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", @@ -20183,6 +20233,12 @@ "requires": { "ansi-regex": "^5.0.1" } + }, + "uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true } } }, @@ -23678,10 +23734,9 @@ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==" }, "v8-compile-cache-lib": { "version": "3.0.1", @@ -24095,6 +24150,12 @@ "randexp": "^0.5.3" } }, + "zod-to-json-schema": { + "version": "3.22.4", + "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.22.4.tgz", + "integrity": "sha512-2Ed5dJ+n/O3cU383xSY28cuVi0BCQhF8nYqWU5paEpl7fVdqdAmiLdqLyfblbNdfOFwFfi/mqU4O1pwc60iBhQ==", + "requires": {} + }, "zstddec": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/zstddec/-/zstddec-0.1.0.tgz", diff --git a/package.json b/package.json index 730be9f5d6988dabee2e69c54847d7ce860defb5..f3a8ec09f2e124b622df2947627ea0a7576d99a3 100644 --- a/package.json +++ b/package.json @@ -52,18 +52,21 @@ "tailwindcss": "3.3.3", "ts-deepmerge": "^6.2.0", "use-debounce": "^9.0.4", - "zod": "^3.22.2" + "uuid": "^9.0.1", + "zod": "^3.22.2", + "zod-to-json-schema": "^3.22.4" }, "devDependencies": { "@commitlint/cli": "^17.7.1", "@commitlint/config-conventional": "^17.7.0", "@testing-library/jest-dom": "^6.1.3", "@testing-library/react": "^14.0.0", - "@types/crypto-js": "^4.2.2", "@testing-library/user-event": "^14.5.2", + "@types/crypto-js": "^4.2.2", "@types/jest": "^29.5.5", "@types/react-redux": "^7.1.26", "@types/redux-mock-store": "^1.0.6", + "@types/uuid": "^9.0.8", "@typescript-eslint/eslint-plugin": "^6.7.0", "@typescript-eslint/parser": "^6.7.0", "axios-mock-adapter": "^1.22.0", diff --git a/src/components/Map/Drawer/BioEntityDrawer/OverlayData/OverlayData.types.ts b/src/components/Map/Drawer/BioEntityDrawer/OverlayData/OverlayData.types.ts index 4f78ef6121607c3a6fd06c7dc17303f8652075d0..3d43db8f8fdb810df0e8288f59d218ac669e2d73 100644 --- a/src/components/Map/Drawer/BioEntityDrawer/OverlayData/OverlayData.types.ts +++ b/src/components/Map/Drawer/BioEntityDrawer/OverlayData/OverlayData.types.ts @@ -1,7 +1,7 @@ import { GeneVariant } from '@/types/models'; export interface OverlayDataAxis { - id: number; + id: number | string; title: string; value?: number; color: string; diff --git a/src/components/Map/Drawer/SearchDrawerWrapper/GroupedSearchResults/BioEntitiesAccordion/BioEntitiesAccordion.component.test.tsx b/src/components/Map/Drawer/SearchDrawerWrapper/GroupedSearchResults/BioEntitiesAccordion/BioEntitiesAccordion.component.test.tsx index d65d291524e7124c080827e2eff819f2018609eb..33d0635014f9d9140edfadac8c7d75c5b63e8784 100644 --- a/src/components/Map/Drawer/SearchDrawerWrapper/GroupedSearchResults/BioEntitiesAccordion/BioEntitiesAccordion.component.test.tsx +++ b/src/components/Map/Drawer/SearchDrawerWrapper/GroupedSearchResults/BioEntitiesAccordion/BioEntitiesAccordion.component.test.tsx @@ -74,7 +74,7 @@ describe('BioEntitiesAccordion - component', () => { expect(screen.getByText('Content (10)')).toBeInTheDocument(); expect(screen.getByText('Core PD map (5)')).toBeInTheDocument(); - expect(screen.getByText('Histamine signaling (2)')).toBeInTheDocument(); - expect(screen.getByText('PRKN substrates (3)')).toBeInTheDocument(); + expect(screen.getByText('Histamine signaling (3)')).toBeInTheDocument(); + expect(screen.getByText('PRKN substrates (2)')).toBeInTheDocument(); }); }); diff --git a/src/components/Map/Drawer/SearchDrawerWrapper/ResultsList/PinsList/PinsList.types.tsx b/src/components/Map/Drawer/SearchDrawerWrapper/ResultsList/PinsList/PinsList.types.tsx index 74d6fe343e329624a3cd16fe827787a090acd756..e0bdafa37a72ba495598c4aa8c333cf005c958cd 100644 --- a/src/components/Map/Drawer/SearchDrawerWrapper/ResultsList/PinsList/PinsList.types.tsx +++ b/src/components/Map/Drawer/SearchDrawerWrapper/ResultsList/PinsList/PinsList.types.tsx @@ -10,7 +10,7 @@ export type PinItem = { export type PinTypeWithNone = PinType | 'none'; export type AvailableSubmaps = { - id: number; + id: number | string; modelId: number; name: string; }; diff --git a/src/components/Map/MapViewer/utils/config/getCanvasIcon.ts b/src/components/Map/MapViewer/utils/config/getCanvasIcon.ts index c377b0efa124b12dc7ad8633e11d3f80cb5d0df0..7d3e69257ce42338132a0b07505bbd3f6022559e 100644 --- a/src/components/Map/MapViewer/utils/config/getCanvasIcon.ts +++ b/src/components/Map/MapViewer/utils/config/getCanvasIcon.ts @@ -59,7 +59,9 @@ export const drawNumberOnCanvas = ( ctx.fillText(text, x, y); }; -export const getCanvasIcon = (args: Args): HTMLCanvasElement => { +export const getCanvasIcon = ( + args: Omit<Args, 'value'> & { value?: number }, +): HTMLCanvasElement => { const canvas = createCanvas(PIN_SIZE); const ctx = canvas.getContext('2d'); if (!ctx) { @@ -67,7 +69,9 @@ export const getCanvasIcon = (args: Args): HTMLCanvasElement => { } drawPinOnCanvas(args, ctx); - drawNumberOnCanvas(args, ctx); + if (args?.value !== undefined) { + drawNumberOnCanvas({ value: args.value }, ctx); + } return canvas; }; diff --git a/src/components/Map/MapViewer/utils/config/overlaysLayer/parseSurfaceMarkersToBioEntityRender.test.ts b/src/components/Map/MapViewer/utils/config/overlaysLayer/parseSurfaceMarkersToBioEntityRender.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..0510f57200aec90f58f3e448f674bf965b90ca9a --- /dev/null +++ b/src/components/Map/MapViewer/utils/config/overlaysLayer/parseSurfaceMarkersToBioEntityRender.test.ts @@ -0,0 +1,96 @@ +import { MarkerSurface } from '@/redux/markers/markers.types'; +import { OverlayBioEntityRender } from '@/types/OLrendering'; +import { parseSurfaceMarkersToBioEntityRender } from './parseSurfaceMarkersToBioEntityRender'; + +const MARKERS: MarkerSurface[] = [ + { + type: 'surface', + id: '1', + color: '#000000', + opacity: 0.1, + x: 1200, + y: 500, + width: 100, + height: 50, + number: 0, + modelId: 0, + }, + { + type: 'surface', + id: '2', + color: '#FF0000', + opacity: 0.67, + x: 432, + y: 2343, + width: 100, + height: 50, + number: 23, + modelId: 33, + }, + { + type: 'surface', + id: '3', + color: '#FFFFFF', + opacity: 0, + x: 1, + y: 1, + width: 2, + height: 2, + number: 1, + modelId: 1, + }, +]; + +const EXPECTED_RETURN: OverlayBioEntityRender[] = [ + { + color: null, + height: 50, + hexColor: '#0000001a', + id: '1', + modelId: 0, + overlayId: 0, + type: 'rectangle', + value: 0.1, + width: 100, + x1: 1200, + x2: 1300, + y1: 550, + y2: 500, + }, + { + color: null, + height: 50, + hexColor: '#FF0000ab', + id: '2', + modelId: 33, + overlayId: 0, + type: 'rectangle', + value: 0.67, + width: 100, + x1: 432, + x2: 532, + y1: 2393, + y2: 2343, + }, + { + color: null, + height: 2, + hexColor: '#FFFFFF00', + id: '3', + modelId: 1, + overlayId: 0, + type: 'rectangle', + value: 0, + width: 2, + x1: 1, + x2: 3, + y1: 3, + y2: 1, + }, +]; + +describe('parseSurfaceMarkersToBioEntityRender - util', () => { + it('returns correctly parsed markers for every element', () => { + expect(parseSurfaceMarkersToBioEntityRender(MARKERS)).toStrictEqual(EXPECTED_RETURN); + }); +}); diff --git a/src/components/Map/MapViewer/utils/config/overlaysLayer/parseSurfaceMarkersToBioEntityRender.ts b/src/components/Map/MapViewer/utils/config/overlaysLayer/parseSurfaceMarkersToBioEntityRender.ts new file mode 100644 index 0000000000000000000000000000000000000000..bd6461e9cf928d45ebee30fc191ca1daa137a523 --- /dev/null +++ b/src/components/Map/MapViewer/utils/config/overlaysLayer/parseSurfaceMarkersToBioEntityRender.ts @@ -0,0 +1,24 @@ +import { ZERO } from '@/constants/common'; +import { MarkerSurface } from '@/redux/markers/markers.types'; +import { OverlayBioEntityRender } from '@/types/OLrendering'; +import { addAlphaToHexString } from '@/utils/convert/addAlphaToHexString'; + +export const parseSurfaceMarkersToBioEntityRender = ( + markers: MarkerSurface[], +): OverlayBioEntityRender[] => { + return markers.map(({ id, modelId, x, y, width, height, color, opacity }) => ({ + type: 'rectangle', + id, + x1: x, + y1: y + height, + x2: x + width, + y2: y, + width, + height, + value: opacity, + modelId: modelId || ZERO, // ignored in next steps + overlayId: ZERO, // ignored in next steps + color: null, // replaced by hexColor in next steps + hexColor: addAlphaToHexString(color, opacity), + })); +}; diff --git a/src/components/Map/MapViewer/utils/config/overlaysLayer/useOverlayFeatures.test.ts b/src/components/Map/MapViewer/utils/config/overlaysLayer/useOverlayFeatures.test.ts index 15c9cf3e5e9820d3d3f9d604bc19a7e5dad1c383..3c4dbcfdeec212a14ebc661e6cdfb9723bd02199 100644 --- a/src/components/Map/MapViewer/utils/config/overlaysLayer/useOverlayFeatures.test.ts +++ b/src/components/Map/MapViewer/utils/config/overlaysLayer/useOverlayFeatures.test.ts @@ -1,6 +1,7 @@ /* eslint-disable no-magic-numbers */ import { CONFIGURATION_INITIAL_STORE_MOCKS } from '@/redux/configuration/configuration.mock'; import { mapStateWithCurrentlySelectedMainMapFixture } from '@/redux/map/map.fixtures'; +import { SURFACE_MARKER } from '@/redux/models/marker.mock'; import { MODELS_DATA_MOCK_WITH_MAIN_MAP } from '@/redux/models/models.mock'; import { MOCKED_OVERLAY_BIO_ENTITY_RENDER } from '@/redux/overlayBioEntity/overlayBioEntity.mock'; import { OVERLAYS_PUBLIC_FETCHED_STATE_MOCK } from '@/redux/overlays/overlays.mock'; @@ -43,6 +44,9 @@ describe('useOverlayFeatures', () => { models: { ...MODELS_DATA_MOCK_WITH_MAIN_MAP, }, + markers: { + data: [SURFACE_MARKER], + }, }); it('should return an array of features', () => { @@ -52,7 +56,7 @@ describe('useOverlayFeatures', () => { wrapper: Wrapper, }); - expect(features).toHaveLength(10); + expect(features).toHaveLength(11); // type: rectangle expect(features[0].getGeometry()?.getCoordinates()).toEqual([ @@ -81,5 +85,19 @@ describe('useOverlayFeatures', () => { // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore expect(features[7].getStyle().getFill().getColor()).toBe('#ff0000cc'); + + // type: rectangle (marker) + expect(features[10].getGeometry()?.getCoordinates()).toEqual([ + [ + [-19588560, 19831740], + [-19588560, 19850446], + [-19551147, 19850446], + [-19551147, 19831740], + [-19588560, 19831740], + ], + ]); + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + expect(features[10].getStyle().getFill().getColor()).toBe('#0000001a'); }); }); diff --git a/src/components/Map/MapViewer/utils/config/overlaysLayer/useOverlayFeatures.ts b/src/components/Map/MapViewer/utils/config/overlaysLayer/useOverlayFeatures.ts index 98e528f393c900d3716cbfb5814fca0db056ddb0..93e24ec85be8ac6dbab4bcfcf307448311c16fc0 100644 --- a/src/components/Map/MapViewer/utils/config/overlaysLayer/useOverlayFeatures.ts +++ b/src/components/Map/MapViewer/utils/config/overlaysLayer/useOverlayFeatures.ts @@ -1,5 +1,6 @@ import { ZERO } from '@/constants/common'; import { useAppSelector } from '@/redux/hooks/useAppSelector'; +import { markersSufraceOfCurrentMapDataSelector } from '@/redux/markers/markers.selectors'; import { getOverlayOrderSelector } from '@/redux/overlayBioEntity/overlayBioEntity.selector'; import { LinePoint } from '@/types/reactions'; import { usePointToProjection } from '@/utils/map/usePointToProjection'; @@ -9,17 +10,36 @@ import type Polygon from 'ol/geom/Polygon'; import { useMemo } from 'react'; import { createOverlayGeometryFeature } from './createOverlayGeometryFeature'; import { createOverlayLineFeature } from './createOverlayLineFeature'; +import { createOverlaySubmapLinkRectangleFeature } from './createOverlaySubmapLinkRectangleFeature'; import { getPolygonLatitudeCoordinates } from './getPolygonLatitudeCoordinates'; -import { useGetOverlayColor } from './useGetOverlayColor'; +import { parseSurfaceMarkersToBioEntityRender } from './parseSurfaceMarkersToBioEntityRender'; import { useBioEntitiesWithSubmapsLinks } from './useBioEntitiesWithSubmapLinks'; -import { createOverlaySubmapLinkRectangleFeature } from './createOverlaySubmapLinkRectangleFeature'; +import { useGetOverlayColor } from './useGetOverlayColor'; export const useOverlayFeatures = (): Feature<Polygon>[] | Feature<SimpleGeometry>[] => { const pointToProjection = usePointToProjection(); const { getOverlayBioEntityColorByAvailableProperties } = useGetOverlayColor(); const overlaysOrder = useAppSelector(getOverlayOrderSelector); + const currentMarkers = useAppSelector(markersSufraceOfCurrentMapDataSelector); + const markersRender = parseSurfaceMarkersToBioEntityRender(currentMarkers); const bioEntities = useBioEntitiesWithSubmapsLinks(); + const markersFeatures = useMemo( + () => + markersRender.map(entity => { + const color = getOverlayBioEntityColorByAvailableProperties(entity); + + return createOverlayGeometryFeature( + [ + ...pointToProjection({ x: entity.x1, y: entity.y1 }), + ...pointToProjection({ x: entity.x2, y: entity.y2 }), + ], + entity?.hexColor || color, + ); + }), + [getOverlayBioEntityColorByAvailableProperties, markersRender, pointToProjection], + ); + const features = useMemo( () => bioEntities.map(entity => { @@ -36,7 +56,9 @@ export const useOverlayFeatures = (): Feature<Polygon>[] | Feature<SimpleGeometr overlaysOrder.find(({ id }) => id === entity.overlayId)?.index || ZERO, }); - const color = getOverlayBioEntityColorByAvailableProperties(entity); + const calculatedColor = getOverlayBioEntityColorByAvailableProperties(entity); + const hexColor = entity?.hexColor; + const color = hexColor || calculatedColor; if (entity.type === 'submap-link') { return createOverlaySubmapLinkRectangleFeature( @@ -72,5 +94,5 @@ export const useOverlayFeatures = (): Feature<Polygon>[] | Feature<SimpleGeometr [overlaysOrder, pointToProjection, getOverlayBioEntityColorByAvailableProperties, bioEntities], ); - return features; + return [...features, ...markersFeatures]; }; diff --git a/src/components/Map/MapViewer/utils/config/pinsLayer/getMarkerSingleFeature.test.ts b/src/components/Map/MapViewer/utils/config/pinsLayer/getMarkerSingleFeature.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..b83827e5a3f402f9c3567716a9ce2ee2edf8d09b --- /dev/null +++ b/src/components/Map/MapViewer/utils/config/pinsLayer/getMarkerSingleFeature.test.ts @@ -0,0 +1,58 @@ +import { initialMapStateFixture } from '@/redux/map/map.fixtures'; +import { PIN_MARKER } from '@/redux/models/marker.mock'; +import { UsePointToProjectionResult, usePointToProjection } from '@/utils/map/usePointToProjection'; +import { + GetReduxWrapperUsingSliceReducer, + getReduxWrapperWithStore, +} from '@/utils/testing/getReduxWrapperWithStore'; +import { renderHook } from '@testing-library/react'; +import { Feature } from 'ol'; +import Style from 'ol/style/Style'; +import { getMarkerSingleFeature } from './getMarkerSingleFeature'; +import * as getPinStyle from './getPinStyle'; + +jest.mock('./getPinStyle', () => ({ + __esModule: true, + ...jest.requireActual('./getPinStyle'), +})); + +const getPinStyleSpy = jest.spyOn(getPinStyle, 'getPinStyle'); + +const getPointToProjection = ( + wrapper: ReturnType<GetReduxWrapperUsingSliceReducer>['Wrapper'], +): UsePointToProjectionResult => { + const { result: usePointToProjectionHook } = renderHook(() => usePointToProjection(), { + wrapper, + }); + + return usePointToProjectionHook.current; +}; + +describe('getMarkerSingleFeature - subUtil', () => { + const { Wrapper } = getReduxWrapperWithStore({ + map: initialMapStateFixture, + }); + const pointToProjection = getPointToProjection(Wrapper); + + it('should return instance of Feature with Style type=%s', () => { + const result = getMarkerSingleFeature(PIN_MARKER, { + pointToProjection, + }); + + const style = result.getStyle() as Style; + + expect(result).toBeInstanceOf(Feature); + expect(style).toBeInstanceOf(Style); + }); + + it('should run getPinStyle with valid args for type=%s', () => { + getMarkerSingleFeature(PIN_MARKER, { + pointToProjection, + }); + + expect(getPinStyleSpy).toHaveBeenCalledWith({ + color: '#0000001a', + value: PIN_MARKER.number, + }); + }); +}); diff --git a/src/components/Map/MapViewer/utils/config/pinsLayer/getMarkerSingleFeature.ts b/src/components/Map/MapViewer/utils/config/pinsLayer/getMarkerSingleFeature.ts new file mode 100644 index 0000000000000000000000000000000000000000..705debb673e1e8b5d38460e73fc1d8bcbe11fd1b --- /dev/null +++ b/src/components/Map/MapViewer/utils/config/pinsLayer/getMarkerSingleFeature.ts @@ -0,0 +1,24 @@ +import { Marker } from '@/redux/markers/markers.types'; +import { addAlphaToHexString } from '@/utils/convert/addAlphaToHexString'; +import { UsePointToProjectionResult } from '@/utils/map/usePointToProjection'; +import { Feature } from 'ol'; +import { getPinFeature } from './getPinFeature'; +import { getPinStyle } from './getPinStyle'; + +export const getMarkerSingleFeature = ( + marker: Marker, + { + pointToProjection, + }: { + pointToProjection: UsePointToProjectionResult; + }, +): Feature => { + const feature = getPinFeature(marker, pointToProjection); + const style = getPinStyle({ + color: addAlphaToHexString(marker.color, marker.opacity), + value: marker.number, + }); + + feature.setStyle(style); + return feature; +}; diff --git a/src/components/Map/MapViewer/utils/config/pinsLayer/getMarkersFeatures.ts b/src/components/Map/MapViewer/utils/config/pinsLayer/getMarkersFeatures.ts new file mode 100644 index 0000000000000000000000000000000000000000..fa12fb5e44b4ed9c587b7d8394aeb170fdc03658 --- /dev/null +++ b/src/components/Map/MapViewer/utils/config/pinsLayer/getMarkersFeatures.ts @@ -0,0 +1,19 @@ +import { Marker } from '@/redux/markers/markers.types'; +import { UsePointToProjectionResult } from '@/utils/map/usePointToProjection'; +import { Feature } from 'ol'; +import { getMarkerSingleFeature } from './getMarkerSingleFeature'; + +export const getMarkersFeatures = ( + markers: Marker[], + { + pointToProjection, + }: { + pointToProjection: UsePointToProjectionResult; + }, +): Feature[] => { + return markers.map(marker => + getMarkerSingleFeature(marker, { + pointToProjection, + }), + ); +}; diff --git a/src/components/Map/MapViewer/utils/config/pinsLayer/getPinFeature.test.ts b/src/components/Map/MapViewer/utils/config/pinsLayer/getPinFeature.test.ts index 64f3decc886751a4913a9d1b04cb0ff53241270b..28610fd818aa15ae7b6b9dc89fec3ab2e9042786 100644 --- a/src/components/Map/MapViewer/utils/config/pinsLayer/getPinFeature.test.ts +++ b/src/components/Map/MapViewer/utils/config/pinsLayer/getPinFeature.test.ts @@ -1,6 +1,7 @@ import { HALF } from '@/constants/dividers'; import { bioEntityContentFixture } from '@/models/fixtures/bioEntityContentsFixture'; import { initialMapStateFixture } from '@/redux/map/map.fixtures'; +import { PIN_MARKER } from '@/redux/models/marker.mock'; import { usePointToProjection } from '@/utils/map/usePointToProjection'; import { getReduxWrapperWithStore } from '@/utils/testing/getReduxWrapperWithStore'; import { renderHook } from '@testing-library/react'; @@ -35,4 +36,18 @@ describe('getPinFeature - subUtil', () => { expect([x, y]).toStrictEqual(geometryPoint); }); + + describe('when is Marker Pin', () => { + const pinMarkerResult = getPinFeature(PIN_MARKER, pointToProjection); + + it('should return point parsed with point to projection', () => { + const [x, y] = pinMarkerResult.getGeometry()?.getExtent() || []; + const geometryPoint = pointToProjection({ + x: PIN_MARKER.x, + y: PIN_MARKER.y, + }); + + expect([x, y]).toStrictEqual(geometryPoint); + }); + }); }); diff --git a/src/components/Map/MapViewer/utils/config/pinsLayer/getPinFeature.ts b/src/components/Map/MapViewer/utils/config/pinsLayer/getPinFeature.ts index ec09a90d48d11cf3d2f743fca21bbd5f1475244b..ff7bfb00b7af92fa23a3d9be3ae2e4d826320252 100644 --- a/src/components/Map/MapViewer/utils/config/pinsLayer/getPinFeature.ts +++ b/src/components/Map/MapViewer/utils/config/pinsLayer/getPinFeature.ts @@ -1,16 +1,18 @@ +import { ZERO } from '@/constants/common'; import { HALF } from '@/constants/dividers'; +import { Marker } from '@/redux/markers/markers.types'; import { BioEntity } from '@/types/models'; import { UsePointToProjectionResult } from '@/utils/map/usePointToProjection'; import { Feature } from 'ol'; import { Point } from 'ol/geom'; export const getPinFeature = ( - { x, y, width, height, id }: BioEntity, + { x, y, width, height, id }: Pick<BioEntity, 'id' | 'width' | 'height' | 'x' | 'y'> | Marker, pointToProjection: UsePointToProjectionResult, ): Feature => { const point = { - x: x + width / HALF, - y: y + height / HALF, + x: x + (width || ZERO) / HALF, + y: y + (height || ZERO) / HALF, }; return new Feature({ diff --git a/src/components/Map/MapViewer/utils/config/pinsLayer/getPinStyle.ts b/src/components/Map/MapViewer/utils/config/pinsLayer/getPinStyle.ts index 3e91dfc047c45e2d6ac6a872564028abe8deb2d7..77ee5c7f3d765eab8ae2d41872a1341198281ddc 100644 --- a/src/components/Map/MapViewer/utils/config/pinsLayer/getPinStyle.ts +++ b/src/components/Map/MapViewer/utils/config/pinsLayer/getPinStyle.ts @@ -4,7 +4,7 @@ import Icon from 'ol/style/Icon'; import Style from 'ol/style/Style'; import { getCanvasIcon } from '../getCanvasIcon'; -export const getPinStyle = ({ value, color }: { value: number; color: string }): Style => +export const getPinStyle = ({ value, color }: { value?: number; color: string }): Style => new Style({ image: new Icon({ displacement: [ZERO, PIN_SIZE.height], diff --git a/src/components/Map/MapViewer/utils/config/pinsLayer/useOlMapPinsLayer.ts b/src/components/Map/MapViewer/utils/config/pinsLayer/useOlMapPinsLayer.ts index ceecf01f0ad220d2637283d80ae564b650f13f53..2e98660497995ef8871b39a322ddfa147a213c89 100644 --- a/src/components/Map/MapViewer/utils/config/pinsLayer/useOlMapPinsLayer.ts +++ b/src/components/Map/MapViewer/utils/config/pinsLayer/useOlMapPinsLayer.ts @@ -2,6 +2,7 @@ import { searchedBioEntitesSelectorOfCurrentMap } from '@/redux/bioEntity/bioEntity.selectors'; import { searchedChemicalsBioEntitesOfCurrentMapSelector } from '@/redux/chemicals/chemicals.selectors'; import { searchedDrugsBioEntitesOfCurrentMapSelector } from '@/redux/drugs/drugs.selectors'; +import { markersPinsOfCurrentMapDataSelector } from '@/redux/markers/markers.selectors'; import { usePointToProjection } from '@/utils/map/usePointToProjection'; import Feature from 'ol/Feature'; import { Geometry } from 'ol/geom'; @@ -10,28 +11,31 @@ import VectorSource from 'ol/source/Vector'; import { useMemo } from 'react'; import { useSelector } from 'react-redux'; import { getBioEntitiesFeatures } from './getBioEntitiesFeatures'; +import { getMarkersFeatures } from './getMarkersFeatures'; export const useOlMapPinsLayer = (): VectorLayer<VectorSource<Feature<Geometry>>> => { const pointToProjection = usePointToProjection(); const contentBioEntites = useSelector(searchedBioEntitesSelectorOfCurrentMap); const chemicalsBioEntities = useSelector(searchedChemicalsBioEntitesOfCurrentMapSelector); const drugsBioEntities = useSelector(searchedDrugsBioEntitesOfCurrentMapSelector); + const markersEntities = useSelector(markersPinsOfCurrentMapDataSelector); - const bioEntityFeatures = useMemo( + const elementsFeatures = useMemo( () => [ getBioEntitiesFeatures(contentBioEntites, { pointToProjection, type: 'bioEntity' }), getBioEntitiesFeatures(chemicalsBioEntities, { pointToProjection, type: 'chemicals' }), getBioEntitiesFeatures(drugsBioEntities, { pointToProjection, type: 'drugs' }), + getMarkersFeatures(markersEntities, { pointToProjection }), ].flat(), - [contentBioEntites, drugsBioEntities, chemicalsBioEntities, pointToProjection], + [contentBioEntites, drugsBioEntities, chemicalsBioEntities, pointToProjection, markersEntities], ); const vectorSource = useMemo(() => { return new VectorSource({ - features: [...bioEntityFeatures], + features: [...elementsFeatures], }); - }, [bioEntityFeatures]); + }, [elementsFeatures]); const pinsLayer = useMemo( () => diff --git a/src/models/bioEntitySchema.ts b/src/models/bioEntitySchema.ts index a747e0cddc8a2f3e1aad1e5293d9dc5e6ae6c350..6f786cc8d19b2d68458fcc33f6a8dddb117f3415 100644 --- a/src/models/bioEntitySchema.ts +++ b/src/models/bioEntitySchema.ts @@ -10,7 +10,7 @@ import { structuralStateSchema } from './structuralStateSchema'; import { submodelSchema } from './submodelSchema'; export const bioEntitySchema = z.object({ - id: z.number(), + id: z.union([z.number(), z.string()]), stringType: z.string(), name: z.string(), elementId: z.string(), diff --git a/src/redux/bioEntity/bioEntity.reducers.ts b/src/redux/bioEntity/bioEntity.reducers.ts index 53ad51de4c5830bea28d573f92fd9103a25f40d8..7eb3b66c996baf7ea37060e06ce501b4b53558d6 100644 --- a/src/redux/bioEntity/bioEntity.reducers.ts +++ b/src/redux/bioEntity/bioEntity.reducers.ts @@ -1,5 +1,5 @@ -import { ActionReducerMapBuilder } from '@reduxjs/toolkit'; import { DEFAULT_ERROR } from '@/constants/errors'; +import { ActionReducerMapBuilder } from '@reduxjs/toolkit'; import { getBioEntity, getMultiBioEntity } from './bioEntity.thunks'; import { BioEntityContentsState } from './bioEntity.types'; @@ -49,3 +49,8 @@ export const getMultiBioEntityContentsReducer = ( // TODO: error management to be discussed in the team }); }; + +export const clearBioEntitiesDataReducer = (state: BioEntityContentsState): void => { + state.data = []; + state.loading = 'idle'; +}; diff --git a/src/redux/bioEntity/bioEntity.selectors.ts b/src/redux/bioEntity/bioEntity.selectors.ts index 8b39954fdb451fe218724c0315382a527b4f39b1..b9566eb75fbac7db3ed74d8ccdfdda56bd607adb 100644 --- a/src/redux/bioEntity/bioEntity.selectors.ts +++ b/src/redux/bioEntity/bioEntity.selectors.ts @@ -14,6 +14,12 @@ import { currentModelIdSelector, modelsDataSelector } from '../models/models.sel export const bioEntitySelector = createSelector(rootSelector, state => state.bioEntity); +export const bioEntityDataSelector = createSelector(bioEntitySelector, bioEntity => bioEntity.data); + +export const bioEntityDataListSelector = createSelector(bioEntityDataSelector, bioEntityData => + bioEntityData.map(b => b.data || []).flat(), +); + export const bioEntitiesForSelectedSearchElement = createSelector( bioEntitySelector, currentSelectedSearchElement, diff --git a/src/redux/bioEntity/bioEntity.slice.ts b/src/redux/bioEntity/bioEntity.slice.ts index 14821569fd0ecd68756f88fe52a88a4b17ab1db4..428e00ce2025d4881622332cf6cb2adb82909b88 100644 --- a/src/redux/bioEntity/bioEntity.slice.ts +++ b/src/redux/bioEntity/bioEntity.slice.ts @@ -1,6 +1,7 @@ import { BioEntityContentsState } from '@/redux/bioEntity/bioEntity.types'; import { createSlice } from '@reduxjs/toolkit'; import { + clearBioEntitiesDataReducer, getBioEntityContentsReducer, getMultiBioEntityContentsReducer, } from './bioEntity.reducers'; @@ -14,11 +15,15 @@ const initialState: BioEntityContentsState = { export const bioEntityContentsSlice = createSlice({ name: 'bioEntityContents', initialState, - reducers: {}, + reducers: { + clearBioEntitiesData: clearBioEntitiesDataReducer, + }, extraReducers: builder => { getBioEntityContentsReducer(builder); getMultiBioEntityContentsReducer(builder); }, }); +export const { clearBioEntitiesData } = bioEntityContentsSlice.actions; + export default bioEntityContentsSlice.reducer; diff --git a/src/redux/chemicals/chemicals.selectors.ts b/src/redux/chemicals/chemicals.selectors.ts index f2d10808719aa1f04fac0a93bba36bc68812407d..03f829f8de425665f9f0a4f6d15d94fd37fee2b8 100644 --- a/src/redux/chemicals/chemicals.selectors.ts +++ b/src/redux/chemicals/chemicals.selectors.ts @@ -8,6 +8,12 @@ import { currentModelIdSelector } from '../models/models.selectors'; export const chemicalsSelector = createSelector(rootSelector, state => state.chemicals); +export const chemicalsDataSelector = createSelector(chemicalsSelector, chemicals => chemicals.data); + +export const chemicalsDataListSelector = createSelector(chemicalsDataSelector, chemicalsData => + chemicalsData.map(c => c.data || []).flat(), +); + export const chemicalsForSelectedSearchElementSelector = createSelector( chemicalsSelector, currentSelectedSearchElement, diff --git a/src/redux/contextMenu/contextMenu.types.ts b/src/redux/contextMenu/contextMenu.types.ts index d95c38c9957babb317d18a327a70c5f1864ac2d5..7ab84923657cdbd77a93698937b9f0f9a770c147 100644 --- a/src/redux/contextMenu/contextMenu.types.ts +++ b/src/redux/contextMenu/contextMenu.types.ts @@ -4,5 +4,5 @@ export interface ContextMenuState { isOpen: boolean; coordinates: Pixel; uniprot: string; - currentSelectedBioEntityId: number; + currentSelectedBioEntityId: number | string; } diff --git a/src/redux/drawer/drawer.types.ts b/src/redux/drawer/drawer.types.ts index f4104f258ef17d1dd0eb416746adfde7e2bb91cb..a348517b0e6beea005555e28e870734205a4a090 100644 --- a/src/redux/drawer/drawer.types.ts +++ b/src/redux/drawer/drawer.types.ts @@ -20,7 +20,7 @@ export type ReactionDrawerState = { }; export type BioEntityDrawerState = { - bioentityId?: number; + bioentityId?: number | string; drugs: KeyedFetchDataState<Drug[], []>; chemicals: KeyedFetchDataState<Chemical[], []>; }; @@ -41,5 +41,5 @@ export type OpenSearchDrawerWithSelectedTabReducerAction = export type OpenReactionDrawerByIdPayload = number; export type OpenReactionDrawerByIdAction = PayloadAction<OpenReactionDrawerByIdPayload>; -export type OpenBioEntityDrawerByIdPayload = number; +export type OpenBioEntityDrawerByIdPayload = number | string; export type OpenBioEntityDrawerByIdAction = PayloadAction<OpenBioEntityDrawerByIdPayload>; diff --git a/src/redux/drugs/drugs.selectors.ts b/src/redux/drugs/drugs.selectors.ts index 6790c081e1303eaec49e5b8dc3045ba4a8d4a0be..45e9c16c828d894e31b3b5b3faf04a9fdd0981dc 100644 --- a/src/redux/drugs/drugs.selectors.ts +++ b/src/redux/drugs/drugs.selectors.ts @@ -8,6 +8,12 @@ import { currentModelIdSelector } from '../models/models.selectors'; export const drugsSelector = createSelector(rootSelector, state => state.drugs); +export const drugsDataSelector = createSelector(drugsSelector, drugs => drugs.data); + +export const drugsDataListSelector = createSelector(drugsDataSelector, drugsData => + drugsData.map(d => d.data || []).flat(), +); + export const drugsForSelectedSearchElementSelector = createSelector( drugsSelector, currentSelectedSearchElement, diff --git a/src/redux/markers/markers.constants.ts b/src/redux/markers/markers.constants.ts new file mode 100644 index 0000000000000000000000000000000000000000..576e0557a677eb894f4be9681bcc060802805257 --- /dev/null +++ b/src/redux/markers/markers.constants.ts @@ -0,0 +1,5 @@ +import { MarkersState } from './markers.types'; + +export const MARKERS_INITIAL_STATE: MarkersState = { + data: [], +}; diff --git a/src/redux/markers/markers.mock.ts b/src/redux/markers/markers.mock.ts new file mode 100644 index 0000000000000000000000000000000000000000..3f7df875a74165bd20f91ff1866bb43e9f38bb88 --- /dev/null +++ b/src/redux/markers/markers.mock.ts @@ -0,0 +1,5 @@ +import { MarkersState } from './markers.types'; + +export const MARKERS_INITIAL_STATE_MOCK: MarkersState = { + data: [], +}; diff --git a/src/redux/markers/markers.reducers.ts b/src/redux/markers/markers.reducers.ts new file mode 100644 index 0000000000000000000000000000000000000000..d0cad10d7ae84ae2c9659529480243e5f7664ea3 --- /dev/null +++ b/src/redux/markers/markers.reducers.ts @@ -0,0 +1,31 @@ +import { PayloadAction } from '@reduxjs/toolkit'; +import { Marker, MarkersState } from './markers.types'; + +export const setMarkersDataReducer = ( + state: MarkersState, + action: PayloadAction<Marker[]>, +): void => { + const { payload } = action; + + state.data = payload; +}; + +export const addMarkerToMarkersDataReducer = ( + state: MarkersState, + action: PayloadAction<Marker>, +): void => { + const { payload } = action; + + state.data.push(payload); +}; + +export const removeMarkerFromMarkersDataReducer = ( + state: MarkersState, + action: PayloadAction<string>, +): void => { + const currentMarkers = state.data; + const { payload: markerId } = action; + const newMarkers = currentMarkers.filter(m => m.id !== markerId); + + state.data = newMarkers; +}; diff --git a/src/redux/markers/markers.selectors.ts b/src/redux/markers/markers.selectors.ts new file mode 100644 index 0000000000000000000000000000000000000000..da6987b3ec82807bd85d2fdaf65dc82cd0015423 --- /dev/null +++ b/src/redux/markers/markers.selectors.ts @@ -0,0 +1,33 @@ +import { createSelector } from '@reduxjs/toolkit'; +import { currentModelIdSelector } from '../models/models.selectors'; +import { rootSelector } from '../root/root.selectors'; +import { MarkerSurface } from './markers.types'; +import { isMarkerSurface } from './markers.utils'; + +export const markersSelector = createSelector(rootSelector, state => state.markers); + +export const markersDataSelector = createSelector(markersSelector, markers => markers.data); + +export const markersDataOfCurrentMapSelector = createSelector( + markersDataSelector, + currentModelIdSelector, + (markers, modelId) => markers.filter(p => (p.modelId ? p.modelId === modelId : true)), +); + +export const markersPinsDataSelector = createSelector(markersDataSelector, markersData => + markersData.filter(m => m.type === 'pin'), +); + +export const markersPinsOfCurrentMapDataSelector = createSelector( + markersDataOfCurrentMapSelector, + markersData => markersData.filter(m => m.type === 'pin'), +); + +export const markersSufraceSelector = createSelector(markersDataSelector, markersData => + markersData.filter(m => m.type === 'surface'), +); + +export const markersSufraceOfCurrentMapDataSelector = createSelector( + markersDataOfCurrentMapSelector, + (markers): MarkerSurface[] => markers.filter(isMarkerSurface), +); diff --git a/src/redux/markers/markers.slice.ts b/src/redux/markers/markers.slice.ts new file mode 100644 index 0000000000000000000000000000000000000000..d37bd49705465f1c025f91788572645d55ab4575 --- /dev/null +++ b/src/redux/markers/markers.slice.ts @@ -0,0 +1,23 @@ +import { createSlice } from '@reduxjs/toolkit'; +import { MARKERS_INITIAL_STATE } from './markers.constants'; +import { + addMarkerToMarkersDataReducer, + removeMarkerFromMarkersDataReducer, + setMarkersDataReducer, +} from './markers.reducers'; + +const markersSlice = createSlice({ + name: 'markers', + initialState: MARKERS_INITIAL_STATE, + reducers: { + setMarkersData: setMarkersDataReducer, + addMarkerToMarkersData: addMarkerToMarkersDataReducer, + removeMarkerFromMarkersData: removeMarkerFromMarkersDataReducer, + }, + extraReducers: () => {}, +}); + +export const { setMarkersData, addMarkerToMarkersData, removeMarkerFromMarkersData } = + markersSlice.actions; + +export default markersSlice.reducer; diff --git a/src/redux/markers/markers.types.ts b/src/redux/markers/markers.types.ts new file mode 100644 index 0000000000000000000000000000000000000000..4ea8307815f564d7ca8826cc2dcb4efc987d5a40 --- /dev/null +++ b/src/redux/markers/markers.types.ts @@ -0,0 +1,30 @@ +export type MarkerType = 'pin' | 'surface'; + +interface MarkerBase { + type: MarkerType; + id: string; + color: string; + opacity: number; + x: number; + y: number; + number?: number; + modelId?: number; +} + +export interface MarkerPin extends MarkerBase { + width?: number; + height?: number; +} + +export interface MarkerSurface extends MarkerBase { + width: number; + height: number; +} + +export type Marker = MarkerPin | MarkerSurface; + +export type MarkerWithoutId = Omit<Marker, 'id'>; + +export interface MarkersState { + data: Marker[]; +} diff --git a/src/redux/markers/markers.utils.ts b/src/redux/markers/markers.utils.ts new file mode 100644 index 0000000000000000000000000000000000000000..08b862e3c28e819a260999cdfbc4214c411762d8 --- /dev/null +++ b/src/redux/markers/markers.utils.ts @@ -0,0 +1,4 @@ +import { Marker, MarkerSurface } from './markers.types'; + +export const isMarkerSurface = (marker: Marker): marker is MarkerSurface => + Boolean(marker?.width && marker?.height && marker.type === 'surface'); diff --git a/src/redux/models/marker.mock.ts b/src/redux/models/marker.mock.ts new file mode 100644 index 0000000000000000000000000000000000000000..951b5d627443f509194a2deec7739dd682e8e48d --- /dev/null +++ b/src/redux/models/marker.mock.ts @@ -0,0 +1,25 @@ +import { MarkerPin, MarkerSurface } from '../markers/markers.types'; + +export const SURFACE_MARKER: MarkerSurface = { + type: 'surface', + id: '1', + color: '#000000', + opacity: 0.1, + x: 1200, + y: 500, + width: 100, + height: 50, + number: 0, + modelId: 0, +}; + +export const PIN_MARKER: MarkerPin = { + type: 'pin', + id: '1', + color: '#000000', + opacity: 0.1, + x: 1200, + y: 500, + number: 0, + modelId: 0, +}; diff --git a/src/redux/root/root.fixtures.ts b/src/redux/root/root.fixtures.ts index b27b88cc9c1c96511ed626d5568b30d04999b1d3..66b6151cdd5494a54e3dd6c70cc3f03fd1d9acfb 100644 --- a/src/redux/root/root.fixtures.ts +++ b/src/redux/root/root.fixtures.ts @@ -1,6 +1,7 @@ import { BACKGROUND_INITIAL_STATE_MOCK } from '../backgrounds/background.mock'; import { BIOENTITY_INITIAL_STATE_MOCK } from '../bioEntity/bioEntity.mock'; import { CHEMICALS_INITIAL_STATE_MOCK } from '../chemicals/chemicals.mock'; +import { COMPARTMENT_PATHWAYS_INITIAL_STATE_MOCK } from '../compartmentPathways/compartmentPathways.mock'; import { CONFIGURATION_INITIAL_STATE } from '../configuration/configuration.adapter'; import { CONTEXT_MENU_INITIAL_STATE } from '../contextMenu/contextMenu.constants'; import { COOKIE_BANNER_INITIAL_STATE_MOCK } from '../cookieBanner/cookieBanner.mock'; @@ -9,19 +10,19 @@ import { DRUGS_INITIAL_STATE_MOCK } from '../drugs/drugs.mock'; import { EXPORT_INITIAL_STATE_MOCK } from '../export/export.mock'; import { LEGEND_INITIAL_STATE_MOCK } from '../legend/legend.mock'; import { initialMapStateFixture } from '../map/map.fixtures'; +import { MARKERS_INITIAL_STATE_MOCK } from '../markers/markers.mock'; import { MODAL_INITIAL_STATE_MOCK } from '../modal/modal.mock'; import { MODELS_INITIAL_STATE_MOCK } from '../models/models.mock'; import { OVERLAY_BIO_ENTITY_INITIAL_STATE_MOCK } from '../overlayBioEntity/overlayBioEntity.mock'; import { OVERLAYS_INITIAL_STATE_MOCK } from '../overlays/overlays.mock'; import { PLUGINS_INITIAL_STATE_MOCK } from '../plugins/plugins.mock'; import { PROJECT_STATE_INITIAL_MOCK } from '../project/project.mock'; +import { PUBLICATIONS_INITIAL_STATE_MOCK } from '../publications/publications.mock'; import { REACTIONS_STATE_INITIAL_MOCK } from '../reactions/reactions.mock'; import { SEARCH_STATE_INITIAL_MOCK } from '../search/search.mock'; +import { STATISTICS_STATE_INITIAL_MOCK } from '../statistics/statistics.mock'; import { RootState } from '../store'; import { USER_INITIAL_STATE_MOCK } from '../user/user.mock'; -import { STATISTICS_STATE_INITIAL_MOCK } from '../statistics/statistics.mock'; -import { COMPARTMENT_PATHWAYS_INITIAL_STATE_MOCK } from '../compartmentPathways/compartmentPathways.mock'; -import { PUBLICATIONS_INITIAL_STATE_MOCK } from '../publications/publications.mock'; export const INITIAL_STORE_STATE_MOCK: RootState = { search: SEARCH_STATE_INITIAL_MOCK, @@ -47,4 +48,5 @@ export const INITIAL_STORE_STATE_MOCK: RootState = { publications: PUBLICATIONS_INITIAL_STATE_MOCK, export: EXPORT_INITIAL_STATE_MOCK, plugins: PLUGINS_INITIAL_STATE_MOCK, + markers: MARKERS_INITIAL_STATE_MOCK, }; diff --git a/src/redux/store.ts b/src/redux/store.ts index 6aa4c44501acd537ce6d49ff63f4a9aba1c3e894..2391ea22a323314c9cb853939d9492a6d036e924 100644 --- a/src/redux/store.ts +++ b/src/redux/store.ts @@ -22,13 +22,14 @@ import { TypedStartListening, configureStore, } from '@reduxjs/toolkit'; +import compartmentPathwaysReducer from './compartmentPathways/compartmentPathways.slice'; import exportReducer from './export/export.slice'; import legendReducer from './legend/legend.slice'; import { mapListenerMiddleware } from './map/middleware/map.middleware'; +import markersReducer from './markers/markers.slice'; import pluginsReducer from './plugins/plugins.slice'; -import statisticsReducer from './statistics/statistics.slice'; -import compartmentPathwaysReducer from './compartmentPathways/compartmentPathways.slice'; import publicationsReducer from './publications/publications.slice'; +import statisticsReducer from './statistics/statistics.slice'; export const reducers = { search: searchReducer, @@ -54,6 +55,7 @@ export const reducers = { publications: publicationsReducer, export: exportReducer, plugins: pluginsReducer, + markers: markersReducer, }; export const middlewares = [mapListenerMiddleware.middleware]; diff --git a/src/services/pluginsManager/bioEntities/addSingleMarker.ts b/src/services/pluginsManager/bioEntities/addSingleMarker.ts new file mode 100644 index 0000000000000000000000000000000000000000..0b496795439fd0ad034442cae31d0e4493717133 --- /dev/null +++ b/src/services/pluginsManager/bioEntities/addSingleMarker.ts @@ -0,0 +1,12 @@ +import { addMarkerToMarkersData } from '@/redux/markers/markers.slice'; +import { Marker, MarkerWithoutId } from '@/redux/markers/markers.types'; +import { store } from '@/redux/store'; +import { v4 as uuidv4 } from 'uuid'; + +export const addSingleMarker = (markerWithoutId: MarkerWithoutId): Marker => { + const { dispatch } = store; + const marker = { id: uuidv4(), ...markerWithoutId }; + dispatch(addMarkerToMarkersData(marker)); + + return marker; +}; diff --git a/src/services/pluginsManager/bioEntities/clearAllElements.ts b/src/services/pluginsManager/bioEntities/clearAllElements.ts new file mode 100644 index 0000000000000000000000000000000000000000..9177d501b7078497512f2650bc677f3ca15b7fbe --- /dev/null +++ b/src/services/pluginsManager/bioEntities/clearAllElements.ts @@ -0,0 +1,27 @@ +import { clearBioEntitiesData } from '@/redux/bioEntity/bioEntity.slice'; +import { clearChemicalsData } from '@/redux/chemicals/chemicals.slice'; +import { clearDrugsData } from '@/redux/drugs/drugs.slice'; +import { setMarkersData } from '@/redux/markers/markers.slice'; +import { store } from '@/redux/store'; + +type ElementName = 'drugs' | 'chemicals' | 'content' | 'marker'; + +export const clearAllElements = (elements: ElementName[]): void => { + const { dispatch } = store; + + if (elements.includes('content')) { + dispatch(clearBioEntitiesData()); + } + + if (elements.includes('chemicals')) { + dispatch(clearChemicalsData()); + } + + if (elements.includes('drugs')) { + dispatch(clearDrugsData()); + } + + if (elements.includes('marker')) { + dispatch(setMarkersData([])); + } +}; diff --git a/src/services/pluginsManager/bioEntities/getAllChemicals.ts b/src/services/pluginsManager/bioEntities/getAllChemicals.ts new file mode 100644 index 0000000000000000000000000000000000000000..92cf1727075b21bb6c8d4e31049ccf49ecfc8459 --- /dev/null +++ b/src/services/pluginsManager/bioEntities/getAllChemicals.ts @@ -0,0 +1,10 @@ +import { chemicalsDataListSelector } from '@/redux/chemicals/chemicals.selectors'; +import { store } from '@/redux/store'; +import { Chemical } from '@/types/models'; + +export const getAllChemicals = (): Chemical[] => { + const { getState } = store; + const chemicals = chemicalsDataListSelector(getState()); + + return chemicals || []; +}; diff --git a/src/services/pluginsManager/bioEntities/getAllContent.ts b/src/services/pluginsManager/bioEntities/getAllContent.ts new file mode 100644 index 0000000000000000000000000000000000000000..af8f6d119499c61aea0ecaaa3c2c3bdd38d28c3d --- /dev/null +++ b/src/services/pluginsManager/bioEntities/getAllContent.ts @@ -0,0 +1,10 @@ +import { bioEntityDataListSelector } from '@/redux/bioEntity/bioEntity.selectors'; +import { store } from '@/redux/store'; +import { BioEntityContent } from '@/types/models'; + +export const getAllBioEntities = (): BioEntityContent[] => { + const { getState } = store; + const bioEntities = bioEntityDataListSelector(getState()); + + return bioEntities || []; +}; diff --git a/src/services/pluginsManager/bioEntities/getAllDrugs.ts b/src/services/pluginsManager/bioEntities/getAllDrugs.ts new file mode 100644 index 0000000000000000000000000000000000000000..3cd7b8c80d85fb7b41d7c8debe731dbc335add98 --- /dev/null +++ b/src/services/pluginsManager/bioEntities/getAllDrugs.ts @@ -0,0 +1,10 @@ +import { drugsDataListSelector } from '@/redux/drugs/drugs.selectors'; +import { store } from '@/redux/store'; +import { Drug } from '@/types/models'; + +export const getAllDrugs = (): Drug[] => { + const { getState } = store; + const drugs = drugsDataListSelector(getState()); + + return drugs || []; +}; diff --git a/src/services/pluginsManager/bioEntities/getAllMarkers.ts b/src/services/pluginsManager/bioEntities/getAllMarkers.ts new file mode 100644 index 0000000000000000000000000000000000000000..1ed70af6a1683d76bafe6f1d5afc2fd27b0e36ee --- /dev/null +++ b/src/services/pluginsManager/bioEntities/getAllMarkers.ts @@ -0,0 +1,10 @@ +import { markersDataSelector } from '@/redux/markers/markers.selectors'; +import { Marker } from '@/redux/markers/markers.types'; +import { store } from '@/redux/store'; + +export const getAllMarkers = (): Marker[] => { + const { getState } = store; + const markers = markersDataSelector(getState()); + + return markers; +}; diff --git a/src/services/pluginsManager/bioEntities/getShownElements.ts b/src/services/pluginsManager/bioEntities/getShownElements.ts new file mode 100644 index 0000000000000000000000000000000000000000..89cf67bdd2ad961dc7bd660bc5e5046cacd3ece4 --- /dev/null +++ b/src/services/pluginsManager/bioEntities/getShownElements.ts @@ -0,0 +1,22 @@ +import { searchedBioEntitesSelectorOfCurrentMap } from '@/redux/bioEntity/bioEntity.selectors'; +import { searchedChemicalsBioEntitesOfCurrentMapSelector } from '@/redux/chemicals/chemicals.selectors'; +import { searchedDrugsBioEntitesOfCurrentMapSelector } from '@/redux/drugs/drugs.selectors'; +import { markersPinsOfCurrentMapDataSelector } from '@/redux/markers/markers.selectors'; +import { store } from '@/redux/store'; +import { GetShownElementsPluginMethodResult } from './getShownElements.types'; + +export const getShownElements = (): GetShownElementsPluginMethodResult => { + const { getState } = store; + + const content = searchedBioEntitesSelectorOfCurrentMap(getState()); + const chemicals = searchedChemicalsBioEntitesOfCurrentMapSelector(getState()); + const drugs = searchedDrugsBioEntitesOfCurrentMapSelector(getState()); + const markers = markersPinsOfCurrentMapDataSelector(getState()); + + return { + content, + chemicals, + drugs, + markers, + }; +}; diff --git a/src/services/pluginsManager/bioEntities/getShownElements.types.ts b/src/services/pluginsManager/bioEntities/getShownElements.types.ts new file mode 100644 index 0000000000000000000000000000000000000000..dcbacd297ec5a113d4ebba2ea3c469a1b2e8ffcb --- /dev/null +++ b/src/services/pluginsManager/bioEntities/getShownElements.types.ts @@ -0,0 +1,9 @@ +import { Marker } from '@/redux/markers/markers.types'; +import { BioEntity } from '@/types/models'; + +export interface GetShownElementsPluginMethodResult { + content: BioEntity[]; + drugs: BioEntity[]; + chemicals: BioEntity[]; + markers: Marker[]; +} diff --git a/src/services/pluginsManager/bioEntities/index.ts b/src/services/pluginsManager/bioEntities/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..0e77668cb5806f1ad73645280988ea0b81b61dad --- /dev/null +++ b/src/services/pluginsManager/bioEntities/index.ts @@ -0,0 +1,23 @@ +import { addSingleMarker } from './addSingleMarker'; +import { clearAllElements } from './clearAllElements'; +import { getAllChemicals } from './getAllChemicals'; +import { getAllBioEntities } from './getAllContent'; +import { getAllDrugs } from './getAllDrugs'; +import { getAllMarkers } from './getAllMarkers'; +import { getShownElements } from './getShownElements'; +import { removeAllMarkers } from './removeAllMarkers'; +import { removeSingleMarker } from './removeSingleMarker'; + +export const bioEntitiesMethods = { + getAllBioEntities, + getAllChemicals, + getAllDrugs, + getAllMarkers, + getShownElements, + addSingleMarker, + removeSingleMarker, + removeAllMarkers, + clearAllElements, +}; + +export type BioEntitiesMethods = typeof bioEntitiesMethods; diff --git a/src/services/pluginsManager/bioEntities/removeAllMarkers.ts b/src/services/pluginsManager/bioEntities/removeAllMarkers.ts new file mode 100644 index 0000000000000000000000000000000000000000..3224d83b6648126cb3382e8501211572253a820b --- /dev/null +++ b/src/services/pluginsManager/bioEntities/removeAllMarkers.ts @@ -0,0 +1,7 @@ +import { setMarkersData } from '@/redux/markers/markers.slice'; +import { store } from '@/redux/store'; + +export const removeAllMarkers = (): void => { + const { dispatch } = store; + dispatch(setMarkersData([])); +}; diff --git a/src/services/pluginsManager/bioEntities/removeSingleMarker.ts b/src/services/pluginsManager/bioEntities/removeSingleMarker.ts new file mode 100644 index 0000000000000000000000000000000000000000..d8254453444235277143a60809c354fcf9a048a5 --- /dev/null +++ b/src/services/pluginsManager/bioEntities/removeSingleMarker.ts @@ -0,0 +1,7 @@ +import { removeMarkerFromMarkersData } from '@/redux/markers/markers.slice'; +import { store } from '@/redux/store'; + +export const removeSingleMarker = (id: string): void => { + const { dispatch } = store; + dispatch(removeMarkerFromMarkersData(id)); +}; diff --git a/src/services/pluginsManager/pluginsManager.ts b/src/services/pluginsManager/pluginsManager.ts index 66ad3b93d18d04c97a9cd9bd055ac6b356bcadd9..fce5756903a9a6b69434e782cca705d9d6ccc23e 100644 --- a/src/services/pluginsManager/pluginsManager.ts +++ b/src/services/pluginsManager/pluginsManager.ts @@ -2,6 +2,7 @@ import { PLUGINS_CONTENT_ELEMENT_ATTR_NAME, PLUGINS_CONTENT_ELEMENT_ID } from '@ import { registerPlugin } from '@/redux/plugins/plugins.thunks'; import { store } from '@/redux/store'; import md5 from 'crypto-js/md5'; +import { bioEntitiesMethods } from './bioEntities'; import type { PluginsManagerType } from './pluginsManager.types'; import { configurationMapper } from './pluginsManager.utils'; @@ -19,6 +20,9 @@ export const PluginsManager: PluginsManagerType = { plugins: { registerPlugin: PluginsManager.registerPlugin, }, + data: { + bioEntities: bioEntitiesMethods, + }, }; const unsubscribe = store.subscribe(() => { diff --git a/src/types/OLrendering.ts b/src/types/OLrendering.ts index 9769064d9bada810382fe653e7df432030f9f94b..54f0c7ab06ea5521f4206a0599e0aba5b7f954f4 100644 --- a/src/types/OLrendering.ts +++ b/src/types/OLrendering.ts @@ -3,7 +3,7 @@ import { Color, GeneVariant } from './models'; export type OverlayBioEntityRenderType = 'line' | 'rectangle' | 'submap-link'; export type OverlayBioEntityRender = { - id: number; + id: number | string; modelId: number; /** bottom left corner of whole element, Xmin */ x1: number; @@ -18,6 +18,7 @@ export type OverlayBioEntityRender = { value: number | null; overlayId: number; color: Color | null; + hexColor?: string; type: OverlayBioEntityRenderType; geneVariants?: GeneVariant[] | null; };