Skip to content

Commit

Permalink
refactor(global): ♻️ fix code of reducer
Browse files Browse the repository at this point in the history
now checking of duplicate builder data and selected builder is placed in reducer

Ref #54
  • Loading branch information
PritamBag committed Jan 9, 2025
1 parent 3c50c1c commit 10afc2e
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 141 deletions.
77 changes: 9 additions & 68 deletions app/actions/builder.actions.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { AppBuilderData } from "../components/data/app-builder/AppBuilder.data";
import { EntityData } from "../components/data/entity/Entity.data";
import { BuilderState } from "../reducers/builder.reducer";
import { ADD_ATTRIBUTE, ADD_BUILDER_DATA, SELECTED_BUILDER } from "../types/builder.types";
import { ADD_ATTRIBUTE, ADD_OR_SELECT_BUILDER_DATA, SELECTED_BUILDER } from "../types/builder.types";
import { BuilderEntitySchema } from "../utils/UtilityFunction";

// export const setBuilderData_Case1 = (data: {[key: string]: string}) => (dispatch) => {
// dispatch({
Expand All @@ -9,77 +10,17 @@ import { ADD_ATTRIBUTE, ADD_BUILDER_DATA, SELECTED_BUILDER } from "../types/buil
// });
// };

// export const setBuilderData = (builderData: AppBuilderData, entityData: DynamicEntity) => {
// return {
// payload: { builderData, entityData },
// type : SET_BUILDER_DATA
// };
// };

// export const setBuilderData = (builderData: AppBuilderData, entityData: DynamicEntity, currentState: BuilderState) => {
// const existingBuilderIndex = currentState.appBuilderData.findIndex(
// (data) => data.builderId === builderData.builderId
// );

// eslint-disable-next-line etc/no-commented-out-code
// let updatedAppBuilderData;

// if (existingBuilderIndex > -1) {
// // Update existing builderData's entityData
// updatedAppBuilderData = currentState.appBuilderData.map((data, index) =>
// index === existingBuilderIndex ? { ...data, entityData } : data
// );
// } else {
// // Add new builderData to the state
// updatedAppBuilderData = [...currentState.appBuilderData, { ...builderData, entityData }];
// }

// return {
// payload: { appBuilderData: updatedAppBuilderData },
// type : SET_BUILDER_DATA
// };
// };

// export const addBuilderData = <TSchema>(builderData: AppBuilderData<TSchema>, entityData: EntityData<TSchema>, currentState: BuilderState) => {
// const existingBuilderIndex = currentState.appBuilderData.findIndex(
// (data) => data.builderId === builderData.builderId
// );

// eslint-disable-next-line etc/no-commented-out-code
// let updatedAppBuilderData;

// if (existingBuilderIndex > -1) {
// // Update existing builderData's entityData using the setter method
// updatedAppBuilderData = currentState.appBuilderData.map((data, index) => {
// if (index === existingBuilderIndex) {
// // Directly update the entityData using the setter
// data.setEntityData(entityData); // Use setter to update entityData
// }
// return data;
// });
// } else {
// // Add new builderData to the state and set entityData
// builderData.setEntityData(entityData);
// updatedAppBuilderData = [...currentState.appBuilderData, builderData];
// }

// return {
// payload: { appBuilderData: updatedAppBuilderData },
// type : SET_BUILDER_DATA
// };
// };

export const addBuilderData = <TSchema>(builderData: AppBuilderData<TSchema>) => {
export const selectBuilderData = (builderId: string) => {
return {
payload: { appBuilderData: builderData },
type : ADD_BUILDER_DATA
payload: { builderId },
type : SELECTED_BUILDER
};
};

export const selectBuilderData = (builderId: string) => {
export const addOrSelectBuilder = (entityID: number, entityData: EntityData<BuilderEntitySchema>, builderType: string) => {
return {
payload: { builderId },
type : SELECTED_BUILDER
payload: { builderType, entityData, entityID },
type : ADD_OR_SELECT_BUILDER_DATA
};
};

Expand Down
78 changes: 26 additions & 52 deletions app/components/AppBuilder.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { AppBuilderData } from "./data/app-builder/AppBuilder.data";
import ToolbarGroup from "./toolbar/ToolbarGroup";
import ToolBoxGroup from "./toolbox/ToolBoxGroup";
import ViewerGroup from "./viewer/ViewerGroup";
import { addBuilderData } from "../actions/builder.actions";
import { addOrSelectBuilder } from "../actions/builder.actions";
import { CLOSE, CLOSE_FUNCTIONALITY_COMMING_SOON, PRIMARY, SMALL } from "../constants/AppBuilder.constant";
import AppBuilderFactory from "../factory/AppBuilder.factory";
import ModuleClasses from "../styles/ModuleClasses";
Expand All @@ -25,20 +25,22 @@ export default function AppBuilder() {
const { state } = coreUseLocation();
const dispatch = useDispatch();

const appBuilderDataFromStore = useSelector((state: any) => state.BuilderOptions?.appBuilderData);
const { appBuilderData: appBuilderDataFromStore } = useSelector((state: any) => state.BuilderOptions);

const [entityData, setEntityData] = useState(null);
const [builderType, setBuilderType] = useState<string>(null);

const [selectedEntitySchema, setSelectedEntitySchema] = useState<BuilderEntitySchema>(null);
// const selectedEntitySchema = getBuilderEntitySchemaInterface(builderType);
const [selectedBuilder, setSelectedBuilder] = useState(null);
const [selectedViewerData, setSelectedViewerData] = useState(null);
const [selectedToolboxData, setSelectedToolboxData] = useState(null);
const [selectedToolbarData, setSelectedToolbarData] = useState(null);
// const [newBuilderDataInitialized, setNewBuilderDataInitialized] = useState(false);
const newBuilderDataInitialized = useRef(false);
const isSelectedBuilder = useRef(false);

/**
* Make the builder selected
*
* @param builderId
*/
function handleTabSelect(builderId: string){
if(builderId/** @todo check if builder id exist */){
// dispatch(selectBuilderData(builderId));
Expand All @@ -47,68 +49,40 @@ export default function AppBuilder() {
}
}

/**
*
* @todo we need to recheck the function since appBuilderData from store is not getting updated after dispatch
*/
const checkIfBuilderExist = () => {
// check builderData.id
const builderData = appBuilderDataFromStore?.find(
(_builderData) => {
// const _entityData: EntityData<BuilderEntitySchema> = _builderData.getEntityData();

return _builderData.builderType === builderType && _builderData?.entityData?.id === entityData?.id;
});

if(builderData) {
return true;
}

return false;
};

useEffect(() => {
if( !newBuilderDataInitialized.current && builderType && entityData && entityData?.id > 0 && !checkIfBuilderExist()){
const appBuilderData: AppBuilderData<BuilderEntitySchema> = AppBuilderFactory.getAppBuilderData<BuilderEntitySchema, AppBuilderData<BuilderEntitySchema>>(builderType, entityData);

// Object.setPrototypeOf(appBuilderData, AppBuilderData.prototype);
appBuilderData.setSelected(true);
dispatch(addBuilderData(appBuilderData));
// setNewBuilderDataInitialized(true);
newBuilderDataInitialized.current = true;
}
}, [builderType, entityData, dispatch]);
/* In this useEffect we will set the builderType and entityData */

useEffect(() => {
/** When location state value changes we will set the selected builder info */
if(!builderType || !entityData || entityData?.id <= 0 ){

// when builderType, entityData or entityData not greater than 0

if (state && (state as AppBuilderState).data && (state as AppBuilderState).builderType){
/* when state and state has data and builderType */
const typedState = state as AppBuilderState;

setBuilderType(typedState.builderType);
setEntityData(typedState.data);
// setSelectedEntitySchema(getBuilderEntitySchemaInterface(typedState.builderType));
} else {
/* when state is undefined or state has no data or builderType */
const currentBuilderData: AppBuilderData<any> = appBuilderDataFromStore[0];

// Object.setPrototypeOf(currentBuilderData, AppBuilderData.prototype);
setBuilderType(currentBuilderData?.getBuilderType());
setEntityData(currentBuilderData?.getEntityData());
// setSelectedEntitySchema(getBuilderEntitySchemaInterface(currentBuilderData?.getBuilderType()));
}
} else {
// if( !newBuilderDataInitialized.current && builderType && entityData && entityData?.id > 0 && !checkIfBuilderExist()){
// const appBuilderData: AppBuilderData<BuilderEntitySchema> = AppBuilderFactory.getAppBuilderData<BuilderEntitySchema, AppBuilderData<BuilderEntitySchema>>(builderType, entityData);

// // Object.setPrototypeOf(appBuilderData, AppBuilderData.prototype);
// appBuilderData.setSelected(true);
// dispatch(addBuilderData(appBuilderData));
// // setNewBuilderDataInitialized(true);
// newBuilderDataInitialized.current = true;
// }
// do nothing
}
}, [state, appBuilderDataFromStore, builderType, entityData]);

useEffect(() => {
/* In this useEffect we will set the selected builder data */
if(!isSelectedBuilder.current && builderType && entityData && entityData?.id > 0){
/* if builder is not initialized and builderType and entityData is valid */
dispatch(addOrSelectBuilder(entityData.id, entityData, builderType));
isSelectedBuilder.current = true;
} else {
// do nothing
}
}, [isSelectedBuilder, builderType, entityData, dispatch]);

useEffect(() => {
if(selectedBuilder) {
Expand All @@ -119,7 +93,7 @@ export default function AppBuilder() {
setSelectedViewerData(_selectedBuilder.getViewers());
setSelectedToolboxData(_selectedBuilder.getToolBoxes());
setSelectedToolbarData(_selectedBuilder.getToolbars());
} else{
} else {
setSelectedBuilder(
appBuilderDataFromStore?.find(
/** @todo type casting is not valid we need to fix and remove set prototype */
Expand Down
3 changes: 2 additions & 1 deletion app/components/data/viewer/json/JsonViewer.data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export class JsonViewerData<TSchema> extends ViewerData<TSchema>{
}

prepareViewerContent(entityData: EntityData<TSchema>): void {
this.viewerContent = entityData?.getSchema();
Object.setPrototypeOf(entityData, EntityData.prototype);
this.viewerContent = entityData.getSchema();
}
}
69 changes: 50 additions & 19 deletions app/reducers/builder.reducer.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { AppBuilderData } from "../components/data/app-builder/AppBuilder.data";
import { ADD_BUILDER_DATA, SELECTED_BUILDER, SET_BUILDER_DATA } from "../types/builder.types";
import { EntityData } from "../components/data/entity/Entity.data";
import AppBuilderFactory from "../factory/AppBuilder.factory";
import { ADD_OR_SELECT_BUILDER_DATA, SET_BUILDER_DATA } from "../types/builder.types";
import { BuilderEntitySchema } from "../utils/UtilityFunction";

export interface BuilderState {
/** @todo Entity schema needs to be created and placed in place of any in the following line */
Expand All @@ -16,34 +19,62 @@ const builderOptions = (state = initialState, action: {type: string, payload: an
appBuilderData: action.payload.appBuilderData,
};

case ADD_BUILDER_DATA:
/** make all others builder not selected */
case ADD_OR_SELECT_BUILDER_DATA:
// eslint-disable-next-line no-case-declarations
const builderData = state.appBuilderData;
let found = false;
// eslint-disable-next-line no-case-declarations
const updatedBuilderData = state.appBuilderData;

updatedBuilderData.forEach((builder) => {
Object.setPrototypeOf(builder, AppBuilderData.prototype);
const entityData = builder.getEntityData();

Object.setPrototypeOf(entityData, EntityData.prototype);

builderData.forEach((builder) => {
builder.setSelected(false);
const payloadEnityData = action.payload.entityData;

if(entityData.getId() === payloadEnityData?.id) {
builder.setSelected(true);
found = true;
} else {
builder.setSelected(false);
}
});

if(!state.appBuilderData.find((_builderData) => {
return _builderData.getEntityData().getId() === action.payload.appBuilderData?.entityData?.id;
})){
builderData.push(action.payload.appBuilderData);
if(!found){
const { builderType, entityData } = action.payload;
const newBuilder: AppBuilderData<BuilderEntitySchema> = AppBuilderFactory.getAppBuilderData<BuilderEntitySchema, AppBuilderData<BuilderEntitySchema>>(builderType, entityData);

Object.setPrototypeOf(newBuilder, AppBuilderData.prototype);
newBuilder.setSelected(true);

updatedBuilderData.push(newBuilder);
}
return {
...state,
appBuilderData: builderData
};

case SELECTED_BUILDER:
return {
...state,
appBuilderData: state.appBuilderData.map((builderData) => {
builderData.setSelected(builderData.builderId === action.payload.builderId);
return builderData;
}),
appBuilderData: JSON.parse(JSON.stringify(updatedBuilderData)),
};

// case SELECTED_BUILDER:
// return {
// ...state,
// appBuilderData: state.appBuilderData.map((builderData) => {
// Object.setPrototypeOf(builderData, AppBuilderData.prototype);
// // builderData.setSelected(builderData.builderId === action.payload.builderId);
// if (builderData.builderId === action.payload.builderId) {
// // Only set selected to true if it's not already true
// if (!builderData.isSelected()) {
// builderData.setSelected(true);
// }
// } else {
// // Set all other builders to unselected
// builderData.setSelected(false);
// }
// return builderData;
// }),
// };

default:
return state;
}
Expand Down
3 changes: 2 additions & 1 deletion app/types/builder.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@ export const BUILDER_DATA_CASE_1 = "BUILDER_DATA_CASE_1";
export const SET_BUILDER_DATA = "SET_BUILDER_DATA";

export const ADD_BUILDER_DATA = "ADD_BUILDER_DATA";
export const SELECTED_BUILDER = "SELECTED_BUILDER";
export const SELECTED_BUILDER = "SELECTED_BUILDER";
export const ADD_OR_SELECT_BUILDER_DATA = "ADD_OR_SELECT_BUILDER_DATA";

0 comments on commit 10afc2e

Please sign in to comment.