Skip to content

Commit

Permalink
feat: logic for nav section instances processing
Browse files Browse the repository at this point in the history
  • Loading branch information
devcatalin committed Oct 25, 2021
1 parent 991b0d9 commit d8655a9
Show file tree
Hide file tree
Showing 7 changed files with 134 additions and 9 deletions.
2 changes: 0 additions & 2 deletions src/models/appstate.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import {HelmChart, HelmValuesFile} from '@models/helm';
import {FileEntry} from './fileentry';
import {K8sResource} from './k8sresource';
import {NavSectionInstance} from './navsection';
import {MonoklePlugin} from './plugin';

/**
Expand Down Expand Up @@ -105,7 +104,6 @@ interface AppState {
diffContent?: string;
plugins: MonoklePlugin[];
resourceRefsProcessingOptions: ResourceRefsProcessingOptions;
navSectionInstancesById: Record<string, NavSectionInstance>;
}

export type {
Expand Down
31 changes: 24 additions & 7 deletions src/models/navsection.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import {RootState} from '@redux/store';
import React from 'react';

export type NavSectionItemCustomComponentProps<ItemType> = {
Expand Down Expand Up @@ -36,8 +37,10 @@ interface NavSectionItemGroup<ItemType> {

export interface NavSection<ItemType, ScopeType = any> {
name: string;
useScope: () => ScopeType;
id: string;
subsectionNames?: string[];
useScope: () => ScopeType;
getScope: (state: RootState) => ScopeType;
getItems?: (scope: ScopeType) => ItemType[];
getGroups?: (scope: ScopeType) => NavSectionItemGroup<ItemType>[];
isLoading?: (scope: ScopeType, items: ItemType[]) => boolean;
Expand All @@ -49,7 +52,7 @@ export interface NavSection<ItemType, ScopeType = any> {

export interface NavSectionItemInstance {
name: string;
identifier: string;
id: string;
isSelected: boolean;
isHighlighted: boolean;
isVisible: boolean;
Expand All @@ -61,14 +64,28 @@ export interface NavSectionItemInstance {
export interface NavSectionItemGroupInstance {
groupId: string;
groupName: string;
groupItems: NavSectionItemInstance[];
groupItemIds: string[];
}

export interface NavSectionInstance {
name: string;
subsectionNames?: string[];
items: NavSectionItemInstance[];
groups: NavSectionItemGroupInstance[];
isLoading: boolean;
isVisible: boolean;
itemIds?: string[];
groupIds?: NavSectionItemGroupInstance[];
isLoading?: boolean;
isVisible?: boolean;
isInitialized?: boolean;
}

export interface NavSectionState {
instanceMap: Record<string, NavSectionInstance>;
itemInstanceMap: Record<string, NavSectionItemInstance>;
itemGroupInstanceMap: Record<string, NavSectionItemGroupInstance>;
scopeMap: Record<string, Record<string, any>>;
}

export interface UpdateNavSectionStatePayload {
instances: NavSectionInstance[];
itemInstances: NavSectionItemInstance[];
scopeMap: Record<string, Record<string, any>>;
}
5 changes: 5 additions & 0 deletions src/navsections/navSectionMap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,12 @@ const register = (navSection: NavSection<any, any>) => {
NavSectionMap[navSection.name] = navSection;
};

const getAll = () => {
return Object.values(NavSectionMap);
};

export default {
getAll,
getByName,
register,
};
71 changes: 71 additions & 0 deletions src/navsections/navSectionProcessor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import {NavSectionInstance, NavSectionItemInstance} from '@models/navsection';
import store from '@redux/store';
import {shallowEqual} from 'react-redux';
import {updateNavSectionState} from '@redux/reducers/navSection';
import navSectionMap from './navSectionMap';

store.subscribe(() => {
const state = store.getState();
const navSectionInstances: NavSectionInstance[] = [];
const navSectionItemInstances: NavSectionItemInstance[] = [];
const nextScopeMap: Record<string, Record<string, any>> = {};

navSectionMap.getAll().forEach(navSection => {
const previousScope = state.navSection.scopeMap[navSection.id];
const nextScope = navSection.getScope(state);
if (shallowEqual(previousScope, nextScope)) {
return;
}
nextScopeMap[navSection.id] = nextScope;
const itemHandler = navSection.itemHandler;
let itemInstances: NavSectionItemInstance[] | undefined;
let rawItems: any[] = [];
if (itemHandler) {
rawItems = (navSection.getItems && navSection.getItems(nextScope)) || [];
itemInstances = rawItems?.map(rawItem => {
return {
name: itemHandler.getName(rawItem),
id: itemHandler.getIdentifier(rawItem),
isSelected: Boolean(itemHandler.isSelected && itemHandler.isSelected(rawItem, nextScope)),
isHighlighted: Boolean(itemHandler.isHighlighted && itemHandler.isHighlighted(rawItem, nextScope)),
isVisible: Boolean(itemHandler.isVisible && itemHandler.isVisible(rawItem, nextScope)),
isDirty: Boolean(itemHandler.isDirty && itemHandler.isDirty(rawItem, nextScope)),
isDisabled: Boolean(itemHandler.isDisabled && itemHandler.isDisabled(rawItem, nextScope)),
shouldScrollIntoView: Boolean(
itemHandler.shouldScrollIntoView && itemHandler.shouldScrollIntoView(rawItem, nextScope)
),
};
});
}
const navSectionInstance: NavSectionInstance = {
name: navSection.name,
subsectionNames: navSection.subsectionNames,
itemIds: itemInstances?.map(i => i.id),
isLoading: Boolean(navSection.isLoading && navSection.isLoading(nextScope, rawItems)),
isVisible: Boolean(navSection.isVisible && navSection.isVisible(nextScope, rawItems)),
isInitialized: Boolean(navSection.isInitialized && navSection.isInitialized(nextScope, rawItems)),
};
navSectionInstances.push(navSectionInstance);
if (itemInstances) {
navSectionItemInstances.push(...itemInstances);
}
});

// TODO: compute everything from useNavSection hook

const updatedNavSectionItemInstances = navSectionItemInstances.filter(nextItemInstance => {
return !shallowEqual(state.navSection.itemInstanceMap[nextItemInstance.id], nextItemInstance);
});

const updatedNavSectionInstances = navSectionInstances.filter(nextInstance => {
return !shallowEqual(state.navSection.instanceMap[nextInstance.name], nextInstance);
});

store.dispatch(
updateNavSectionState({
instances: updatedNavSectionInstances,
itemInstances: updatedNavSectionItemInstances,
scopeMap: nextScopeMap,
})
);
});
9 changes: 9 additions & 0 deletions src/redux/initialState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import electronStore from '@utils/electronStore';
import {ObjectNavigator, NavigatorSection, NavigatorSubSection} from '@models/navigator';
import {ResourceKindHandlers} from '@src/kindhandlers';
import navSectionNames from '@constants/navSectionNames';
import {NavSectionState} from '@models/navsection';

const NAV_K8S_RESOURCES_SECTIONS_ORDER = navSectionNames.representation[navSectionNames.K8S_RESOURCES];

Expand Down Expand Up @@ -162,10 +163,18 @@ const initialUiState: UiState = {
resetLayout: false,
};

const initialNavSectionState: NavSectionState = {
instanceMap: {},
itemInstanceMap: {},
itemGroupInstanceMap: {},
scopeMap: {},
};

export default {
alert: initialAlertState,
config: initialAppConfigState,
main: initialAppState,
logs: initialLogsState,
ui: initialUiState,
navSection: initialNavSectionState,
};
23 changes: 23 additions & 0 deletions src/redux/reducers/navSection.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import {createSlice, Draft, PayloadAction} from '@reduxjs/toolkit';
import initialState from '@redux/initialState';
import {NavSectionState, UpdateNavSectionStatePayload} from '@models/navsection';

export const navSectionSlice = createSlice({
name: 'navSection',
initialState: initialState.navSection,
reducers: {
updateNavSectionState: (state: Draft<NavSectionState>, action: PayloadAction<UpdateNavSectionStatePayload>) => {
const {instances, itemInstances, scopeMap} = action.payload;
instances.forEach(instance => {
state.instanceMap[instance.name] = instance;
});
itemInstances.forEach(itemInstance => {
state.itemInstanceMap[itemInstance.id];
});
state.scopeMap = scopeMap;
},
},
});

export const {updateNavSectionState} = navSectionSlice.actions;
export default navSectionSlice.reducer;
2 changes: 2 additions & 0 deletions src/redux/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {configSlice} from './reducers/appConfig';
import {alertSlice} from './reducers/alert';
import {logsSlice} from './reducers/logs';
import {uiSlice} from './reducers/ui';
import {navSectionSlice} from './reducers/navSection';

const store = configureStore({
reducer: {
Expand All @@ -15,6 +16,7 @@ const store = configureStore({
alert: alertSlice.reducer,
logs: logsSlice.reducer,
ui: uiSlice.reducer,
navSection: navSectionSlice.reducer,
},
middleware: getDefaultMiddleware => [forwardToMain, ...getDefaultMiddleware().concat(logger)],
});
Expand Down

0 comments on commit d8655a9

Please sign in to comment.