Commit 2d1673e8 authored by Alejandro Celaya's avatar Alejandro Celaya Committed by Alejandro Celaya

Migrate groups store module to TypeScript

parent 666058a4
import { createSelector } from 'reselect'; import { createSelector } from 'reselect';
import type { Group } from '../../../types/api';
import { createStoreModule, makeAction } from '../create-store'; import { createStoreModule, makeAction } from '../create-store';
import { sessionModule } from './session'; import { sessionModule } from './session';
import type { State as SessionState } from './session';
/** type GroupID = Group['id'];
* @typedef {import('../../../types/api').Group} Group
* @typedef {import('./session').State} SessionState
*/
const initialState = { export type State = {
/** /**
* When there are entries, only `groups` with `id`s included in this list * When there are entries, only `groups` with `id`s included in this list
* of will be displayed in the sidebar. * of will be displayed in the sidebar.
*
* @type {Group["id"][]|null}
*/ */
filteredGroupIds: null, filteredGroupIds: GroupID[] | null;
/** /** List of groups. */
* List of groups. groups: Group[];
* @type {Group[]} /** ID of currently selected group. */
*/ focusedGroupId: string | null;
groups: [], };
/** const initialState: State = {
* ID of currently selected group. filteredGroupIds: null,
* @type {string|null} groups: [],
*/
focusedGroupId: null, focusedGroupId: null,
}; };
/** @typedef {typeof initialState} State */
const reducers = { const reducers = {
/** FILTER_GROUPS(state: State, action: { filteredGroupIds: string[] }) {
* @param {State} state
* @param {{ filteredGroupIds: string[] }} action
*/
FILTER_GROUPS(state, action) {
if (!action.filteredGroupIds?.length) { if (!action.filteredGroupIds?.length) {
return { return {
filteredGroupIds: null, filteredGroupIds: null,
...@@ -64,11 +54,7 @@ const reducers = { ...@@ -64,11 +54,7 @@ const reducers = {
}; };
}, },
/** FOCUS_GROUP(state: State, action: { id: string }) {
* @param {State} state
* @param {{ id: string }} action
*/
FOCUS_GROUP(state, action) {
const group = state.groups.find(g => g.id === action.id); const group = state.groups.find(g => g.id === action.id);
if (!group) { if (!group) {
console.error( console.error(
...@@ -79,11 +65,7 @@ const reducers = { ...@@ -79,11 +65,7 @@ const reducers = {
return { focusedGroupId: action.id }; return { focusedGroupId: action.id };
}, },
/** LOAD_GROUPS(state: State, action: { groups: Group[] }) {
* @param {State} state
* @param {{ groups: Group[] }} action
*/
LOAD_GROUPS(state, action) {
const groups = action.groups; const groups = action.groups;
let focusedGroupId = state.focusedGroupId; let focusedGroupId = state.focusedGroupId;
...@@ -120,87 +102,67 @@ function clearGroups() { ...@@ -120,87 +102,67 @@ function clearGroups() {
/** /**
* Set filtered groups. * Set filtered groups.
*
* @param {Group["id"][]} filteredGroupIds
*/ */
function filterGroups(filteredGroupIds) { function filterGroups(filteredGroupIds: GroupID[]) {
return makeAction(reducers, 'FILTER_GROUPS', { filteredGroupIds }); return makeAction(reducers, 'FILTER_GROUPS', { filteredGroupIds });
} }
/** /**
* Set the current focused group. * Set the current focused group.
*
* @param {string} id
*/ */
function focusGroup(id) { function focusGroup(id: string) {
return makeAction(reducers, 'FOCUS_GROUP', { id }); return makeAction(reducers, 'FOCUS_GROUP', { id });
} }
/** /**
* Update the set of loaded groups. * Update the set of loaded groups.
*
* @param {Group[]} groups
*/ */
function loadGroups(groups) { function loadGroups(groups: Group[]) {
return makeAction(reducers, 'LOAD_GROUPS', { groups }); return makeAction(reducers, 'LOAD_GROUPS', { groups });
} }
/** /**
* Return the currently focused group. * Return the currently focused group.
*
* @param {State} state
*/ */
function focusedGroup(state) { function focusedGroup(state: State): Group | null {
if (!state.focusedGroupId) { if (!state.focusedGroupId) {
return null; return null;
} }
return getGroup(state, state.focusedGroupId); return getGroup(state, state.focusedGroupId) ?? null;
} }
/** /**
* Return the current focused group ID or `null`. * Return the current focused group ID or `null`.
*
* @param {State} state
*/ */
function focusedGroupId(state) { function focusedGroupId(state: State) {
return state.focusedGroupId; return state.focusedGroupId;
} }
/** /**
* Return the list of all groups, ignoring any filter present. * Return the list of all groups, ignoring any filter present.
*
* @param {State} state
*/ */
function allGroups(state) { function allGroups(state: State) {
return state.groups; return state.groups;
} }
/** /**
* Return a list of groups filtered by any values in `filteredGroupIds` * Return a list of groups filtered by any values in `filteredGroupIds`
*
* @param {State} state
*/ */
function filteredGroups(state) { function filteredGroups(state: State) {
if (!state.filteredGroupIds) { if (!state.filteredGroupIds) {
return state.groups; return state.groups;
} }
return state.groups.filter(g => state.filteredGroupIds?.includes(g.id)); return state.groups.filter(g => state.filteredGroupIds?.includes(g.id));
} }
/** function filteredGroupIds(state: State) {
* @param {State} state
*/
function filteredGroupIds(state) {
return state.filteredGroupIds; return state.filteredGroupIds;
} }
/** /**
* Return the group with the given ID. * Return the group with the given ID.
*
* @param {State} state
* @param {string} id
*/ */
function getGroup(state, id) { function getGroup(state: State, id: string): Group | undefined {
return state.groups.find(g => g.id === id); return state.groups.find(g => g.id === id);
} }
...@@ -208,8 +170,7 @@ function getGroup(state, id) { ...@@ -208,8 +170,7 @@ function getGroup(state, id) {
* Return groups the user isn't a member of that are scoped to the URI. * Return groups the user isn't a member of that are scoped to the URI.
*/ */
const getFeaturedGroups = createSelector( const getFeaturedGroups = createSelector(
/** @param {State} state */ (state: State) => filteredGroups(state),
state => filteredGroups(state),
groups => groups.filter(group => !group.isMember && group.isScopedToUri) groups => groups.filter(group => !group.isMember && group.isScopedToUri)
); );
...@@ -219,25 +180,24 @@ const getFeaturedGroups = createSelector( ...@@ -219,25 +180,24 @@ const getFeaturedGroups = createSelector(
* menu is permanent. * menu is permanent.
*/ */
const getInScopeGroups = createSelector( const getInScopeGroups = createSelector(
/** @param {State} state */ (state: State) => filteredGroups(state),
state => filteredGroups(state),
groups => groups.filter(g => g.isScopedToUri) groups => groups.filter(g => g.isScopedToUri)
); );
// Selectors that receive root state. // Selectors that receive root state.
/** type RootState = {
* @typedef {{ groups: State, session: SessionState }} RootState groups: State;
*/ session: SessionState;
};
/** /**
* Return groups the logged in user is a member of. * Return groups the logged-in user is a member of.
*/ */
const getMyGroups = createSelector( const getMyGroups = createSelector(
/** @param {RootState} rootState */ (rootState: RootState) => filteredGroups(rootState.groups),
rootState => filteredGroups(rootState.groups), (rootState: RootState) =>
/** @param {RootState} rootState */ sessionModule.selectors.isLoggedIn(rootState.session),
rootState => sessionModule.selectors.isLoggedIn(rootState.session),
(groups, loggedIn) => { (groups, loggedIn) => {
// If logged out, the Public group still has isMember set to true so only // If logged out, the Public group still has isMember set to true so only
// return groups with membership in logged in state. // return groups with membership in logged in state.
...@@ -252,12 +212,9 @@ const getMyGroups = createSelector( ...@@ -252,12 +212,9 @@ const getMyGroups = createSelector(
* Return groups that don't show up in Featured and My Groups. * Return groups that don't show up in Featured and My Groups.
*/ */
const getCurrentlyViewingGroups = createSelector( const getCurrentlyViewingGroups = createSelector(
/** @param {RootState} rootState */ (rootState: RootState) => filteredGroups(rootState.groups),
rootState => filteredGroups(rootState.groups), (rootState: RootState) => getMyGroups(rootState),
/** @param {RootState} rootState */ (rootState: RootState) => getFeaturedGroups(rootState.groups),
rootState => getMyGroups(rootState),
/** @param {RootState} rootState */
rootState => getFeaturedGroups(rootState.groups),
(allGroups, myGroups, featuredGroups) => { (allGroups, myGroups, featuredGroups) => {
return allGroups.filter( return allGroups.filter(
g => !myGroups.includes(g) && !featuredGroups.includes(g) g => !myGroups.includes(g) && !featuredGroups.includes(g)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment