Skip to content
Snippets Groups Projects
Commit 59d4fd60 authored by Tadeusz Miesiąc's avatar Tadeusz Miesiąc
Browse files

feat(configuration options): fetch configuration at start of the app

parent d8d3894d
No related branches found
No related tags found
2 merge requests!223reset the pin numbers before search results are fetch (so the results will be...,!78Resolve MIN-189 "/display general overlays"
Showing
with 312 additions and 0 deletions
// const overlayParticleMock = {
// left: {
// // molekuła na której jest prostokąt
// id: 38929,
// model: 52,
// glyph: null,
// submodel: null,
// compartment: 46645,
// elementId: 'path_0_sa8410',
// x: 15181.0, // wspolrzedne do lewego gornego naroznika
// y: 6976.0, // wspolrzedne do lewego gornego naroznika
// z: 4528,
// width: 80.0,
// height: 40.0,
// fontSize: 12.0,
// fontColor: {
// alpha: 255,
// rgb: -16777216,
// },
// fillColor: {
// alpha: 255,
// rgb: -3342388, // wartosc hexa przeksztalcona na wartosc binarna? rgb
// },
// borderColor: {
// alpha: 255,
// rgb: -16777216,
// },
// visibilityLevel: '3',
// transparencyLevel: '0',
// notes: '',
// symbol: 'ATP6V0B',
// fullName: 'ATPase H+ transporting V0 subunit b',
// abbreviation: null,
// formula: null,
// name: 'ATP6V0B',
// nameX: 15181.0,
// nameY: 6976.0,
// nameWidth: 80.0,
// nameHeight: 40.0,
// nameVerticalAlign: 'MIDDLE',
// nameHorizontalAlign: 'CENTER',
// synonyms: ['HATPL', 'VMA16'],
// formerSymbols: ['ATP6F'],
// activity: false,
// lineWidth: 1.0,
// complex: 38928,
// initialAmount: null,
// charge: null,
// initialConcentration: 0.0,
// onlySubstanceUnits: false,
// homodimer: 1,
// hypothetical: null,
// boundaryCondition: false,
// constant: false,
// modificationResidues: [],
// stringType: 'Protein',
// substanceUnits: null,
// references: [
// {
// link: 'https://www.ncbi.nlm.nih.gov/gene/533',
// type: 'ENTREZ',
// resource: '533',
// id: 178289,
// annotatorClassName: 'lcsb.mapviewer.annotation.services.annotators.HgncAnnotator',
// },
// {
// link: 'https://www.ncbi.nlm.nih.gov/protein/NM_004047',
// type: 'REFSEQ',
// resource: 'NM_004047',
// id: 178290,
// annotatorClassName: 'lcsb.mapviewer.annotation.services.annotators.HgncAnnotator',
// },
// {
// link: 'https://www.genenames.org/cgi-bin/gene_symbol_report?match=ATP6V0B',
// type: 'HGNC_SYMBOL',
// resource: 'ATP6V0B',
// id: 178291,
// annotatorClassName: 'lcsb.mapviewer.annotation.services.annotators.HgncAnnotator',
// },
// {
// link: 'https://www.ensembl.org/id/ENSG00000117410',
// type: 'ENSEMBL',
// resource: 'ENSG00000117410',
// id: 178292,
// annotatorClassName: 'lcsb.mapviewer.annotation.services.annotators.HgncAnnotator',
// },
// {
// link: 'https://purl.uniprot.org/uniprot/Q99437',
// type: 'UNIPROT',
// resource: 'Q99437',
// id: 178293,
// annotatorClassName: 'lcsb.mapviewer.annotation.services.annotators.HgncAnnotator',
// },
// {
// link: 'https://www.genenames.org/data/gene-symbol-report/#!/hgnc_id/861',
// type: 'HGNC',
// resource: '861',
// id: 178294,
// annotatorClassName: 'lcsb.mapviewer.annotation.services.annotators.HgncAnnotator',
// },
// ],
// },
// right: {
// // definiuje prostokat, na jakiej podstawie zostalo matchowane, moze byc nazwa, identyfikator, nazwa+mapa
// id: 9558,
// name: 'ATP6V0B',
// modelName: null,
// elementId: null,
// reverseReaction: null,
// lineWidth: null,
// // bede mial albo wartosc albo kolor, jak bede mial oba (raczej nie bedzie) to jest to bug
// value: -0.493438352, // musze wartość zmapowac na kolor -> -1 to np czerwony a 1 to niebieski. Nie mam koloru. W configuracji minervy jest legenda z kolorem dla -1, 0 i 1
// color: null,
// // kiedy nie ma wartości value i color to z configuracji jest brany element "no color val" dla koloru
// description: null,
// },
// };
// const color = {
// // definiuje prostokat, na jakiej podstawie zostalo matchowane, moze byc nazwa, identyfikator, nazwa+mapa
// id: 9558,
// name: 'ATP6V0B',
// modelName: null,
// elementId: null,
// reverseReaction: null,
// lineWidth: null,
// // bede mial albo wartosc albo kolor, jak bede mial oba (raczej nie bedzie) to jest to bug
// value: null,
// color: {
// alpha: 255,
// rgb: -16711936,
// },
// description: null,
// };
// // pole lines jest od reakcji - polegac na tym polu zeby odroznic molekuly od reakcji
// // porozmawiac z Markiem o sumowaniu overlays na przycisku "go to submap"
import { z } from 'zod';
export const configurationOptionSchema = z.object({
idObject: z.number(),
type: z.string(),
valueType: z.string(),
commonName: z.string(),
isServerSide: z.boolean(),
value: z.string().optional(),
group: z.string(),
});
import { ConfigurationOption } from '@/types/models';
export const CONFIGURATION_OPTIONS_TYPES_MOCK: string[] = [
'MIN_COLOR_VAL',
'MAX_COLOR_VAL',
'SIMPLE_COLOR_VAL',
'NEUTRAL_COLOR_VAL',
];
export const CONFIGURATION_OPTIONS_COLOURS_MOCK: ConfigurationOption[] = [
{
idObject: 29,
type: 'MIN_COLOR_VAL',
valueType: 'COLOR',
commonName: 'Overlay color for negative values',
isServerSide: false,
value: 'FF0000',
group: 'Overlays',
},
{
idObject: 30,
type: 'MAX_COLOR_VAL',
valueType: 'COLOR',
commonName: 'Overlay color for postive values',
isServerSide: false,
value: '0000FF',
group: 'Overlays',
},
{
idObject: 31,
type: 'SIMPLE_COLOR_VAL',
valueType: 'COLOR',
commonName: 'Overlay color when no values are defined',
isServerSide: false,
value: '00FF00',
group: 'Overlays',
},
{
idObject: 32,
type: 'NEUTRAL_COLOR_VAL',
valueType: 'COLOR',
commonName: 'Overlay color for value=0',
isServerSide: false,
value: 'FFFFFF',
group: 'Overlays',
},
];
...@@ -29,4 +29,5 @@ export const apiPath = { ...@@ -29,4 +29,5 @@ export const apiPath = {
getAllBackgroundsByProjectIdQuery: (projectId: string): string => getAllBackgroundsByProjectIdQuery: (projectId: string): string =>
`projects/${projectId}/backgrounds/`, `projects/${projectId}/backgrounds/`,
getProjectById: (projectId: string): string => `projects/${projectId}`, getProjectById: (projectId: string): string => `projects/${projectId}`,
getConfigurationOptions: (): string => 'configuration/options/',
}; };
import { DEFAULT_ERROR } from '@/constants/errors';
import { Loading } from '@/types/loadingState';
import { ConfigurationOption } from '@/types/models';
import { createEntityAdapter } from '@reduxjs/toolkit';
export const configurationAdapter = createEntityAdapter<ConfigurationOption>({
selectId: option => option.type,
});
const REQUEST_INITIAL_STATUS: { loading: Loading; error: Error } = {
loading: 'idle',
error: DEFAULT_ERROR,
};
export const CONFIGURATION_INITIAL_STATE =
configurationAdapter.getInitialState(REQUEST_INITIAL_STATUS);
export type ConfigurationState = typeof CONFIGURATION_INITIAL_STATE;
/* eslint-disable no-magic-numbers */
import { DEFAULT_ERROR } from '@/constants/errors';
import {
CONFIGURATION_OPTIONS_TYPES_MOCK,
CONFIGURATION_OPTIONS_COLOURS_MOCK,
} from '@/models/mocks/configurationOptionMock';
import { ConfigurationState } from './configuration.adapter';
export const CONFIGURATION_INITIAL_STORE_MOCK: ConfigurationState = {
ids: [],
entities: {},
loading: 'idle',
error: DEFAULT_ERROR,
};
/** IMPORTANT MOCK IDS MUST MATCH KEYS IN ENTITIES */
export const CONFIGURATION_INITIAL_STORE_MOCKS: ConfigurationState = {
ids: CONFIGURATION_OPTIONS_TYPES_MOCK,
entities: {
[CONFIGURATION_OPTIONS_TYPES_MOCK[0]]: CONFIGURATION_OPTIONS_COLOURS_MOCK[0],
[CONFIGURATION_OPTIONS_TYPES_MOCK[1]]: CONFIGURATION_OPTIONS_COLOURS_MOCK[1],
[CONFIGURATION_OPTIONS_TYPES_MOCK[2]]: CONFIGURATION_OPTIONS_COLOURS_MOCK[2],
[CONFIGURATION_OPTIONS_TYPES_MOCK[3]]: CONFIGURATION_OPTIONS_COLOURS_MOCK[3],
},
loading: 'idle',
error: DEFAULT_ERROR,
};
import { ActionReducerMapBuilder } from '@reduxjs/toolkit';
import { getConfigurationOptions } from './configuration.thunks';
import { ConfigurationState, configurationAdapter } from './configuration.adapter';
export const getConfigurationOptionsReducer = (
builder: ActionReducerMapBuilder<ConfigurationState>,
): void => {
builder.addCase(getConfigurationOptions.pending, state => {
state.loading = 'pending';
});
builder.addCase(getConfigurationOptions.fulfilled, (state, action) => {
if (action.payload) {
state.loading = 'succeeded';
configurationAdapter.addMany(state, action.payload);
}
});
builder.addCase(getConfigurationOptions.rejected, state => {
state.loading = 'failed';
// TODO to discuss manage state of failure
});
};
import { createSlice } from '@reduxjs/toolkit';
import { getConfigurationOptionsReducer } from './configuration.reducers';
import { CONFIGURATION_INITIAL_STATE } from './configuration.adapter';
export const configurationSlice = createSlice({
name: 'configuration',
initialState: CONFIGURATION_INITIAL_STATE,
reducers: {},
extraReducers: builder => {
getConfigurationOptionsReducer(builder);
},
});
export default configurationSlice.reducer;
import { ConfigurationOption } from '@/types/models';
import { createAsyncThunk } from '@reduxjs/toolkit';
import { z } from 'zod';
import { axiosInstance } from '@/services/api/utils/axiosInstance';
import { validateDataUsingZodSchema } from '@/utils/validateDataUsingZodSchema';
import { configurationOptionSchema } from '@/models/configurationOptionSchema';
import { apiPath } from '../apiPath';
export const getConfigurationOptions = createAsyncThunk(
'configuration/getConfigurationOptions',
async (): Promise<ConfigurationOption[] | undefined> => {
const response = await axiosInstance.get<ConfigurationOption[]>(
apiPath.getConfigurationOptions(),
);
const isDataValid = validateDataUsingZodSchema(
response.data,
z.array(configurationOptionSchema),
);
return isDataValid ? response.data : undefined;
},
);
...@@ -16,6 +16,7 @@ import { ...@@ -16,6 +16,7 @@ import {
} from '../map/map.thunks'; } from '../map/map.thunks';
import { getSearchData } from '../search/search.thunks'; import { getSearchData } from '../search/search.thunks';
import { setPerfectMatch } from '../search/search.slice'; import { setPerfectMatch } from '../search/search.slice';
import { getConfigurationOptions } from '../configuration/configuration.thunks';
interface InitializeAppParams { interface InitializeAppParams {
queryData: QueryData; queryData: QueryData;
...@@ -28,6 +29,7 @@ export const fetchInitialAppData = createAsyncThunk< ...@@ -28,6 +29,7 @@ export const fetchInitialAppData = createAsyncThunk<
>('appInit/fetchInitialAppData', async ({ queryData }, { dispatch }): Promise<void> => { >('appInit/fetchInitialAppData', async ({ queryData }, { dispatch }): Promise<void> => {
/** Fetch all data required for renderin map */ /** Fetch all data required for renderin map */
await Promise.all([ await Promise.all([
dispatch(getConfigurationOptions()),
dispatch(getProjectById(PROJECT_ID)), dispatch(getProjectById(PROJECT_ID)),
dispatch(getAllBackgroundsByProjectId(PROJECT_ID)), dispatch(getAllBackgroundsByProjectId(PROJECT_ID)),
dispatch(getAllPublicOverlaysByProjectId(PROJECT_ID)), dispatch(getAllPublicOverlaysByProjectId(PROJECT_ID)),
......
import { BACKGROUND_INITIAL_STATE_MOCK } from '../backgrounds/background.mock'; import { BACKGROUND_INITIAL_STATE_MOCK } from '../backgrounds/background.mock';
import { BIOENTITY_INITIAL_STATE_MOCK } from '../bioEntity/bioEntity.mock'; import { BIOENTITY_INITIAL_STATE_MOCK } from '../bioEntity/bioEntity.mock';
import { CHEMICALS_INITIAL_STATE_MOCK } from '../chemicals/chemicals.mock'; import { CHEMICALS_INITIAL_STATE_MOCK } from '../chemicals/chemicals.mock';
import { CONFIGURATION_INITIAL_STATE } from '../configuration/configuration.adapter';
import { initialStateFixture as drawerInitialStateMock } from '../drawer/drawerFixture'; import { initialStateFixture as drawerInitialStateMock } from '../drawer/drawerFixture';
import { DRUGS_INITIAL_STATE_MOCK } from '../drugs/drugs.mock'; import { DRUGS_INITIAL_STATE_MOCK } from '../drugs/drugs.mock';
import { initialMapStateFixture } from '../map/map.fixtures'; import { initialMapStateFixture } from '../map/map.fixtures';
...@@ -23,4 +24,5 @@ export const INITIAL_STORE_STATE_MOCK: RootState = { ...@@ -23,4 +24,5 @@ export const INITIAL_STORE_STATE_MOCK: RootState = {
map: initialMapStateFixture, map: initialMapStateFixture,
overlays: OVERLAYS_INITIAL_STATE_MOCK, overlays: OVERLAYS_INITIAL_STATE_MOCK,
reactions: REACTIONS_STATE_INITIAL_MOCK, reactions: REACTIONS_STATE_INITIAL_MOCK,
configuration: CONFIGURATION_INITIAL_STATE,
}; };
...@@ -9,6 +9,7 @@ import overlaysReducer from '@/redux/overlays/overlays.slice'; ...@@ -9,6 +9,7 @@ import overlaysReducer from '@/redux/overlays/overlays.slice';
import projectReducer from '@/redux/project/project.slice'; import projectReducer from '@/redux/project/project.slice';
import reactionsReducer from '@/redux/reactions/reactions.slice'; import reactionsReducer from '@/redux/reactions/reactions.slice';
import searchReducer from '@/redux/search/search.slice'; import searchReducer from '@/redux/search/search.slice';
import configurationReducer from '@/redux/configuration/configuration.slice';
import { import {
AnyAction, AnyAction,
ListenerEffectAPI, ListenerEffectAPI,
...@@ -30,6 +31,7 @@ export const reducers = { ...@@ -30,6 +31,7 @@ export const reducers = {
overlays: overlaysReducer, overlays: overlaysReducer,
models: modelsReducer, models: modelsReducer,
reactions: reactionsReducer, reactions: reactionsReducer,
configuration: configurationReducer,
}; };
export const middlewares = [mapListenerMiddleware.middleware]; export const middlewares = [mapListenerMiddleware.middleware];
......
export type Loading = 'idle' | 'pending' | 'succeeded' | 'failed'; export type Loading = 'idle' | 'pending' | 'succeeded' | 'failed';
export interface LoadingInterface {
loading: 'idle' | 'pending' | 'succeeded' | 'failed';
}
...@@ -2,6 +2,7 @@ import { bioEntityContentSchema } from '@/models/bioEntityContentSchema'; ...@@ -2,6 +2,7 @@ import { bioEntityContentSchema } from '@/models/bioEntityContentSchema';
import { bioEntityResponseSchema } from '@/models/bioEntityResponseSchema'; import { bioEntityResponseSchema } from '@/models/bioEntityResponseSchema';
import { bioEntitySchema } from '@/models/bioEntitySchema'; import { bioEntitySchema } from '@/models/bioEntitySchema';
import { chemicalSchema } from '@/models/chemicalSchema'; import { chemicalSchema } from '@/models/chemicalSchema';
import { configurationOptionSchema } from '@/models/configurationOptionSchema';
import { disease } from '@/models/disease'; import { disease } from '@/models/disease';
import { drugSchema } from '@/models/drugSchema'; import { drugSchema } from '@/models/drugSchema';
import { elementSearchResult, elementSearchResultType } from '@/models/elementSearchResult'; import { elementSearchResult, elementSearchResultType } from '@/models/elementSearchResult';
...@@ -35,3 +36,4 @@ export type Reference = z.infer<typeof referenceSchema>; ...@@ -35,3 +36,4 @@ export type Reference = z.infer<typeof referenceSchema>;
export type ReactionLine = z.infer<typeof reactionLineSchema>; export type ReactionLine = z.infer<typeof reactionLineSchema>;
export type ElementSearchResult = z.infer<typeof elementSearchResult>; export type ElementSearchResult = z.infer<typeof elementSearchResult>;
export type ElementSearchResultType = z.infer<typeof elementSearchResultType>; export type ElementSearchResultType = z.infer<typeof elementSearchResultType>;
export type ConfigurationOption = z.infer<typeof configurationOptionSchema>;
- render overlays for map for single element
-
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment