geneViewTranscriptsSlice.ts 8.1 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
/**
 * See the NOTICE file distributed with this work for additional information
 * regarding copyright ownership.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { createSlice, PayloadAction } from '@reduxjs/toolkit';
import { Action } from 'redux';
import { ThunkAction } from 'redux-thunk';
20
import set from 'lodash/fp/set';
21 22 23

import {
  getEntityViewerActiveGenomeId,
24
  getEntityViewerActiveEntityId
25 26 27 28
} from 'src/content/app/entity-viewer/state/general/entityViewerGeneralSelectors';

import {
  getExpandedTranscriptIds,
29 30
  getExpandedTranscriptDownloadIds,
  getExpandedTranscriptMoreInfoIds
31 32 33 34
} from './geneViewTranscriptsSelectors';

import { RootState } from 'src/store';

35 36
export enum SortingRule {
  DEFAULT = 'default',
Ridwan Amode's avatar
Ridwan Amode committed
37 38 39 40
  SPLICED_LENGTH_DESC = 'spliced_length_desc',
  SPLICED_LENGTH_ASC = 'spliced_length_asc',
  EXON_COUNT_DESC = 'exon_count_desc',
  EXON_COUNT_ASC = 'exon_count_asc'
41 42
}

43 44 45
export type TranscriptsStatePerGene = {
  expandedIds: string[];
  expandedDownloadIds: string[];
46
  expandedMoreInfoIds: string[];
47 48
  filters: Filters;
  sortingRule: SortingRule;
49 50 51 52 53 54 55 56
};

export type GeneViewTranscriptsState = {
  [genomeId: string]: {
    [geneId: string]: TranscriptsStatePerGene;
  };
};

57 58 59
export type Filters = { [filter: string]: boolean };

const defaultStatePerGene: TranscriptsStatePerGene = {
60
  expandedIds: [],
61
  expandedDownloadIds: [],
62
  expandedMoreInfoIds: [],
63 64 65 66
  filters: {},
  sortingRule: SortingRule.DEFAULT
};

67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
export const setFilters =
  (filters: Filters): ThunkAction<void, any, null, Action<string>> =>
  (dispatch, getState: () => RootState) => {
    const state = getState();
    const activeGenomeId = getEntityViewerActiveGenomeId(state);
    const activeEntityId = getEntityViewerActiveEntityId(state);
    if (!activeGenomeId || !activeEntityId) {
      return;
    }
    dispatch(
      transcriptsSlice.actions.updateFilters({
        activeGenomeId,
        activeEntityId,
        filters
      })
    );
  };
84

85 86 87 88 89 90 91 92 93
export const setSortingRule =
  (sortingRule: SortingRule): ThunkAction<void, any, null, Action<string>> =>
  (dispatch, getState: () => RootState) => {
    const state = getState();
    const activeGenomeId = getEntityViewerActiveGenomeId(state);
    const activeEntityId = getEntityViewerActiveEntityId(state);
    if (!activeGenomeId || !activeEntityId) {
      return;
    }
94

95 96 97 98 99 100 101 102
    dispatch(
      transcriptsSlice.actions.updateSortingRule({
        activeGenomeId,
        activeEntityId,
        sortingRule
      })
    );
  };
103

104 105 106 107 108 109 110 111 112
export const toggleTranscriptInfo =
  (transcriptId: string): ThunkAction<void, any, null, Action<string>> =>
  (dispatch, getState: () => RootState) => {
    const state = getState();
    const activeGenomeId = getEntityViewerActiveGenomeId(state);
    const activeEntityId = getEntityViewerActiveEntityId(state);
    if (!activeGenomeId || !activeEntityId) {
      return;
    }
113

114 115 116 117 118 119
    const expandedIds = new Set<string>(getExpandedTranscriptIds(state));
    if (expandedIds.has(transcriptId)) {
      expandedIds.delete(transcriptId);
    } else {
      expandedIds.add(transcriptId);
    }
120

121 122 123 124 125 126 127 128
    dispatch(
      transcriptsSlice.actions.updateExpandedTranscripts({
        activeGenomeId,
        activeEntityId,
        expandedIds: [...expandedIds.values()]
      })
    );
  };
129

130 131 132 133 134 135 136 137 138
export const toggleTranscriptDownload =
  (transcriptId: string): ThunkAction<void, any, null, Action<string>> =>
  (dispatch, getState: () => RootState) => {
    const state = getState();
    const activeGenomeId = getEntityViewerActiveGenomeId(state);
    const activeEntityId = getEntityViewerActiveEntityId(state);
    if (!activeGenomeId || !activeEntityId) {
      return;
    }
139

140 141 142 143 144 145 146 147
    const expandedIds = new Set<string>(
      getExpandedTranscriptDownloadIds(state)
    );
    if (expandedIds.has(transcriptId)) {
      expandedIds.delete(transcriptId);
    } else {
      expandedIds.add(transcriptId);
    }
148

149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
    dispatch(
      transcriptsSlice.actions.updateExpandedDownloads({
        activeGenomeId,
        activeEntityId,
        expandedIds: [...expandedIds.values()]
      })
    );
  };

export const toggleTranscriptMoreInfo =
  (transcriptId: string): ThunkAction<void, any, null, Action<string>> =>
  (dispatch, getState: () => RootState) => {
    const state = getState();
    const activeGenomeId = getEntityViewerActiveGenomeId(state);
    const activeEntityId = getEntityViewerActiveEntityId(state);
    if (!activeGenomeId || !activeEntityId) {
      return;
    }

    const expandedIds = new Set<string>(
      getExpandedTranscriptMoreInfoIds(state)
    );
    if (expandedIds.has(transcriptId)) {
      expandedIds.delete(transcriptId);
    } else {
      expandedIds.add(transcriptId);
    }

    dispatch(
      transcriptsSlice.actions.updateExpandedMoreInfo({
        activeGenomeId,
        activeEntityId,
        expandedIds: [...expandedIds.values()]
      })
    );
  };
185 186 187

const ensureGenePresence = (
  state: GeneViewTranscriptsState,
188
  ids: { activeGenomeId: string; activeEntityId: string }
189
) => {
190
  const { activeGenomeId, activeEntityId } = ids;
191
  if (!state[activeGenomeId]) {
192 193
    return set(
      activeGenomeId,
194
      { [activeEntityId]: defaultStatePerGene },
195 196
      state
    );
197
  } else if (!state[activeGenomeId][activeEntityId]) {
198
    return set(
199
      `${activeGenomeId}.${activeEntityId}`,
200 201 202 203 204
      defaultStatePerGene,
      state
    );
  } else {
    return state;
205 206 207 208 209
  }
};

type ExpandedIdsPayload = {
  activeGenomeId: string;
210
  activeEntityId: string;
211 212 213
  expandedIds: string[];
};

214 215
type UpdateFiltersPayload = {
  activeGenomeId: string;
216
  activeEntityId: string;
217 218 219 220 221 222 223
  filters: {
    [filter: string]: boolean;
  };
};

type UpdateSortingRulePayload = {
  activeGenomeId: string;
224
  activeEntityId: string;
225 226 227
  sortingRule: SortingRule;
};

228 229 230 231 232 233 234 235
const transcriptsSlice = createSlice({
  name: 'entity-viewer-gene-view-transcripts',
  initialState: {} as GeneViewTranscriptsState,
  reducers: {
    updateExpandedTranscripts(
      state,
      action: PayloadAction<ExpandedIdsPayload>
    ) {
236
      const { activeGenomeId, activeEntityId, expandedIds } = action.payload;
237 238
      const updatedState = ensureGenePresence(state, action.payload);
      return set(
239
        `${activeGenomeId}.${activeEntityId}.expandedIds`,
240 241 242
        expandedIds,
        updatedState
      );
243 244
    },
    updateExpandedDownloads(state, action: PayloadAction<ExpandedIdsPayload>) {
245
      const { activeGenomeId, activeEntityId, expandedIds } = action.payload;
246 247
      const updatedState = ensureGenePresence(state, action.payload);
      return set(
248
        `${activeGenomeId}.${activeEntityId}.expandedDownloadIds`,
249 250 251
        expandedIds,
        updatedState
      );
252
    },
253 254 255 256 257 258 259 260 261
    updateExpandedMoreInfo(state, action: PayloadAction<ExpandedIdsPayload>) {
      const { activeGenomeId, activeEntityId, expandedIds } = action.payload;
      const updatedState = ensureGenePresence(state, action.payload);
      return set(
        `${activeGenomeId}.${activeEntityId}.expandedMoreInfoIds`,
        expandedIds,
        updatedState
      );
    },
262
    updateFilters(state, action: PayloadAction<UpdateFiltersPayload>) {
263
      const { activeGenomeId, activeEntityId, filters } = action.payload;
264 265
      const updatedState = ensureGenePresence(state, action.payload);
      return set(
266
        `${activeGenomeId}.${activeEntityId}.filters`,
267 268 269 270 271
        filters,
        updatedState
      );
    },
    updateSortingRule(state, action: PayloadAction<UpdateSortingRulePayload>) {
272
      const { activeGenomeId, activeEntityId, sortingRule } = action.payload;
273 274
      const updatedState = ensureGenePresence(state, action.payload);
      return set(
275
        `${activeGenomeId}.${activeEntityId}.sortingRule`,
276 277 278
        sortingRule,
        updatedState
      );
279 280 281 282 283
    }
  }
});

export default transcriptsSlice.reducer;