Merged PR 173: Implements API methods through right click + more (read desc)
- Implements API methods through right click - Refactor events - Refactor usage of setHistory and setHistoryCurrentStep into a single function - Update ContainerOperations documentations - Added AddContainers in order to add multiple containers + refactor AddContainer to use it - Fix regression - Fix AddContainer at index
This commit is contained in:
parent
79c6874240
commit
57e6c9a156
20 changed files with 652 additions and 291 deletions
|
@ -1,4 +1,3 @@
|
|||
import { Dispatch, SetStateAction } from 'react';
|
||||
import { IHistoryState } from '../../../Interfaces/IHistoryState';
|
||||
import { IConfiguration } from '../../../Interfaces/IConfiguration';
|
||||
import { ContainerModel, IContainerModel } from '../../../Interfaces/IContainerModel';
|
||||
|
@ -16,14 +15,13 @@ import { PropertyType } from '../../../Enums/PropertyType';
|
|||
/**
|
||||
* Select a container
|
||||
* @param container Selected container
|
||||
* @returns New history
|
||||
*/
|
||||
export function SelectContainer(
|
||||
containerId: string,
|
||||
fullHistory: IHistoryState[],
|
||||
historyCurrentStep: number,
|
||||
setHistory: Dispatch<SetStateAction<IHistoryState[]>>,
|
||||
setHistoryCurrentStep: Dispatch<SetStateAction<number>>
|
||||
): void {
|
||||
historyCurrentStep: number
|
||||
): IHistoryState[] {
|
||||
const history = GetCurrentHistory(fullHistory, historyCurrentStep);
|
||||
const current = history[history.length - 1];
|
||||
|
||||
|
@ -35,8 +33,7 @@ export function SelectContainer(
|
|||
symbols: structuredClone(current.symbols),
|
||||
selectedSymbolId: current.selectedSymbolId
|
||||
});
|
||||
setHistory(history);
|
||||
setHistoryCurrentStep(history.length - 1);
|
||||
return history;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -44,16 +41,13 @@ export function SelectContainer(
|
|||
* @param containerId containerId of the container to delete
|
||||
* @param fullHistory History of the editor
|
||||
* @param historyCurrentStep Current step
|
||||
* @param setHistory State setter for History
|
||||
* @param setHistoryCurrentStep State setter for current step
|
||||
* @returns New history
|
||||
*/
|
||||
export function DeleteContainer(
|
||||
containerId: string,
|
||||
fullHistory: IHistoryState[],
|
||||
historyCurrentStep: number,
|
||||
setHistory: Dispatch<SetStateAction<IHistoryState[]>>,
|
||||
setHistoryCurrentStep: Dispatch<SetStateAction<number>>
|
||||
): void {
|
||||
historyCurrentStep: number
|
||||
): IHistoryState[] {
|
||||
const history = GetCurrentHistory(fullHistory, historyCurrentStep);
|
||||
const current = history[history.length - 1];
|
||||
|
||||
|
@ -80,7 +74,7 @@ export function DeleteContainer(
|
|||
}
|
||||
|
||||
const newSymbols = structuredClone(current.symbols);
|
||||
UnlinkSymbol(newSymbols, container);
|
||||
UnlinkContainerFromSymbols(newSymbols, container);
|
||||
|
||||
const index = container.parent.children.indexOf(container);
|
||||
if (index > -1) {
|
||||
|
@ -108,10 +102,21 @@ export function DeleteContainer(
|
|||
symbols: newSymbols,
|
||||
selectedSymbolId: current.selectedSymbolId
|
||||
});
|
||||
setHistory(history);
|
||||
setHistoryCurrentStep(history.length - 1);
|
||||
return history;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the next container that will be selected
|
||||
* after the selectedContainer is removed.
|
||||
* If the selected container is removed, select the sibling before,
|
||||
* If there is no sibling, select the parent,
|
||||
*
|
||||
* @param mainContainerClone Main container
|
||||
* @param selectedContainerId Current selected container
|
||||
* @param parent Parent of the selected/deleted container
|
||||
* @param index Index of the selected/deleted container
|
||||
* @returns {IContainerModel} Next selected container
|
||||
*/
|
||||
function GetSelectedContainerOnDelete(
|
||||
mainContainerClone: IContainerModel,
|
||||
selectedContainerId: string,
|
||||
|
@ -125,7 +130,13 @@ function GetSelectedContainerOnDelete(
|
|||
return newSelectedContainerId;
|
||||
}
|
||||
|
||||
function UnlinkSymbol(symbols: Map<string, ISymbolModel>, container: IContainerModel): void {
|
||||
/**
|
||||
* Unlink a container and its children to symbols
|
||||
* (used when deleting a container)
|
||||
* @param symbols Symbols to update
|
||||
* @param container Container to unlink
|
||||
*/
|
||||
function UnlinkContainerFromSymbols(symbols: Map<string, ISymbolModel>, container: IContainerModel): void {
|
||||
const it = MakeIterator(container);
|
||||
for (const child of it) {
|
||||
const symbol = symbols.get(child.properties.linkedSymbolId);
|
||||
|
@ -142,8 +153,6 @@ function UnlinkSymbol(symbols: Map<string, ISymbolModel>, container: IContainerM
|
|||
* @param configuration Configuration of the App
|
||||
* @param fullHistory History of the editor
|
||||
* @param historyCurrentStep Current step
|
||||
* @param setHistory State setter for History
|
||||
* @param setHistoryCurrentStep State setter for current step
|
||||
* @returns void
|
||||
*/
|
||||
export function AddContainerToSelectedContainer(
|
||||
|
@ -151,28 +160,153 @@ export function AddContainerToSelectedContainer(
|
|||
selected: IContainerModel | undefined,
|
||||
configuration: IConfiguration,
|
||||
fullHistory: IHistoryState[],
|
||||
historyCurrentStep: number,
|
||||
setHistory: Dispatch<SetStateAction<IHistoryState[]>>,
|
||||
setHistoryCurrentStep: Dispatch<SetStateAction<number>>
|
||||
): void {
|
||||
historyCurrentStep: number
|
||||
): IHistoryState[] | null {
|
||||
if (selected === null ||
|
||||
selected === undefined) {
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
|
||||
const parent = selected;
|
||||
AddContainer(
|
||||
return AddContainer(
|
||||
parent.children.length,
|
||||
type,
|
||||
parent.properties.id,
|
||||
configuration,
|
||||
fullHistory,
|
||||
historyCurrentStep,
|
||||
setHistory,
|
||||
setHistoryCurrentStep
|
||||
historyCurrentStep
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and add a new container at `index` in children of parent of `parentId`
|
||||
* @param index Index where to insert to the new container
|
||||
* @param type Type of container
|
||||
* @param parentId Parent in which to insert the new container
|
||||
* @param configuration Configuration of the app
|
||||
* @param fullHistory History of the editor
|
||||
* @param historyCurrentStep Current step
|
||||
* @returns void
|
||||
*/
|
||||
export function AddContainers(
|
||||
index: number,
|
||||
types: string[],
|
||||
parentId: string,
|
||||
configuration: IConfiguration,
|
||||
fullHistory: IHistoryState[],
|
||||
historyCurrentStep: number
|
||||
): IHistoryState[] {
|
||||
const history = GetCurrentHistory(fullHistory, historyCurrentStep);
|
||||
const current = history[history.length - 1];
|
||||
|
||||
// Deep clone the main container for the history
|
||||
const clone: IContainerModel = structuredClone(current.mainContainer);
|
||||
|
||||
// Find the parent in the clone
|
||||
const parentClone: IContainerModel | undefined = FindContainerById(
|
||||
clone, parentId
|
||||
);
|
||||
|
||||
if (parentClone === null || parentClone === undefined) {
|
||||
throw new Error('[AddContainer] Container model was not found among children of the main container!');
|
||||
}
|
||||
|
||||
// Deep clone the counters
|
||||
const newCounters = Object.assign({}, current.typeCounters);
|
||||
|
||||
// containerIds is used for logging purpose (see setHistory below)
|
||||
const containerIds: string[] = [];
|
||||
|
||||
// Iterate over the containers
|
||||
types.forEach((type, typeIndex) => {
|
||||
// Get the preset properties from the API
|
||||
const containerConfig = configuration.AvailableContainers
|
||||
.find(option => option.Type === type);
|
||||
|
||||
if (containerConfig === undefined) {
|
||||
throw new Error(`[AddContainer] Object type not found. Found: ${type}`);
|
||||
}
|
||||
|
||||
// Default margin
|
||||
const left: number = containerConfig.Margin?.left ?? 0;
|
||||
const bottom: number = containerConfig.Margin?.bottom ?? 0;
|
||||
const top: number = containerConfig.Margin?.top ?? 0;
|
||||
const right: number = containerConfig.Margin?.right ?? 0;
|
||||
|
||||
// Default coordinates
|
||||
let x = containerConfig.DefaultX ?? 0;
|
||||
let y = containerConfig.DefaultY ?? 0;
|
||||
let width = containerConfig.Width ?? containerConfig.MaxWidth ?? containerConfig.MinWidth ?? parentClone.properties.width;
|
||||
let height = containerConfig.Height ?? parentClone.properties.height;
|
||||
|
||||
({ x, y, width, height } = ApplyMargin(x, y, width, height, left, bottom, top, right));
|
||||
|
||||
// Apply an add method (append or insert/replace)
|
||||
x = ApplyAddMethod(index + typeIndex, containerConfig, parentClone, x);
|
||||
|
||||
// Set the counter of the object type in order to assign an unique id
|
||||
UpdateCounters(newCounters, type);
|
||||
const count = newCounters[type];
|
||||
|
||||
const defaultProperties = GetDefaultContainerProps(
|
||||
type,
|
||||
count,
|
||||
parentClone,
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
height,
|
||||
containerConfig
|
||||
);
|
||||
|
||||
// Create the container
|
||||
const newContainer = new ContainerModel(
|
||||
parentClone,
|
||||
defaultProperties,
|
||||
[],
|
||||
{
|
||||
type
|
||||
}
|
||||
);
|
||||
|
||||
// Add it to the parent
|
||||
if (index === parentClone.children.length) {
|
||||
parentClone.children.push(newContainer);
|
||||
} else {
|
||||
parentClone.children.splice(index, 0, newContainer);
|
||||
}
|
||||
|
||||
/// Handle behaviors here ///
|
||||
|
||||
// Initialize default children of the container
|
||||
InitializeDefaultChild(configuration, containerConfig, newContainer, newCounters);
|
||||
|
||||
// Apply the behaviors (flex, rigid, anchor)
|
||||
ApplyBehaviors(newContainer, current.symbols);
|
||||
|
||||
// Then, apply the behaviors on its siblings (mostly for flex)
|
||||
ApplyBehaviorsOnSiblings(newContainer, current.symbols);
|
||||
|
||||
// Sort the parent children by x
|
||||
UpdateParentChildrenList(parentClone);
|
||||
|
||||
// Add to the list of container id for logging purpose
|
||||
containerIds.push(newContainer.properties.id);
|
||||
});
|
||||
|
||||
// Update the state
|
||||
history.push({
|
||||
lastAction: `Add [${containerIds.join(', ')}] in ${parentClone.properties.id}`,
|
||||
mainContainer: clone,
|
||||
selectedContainerId: parentClone.properties.id,
|
||||
typeCounters: newCounters,
|
||||
symbols: structuredClone(current.symbols),
|
||||
selectedSymbolId: current.selectedSymbolId
|
||||
});
|
||||
|
||||
return history;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and add a new container at `index` in children of parent of `parentId`
|
||||
* @param index Index where to insert to the new container
|
||||
|
@ -183,7 +317,7 @@ export function AddContainerToSelectedContainer(
|
|||
* @param historyCurrentStep Current step
|
||||
* @param setHistory State setter of History
|
||||
* @param setHistoryCurrentStep State setter of the current step
|
||||
* @returns void
|
||||
* @returns new history
|
||||
*/
|
||||
export function AddContainer(
|
||||
index: number,
|
||||
|
@ -191,104 +325,55 @@ export function AddContainer(
|
|||
parentId: string,
|
||||
configuration: IConfiguration,
|
||||
fullHistory: IHistoryState[],
|
||||
historyCurrentStep: number,
|
||||
setHistory: Dispatch<SetStateAction<IHistoryState[]>>,
|
||||
setHistoryCurrentStep: Dispatch<SetStateAction<number>>
|
||||
): void {
|
||||
const history = GetCurrentHistory(fullHistory, historyCurrentStep);
|
||||
const current = history[history.length - 1];
|
||||
|
||||
// Get the preset properties from the API
|
||||
const containerConfig = configuration.AvailableContainers
|
||||
.find(option => option.Type === type);
|
||||
|
||||
if (containerConfig === undefined) {
|
||||
throw new Error(`[AddContainer] Object type not found. Found: ${type}`);
|
||||
}
|
||||
|
||||
// Set the counter of the object type in order to assign an unique id
|
||||
const newCounters = Object.assign({}, current.typeCounters);
|
||||
UpdateCounters(newCounters, type);
|
||||
const count = newCounters[type];
|
||||
|
||||
// Create maincontainer model
|
||||
const clone: IContainerModel = structuredClone(current.mainContainer);
|
||||
|
||||
// Find the parent
|
||||
const parentClone: IContainerModel | undefined = FindContainerById(
|
||||
clone, parentId
|
||||
historyCurrentStep: number
|
||||
): IHistoryState[] {
|
||||
// just call AddContainers with an array on a single element
|
||||
return AddContainers(
|
||||
index,
|
||||
[type],
|
||||
parentId,
|
||||
configuration,
|
||||
fullHistory,
|
||||
historyCurrentStep
|
||||
);
|
||||
|
||||
if (parentClone === null || parentClone === undefined) {
|
||||
throw new Error('[AddContainer] Container model was not found among children of the main container!');
|
||||
}
|
||||
const left: number = containerConfig.Margin?.left ?? 0;
|
||||
const bottom: number = containerConfig.Margin?.bottom ?? 0;
|
||||
const top: number = containerConfig.Margin?.top ?? 0;
|
||||
const right: number = containerConfig.Margin?.right ?? 0;
|
||||
|
||||
let x = containerConfig.DefaultX ?? 0;
|
||||
let y = containerConfig.DefaultY ?? 0;
|
||||
let width = containerConfig.Width ?? containerConfig.MaxWidth ?? containerConfig.MinWidth ?? parentClone.properties.width;
|
||||
let height = containerConfig.Height ?? parentClone.properties.height;
|
||||
|
||||
({ x, y, width, height } = ApplyMargin(x, y, width, height, left, bottom, top, right));
|
||||
|
||||
x = ApplyAddMethod(index, containerConfig, parentClone, x);
|
||||
|
||||
const defaultProperties = GetDefaultContainerProps(
|
||||
type,
|
||||
count,
|
||||
parentClone,
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
height,
|
||||
containerConfig
|
||||
);
|
||||
|
||||
// Create the container
|
||||
const newContainer = new ContainerModel(
|
||||
parentClone,
|
||||
defaultProperties,
|
||||
[],
|
||||
{
|
||||
type
|
||||
}
|
||||
);
|
||||
|
||||
parentClone.children.push(newContainer);
|
||||
UpdateParentChildrenList(parentClone);
|
||||
|
||||
InitializeDefaultChild(configuration, containerConfig, newContainer, newCounters);
|
||||
|
||||
ApplyBehaviors(newContainer, current.symbols);
|
||||
|
||||
ApplyBehaviorsOnSiblings(newContainer, current.symbols);
|
||||
|
||||
// Update the state
|
||||
history.push({
|
||||
lastAction: `Add ${newContainer.properties.id} in ${parentClone.properties.id}`,
|
||||
mainContainer: clone,
|
||||
selectedContainerId: parentClone.properties.id,
|
||||
typeCounters: newCounters,
|
||||
symbols: structuredClone(current.symbols),
|
||||
selectedSymbolId: current.selectedSymbolId
|
||||
});
|
||||
setHistory(history);
|
||||
setHistoryCurrentStep(history.length - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort the parent children by x
|
||||
* @param parentClone The clone used for the sort
|
||||
* @returns void
|
||||
*/
|
||||
function UpdateParentChildrenList(parentClone: IContainerModel | null | undefined): void {
|
||||
if (parentClone === null || parentClone === undefined) {
|
||||
return;
|
||||
}
|
||||
const children = parentClone.children;
|
||||
parentClone.children.sort(
|
||||
(a, b) => TransformX(a.properties.x, a.properties.width, a.properties.xPositionReference) -
|
||||
TransformX(b.properties.x, b.properties.width, b.properties.xPositionReference)
|
||||
(a, b) => {
|
||||
const xA = TransformX(a.properties.x, a.properties.width, a.properties.xPositionReference);
|
||||
const xB = TransformX(b.properties.x, b.properties.width, b.properties.xPositionReference);
|
||||
if (xA < xB) {
|
||||
return -1;
|
||||
}
|
||||
if (xB < xA) {
|
||||
return 1;
|
||||
}
|
||||
// xA = xB
|
||||
const indexA = children.indexOf(a);
|
||||
const indexB = children.indexOf(b);
|
||||
return indexA - indexB;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the children of the container
|
||||
* @param configuration Current configuration of the app
|
||||
* @param containerConfig The new container config used to read the default child type
|
||||
* @param newContainer The new container to initialize its default children
|
||||
* @param newCounters Type counter used for unique ids
|
||||
* @returns
|
||||
*/
|
||||
function InitializeDefaultChild(
|
||||
configuration: IConfiguration,
|
||||
containerConfig: IAvailableContainer,
|
||||
|
@ -368,12 +453,18 @@ function InitializeDefaultChild(
|
|||
* @param x Additionnal offset
|
||||
* @returns New offset
|
||||
*/
|
||||
function ApplyAddMethod(index: number, containerConfig: IAvailableContainer, parent: IContainerModel, x: number): number {
|
||||
function ApplyAddMethod(
|
||||
index: number,
|
||||
containerConfig: IAvailableContainer,
|
||||
parent: IContainerModel,
|
||||
x: number
|
||||
): number {
|
||||
if (index > 0 && (
|
||||
containerConfig.AddMethod === undefined ||
|
||||
containerConfig.AddMethod === AddMethod.Append)) {
|
||||
// Append method (default)
|
||||
const lastChild: IContainerModel | undefined = parent.children.at(index - 1);
|
||||
const lastChild: IContainerModel | undefined = parent.children
|
||||
.at(index - 1);
|
||||
|
||||
if (lastChild !== undefined) {
|
||||
x += (lastChild.properties.x + lastChild.properties.width);
|
||||
|
@ -394,10 +485,8 @@ export function OnPropertyChange(
|
|||
type: PropertyType = PropertyType.Simple,
|
||||
selected: IContainerModel | undefined,
|
||||
fullHistory: IHistoryState[],
|
||||
historyCurrentStep: number,
|
||||
setHistory: Dispatch<SetStateAction<IHistoryState[]>>,
|
||||
setHistoryCurrentStep: Dispatch<SetStateAction<number>>
|
||||
): void {
|
||||
historyCurrentStep: number
|
||||
): IHistoryState[] {
|
||||
const history = GetCurrentHistory(fullHistory, historyCurrentStep);
|
||||
const current = history[history.length - 1];
|
||||
|
||||
|
@ -423,8 +512,7 @@ export function OnPropertyChange(
|
|||
symbols: structuredClone(current.symbols),
|
||||
selectedSymbolId: current.selectedSymbolId
|
||||
});
|
||||
setHistory(history);
|
||||
setHistoryCurrentStep(history.length - 1);
|
||||
return history;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -465,6 +553,13 @@ function SetContainer(
|
|||
UpdateParentChildrenList(container.parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign the property to a container depending on the type
|
||||
* @param container Container in which the property will be applied to
|
||||
* @param key Key/Id of the property
|
||||
* @param value Value of the property
|
||||
* @param type Type of the property
|
||||
*/
|
||||
function AssignProperty(container: ContainerModel, key: string, value: string | number | boolean, type: PropertyType): void {
|
||||
switch (type) {
|
||||
case PropertyType.Style:
|
||||
|
@ -477,7 +572,12 @@ function AssignProperty(container: ContainerModel, key: string, value: string |
|
|||
(container.properties as any)[key] = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the margin property
|
||||
*/
|
||||
function SetMargin(): void {
|
||||
// We need to detect change in order to apply transformation to the width and height
|
||||
// Knowing the current margin is not enough as we dont keep the original width and height
|
||||
const oldMarginValue: number = (container.properties.margin as any)[key];
|
||||
const diff = Number(value) - oldMarginValue;
|
||||
switch (key) {
|
||||
|
@ -500,6 +600,14 @@ function AssignProperty(container: ContainerModel, key: string, value: string |
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Link a symbol to a container
|
||||
* @param containerId Container id
|
||||
* @param oldSymbolId Old Symbol id
|
||||
* @param newSymbolId New Symbol id
|
||||
* @param symbols Current list of symbols
|
||||
* @returns
|
||||
*/
|
||||
function LinkSymbol(
|
||||
containerId: string,
|
||||
oldSymbolId: string,
|
||||
|
@ -519,10 +627,18 @@ function LinkSymbol(
|
|||
newSymbol.linkedContainers.add(containerId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterate over the siblings of newContainer and apply the behaviors
|
||||
* @param newContainer
|
||||
* @param symbols
|
||||
* @returns
|
||||
*/
|
||||
function ApplyBehaviorsOnSiblings(newContainer: ContainerModel, symbols: Map<string, ISymbolModel>): void {
|
||||
if (newContainer.parent === null || newContainer.parent === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
newContainer.parent.children.filter(container => newContainer !== container).forEach(container => ApplyBehaviors(container, symbols));
|
||||
newContainer.parent.children
|
||||
.filter(container => newContainer !== container)
|
||||
.forEach(container => ApplyBehaviors(container, symbols));
|
||||
}
|
||||
|
|
131
src/Components/Editor/Actions/ContextMenuActions.ts
Normal file
131
src/Components/Editor/Actions/ContextMenuActions.ts
Normal file
|
@ -0,0 +1,131 @@
|
|||
import Swal from 'sweetalert2';
|
||||
import { AddMethod } from '../../../Enums/AddMethod';
|
||||
import { IAction } from '../../../Interfaces/IAction';
|
||||
import { IConfiguration } from '../../../Interfaces/IConfiguration';
|
||||
import { IContainerModel } from '../../../Interfaces/IContainerModel';
|
||||
import { IHistoryState } from '../../../Interfaces/IHistoryState';
|
||||
import { ISetContainerListRequest } from '../../../Interfaces/ISetContainerListRequest';
|
||||
import { ISetContainerListResponse } from '../../../Interfaces/ISetContainerListResponse';
|
||||
import { FindContainerById } from '../../../utils/itertools';
|
||||
import { SetContainerList } from '../../API/api';
|
||||
import { AddContainers, DeleteContainer } from './ContainerOperations';
|
||||
|
||||
export function GetAction(
|
||||
action: IAction,
|
||||
currentState: IHistoryState,
|
||||
configuration: IConfiguration,
|
||||
history: IHistoryState[],
|
||||
historyCurrentStep: number,
|
||||
setNewHistory: (newHistory: IHistoryState[]) => void
|
||||
): (target: HTMLElement) => void {
|
||||
return (target: HTMLElement) => {
|
||||
const id = target.id;
|
||||
const container = FindContainerById(currentState.mainContainer, id);
|
||||
|
||||
if (container === undefined) {
|
||||
Swal.fire({
|
||||
title: 'Error',
|
||||
text: 'No container was selected on right click',
|
||||
icon: 'error'
|
||||
});
|
||||
throw new Error(`[API:${action.Action}] No container was selected`);
|
||||
}
|
||||
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
const request: ISetContainerListRequest = {
|
||||
Container: container,
|
||||
Action: action.Action,
|
||||
ApplicationState: currentState
|
||||
};
|
||||
/* eslint-enable */
|
||||
|
||||
SetContainerList(request)
|
||||
.then((response: ISetContainerListResponse) => {
|
||||
HandleSetContainerList(
|
||||
action,
|
||||
container,
|
||||
response,
|
||||
configuration,
|
||||
history,
|
||||
historyCurrentStep,
|
||||
setNewHistory
|
||||
);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function HandleSetContainerList(
|
||||
action: IAction,
|
||||
selectedContainer: IContainerModel,
|
||||
response: ISetContainerListResponse,
|
||||
configuration: IConfiguration,
|
||||
history: IHistoryState[],
|
||||
historyCurrentStep: number,
|
||||
setNewHistory: (newHistory: IHistoryState[]) => void
|
||||
): void {
|
||||
switch (action.AddingBehavior) {
|
||||
case AddMethod.Append:
|
||||
setNewHistory(
|
||||
AddContainers(
|
||||
selectedContainer.children.length,
|
||||
response.Containers.map(container => container.properties.type),
|
||||
selectedContainer.properties.id,
|
||||
configuration,
|
||||
history,
|
||||
historyCurrentStep
|
||||
));
|
||||
break;
|
||||
case AddMethod.Insert:
|
||||
break;
|
||||
case AddMethod.Replace:
|
||||
setNewHistory(
|
||||
HandleReplace(
|
||||
selectedContainer,
|
||||
response,
|
||||
configuration,
|
||||
history,
|
||||
historyCurrentStep
|
||||
)
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function HandleReplace(
|
||||
selectedContainer: IContainerModel,
|
||||
response: ISetContainerListResponse,
|
||||
configuration: IConfiguration,
|
||||
history: IHistoryState[],
|
||||
historyCurrentStep: number
|
||||
): IHistoryState[] {
|
||||
if (selectedContainer.parent === undefined || selectedContainer.parent === null) {
|
||||
throw new Error('[ReplaceContainer] Cannot replace a container that does not exists');
|
||||
}
|
||||
|
||||
const index = selectedContainer.parent.children.indexOf(selectedContainer);
|
||||
|
||||
const types = response.Containers.map(container => container.properties.type);
|
||||
const newHistoryBeforeDelete = AddContainers(
|
||||
index + 1,
|
||||
types,
|
||||
selectedContainer.properties.parentId,
|
||||
configuration,
|
||||
history,
|
||||
historyCurrentStep
|
||||
);
|
||||
|
||||
const newHistoryAfterDelete = DeleteContainer(
|
||||
selectedContainer.properties.id,
|
||||
newHistoryBeforeDelete,
|
||||
newHistoryBeforeDelete.length - 1
|
||||
);
|
||||
|
||||
// Remove AddContainers from history
|
||||
newHistoryAfterDelete.splice(newHistoryAfterDelete.length - 2, 1);
|
||||
|
||||
// Rename the last action by Replace
|
||||
newHistoryAfterDelete[newHistoryAfterDelete.length - 1].lastAction =
|
||||
`Replace ${selectedContainer.properties.id} by [${types.join(', ')}]`;
|
||||
|
||||
return newHistoryAfterDelete;
|
||||
}
|
|
@ -13,10 +13,8 @@ export function AddSymbol(
|
|||
name: string,
|
||||
configuration: IConfiguration,
|
||||
fullHistory: IHistoryState[],
|
||||
historyCurrentStep: number,
|
||||
setHistory: Dispatch<SetStateAction<IHistoryState[]>>,
|
||||
setHistoryCurrentStep: Dispatch<SetStateAction<number>>
|
||||
): void {
|
||||
historyCurrentStep: number
|
||||
): IHistoryState[] {
|
||||
const history = GetCurrentHistory(fullHistory, historyCurrentStep);
|
||||
const current = history[history.length - 1];
|
||||
|
||||
|
@ -44,17 +42,14 @@ export function AddSymbol(
|
|||
symbols: newSymbols,
|
||||
selectedSymbolId: newSymbol.id
|
||||
});
|
||||
setHistory(history);
|
||||
setHistoryCurrentStep(history.length - 1);
|
||||
return history;
|
||||
}
|
||||
|
||||
export function SelectSymbol(
|
||||
symbolId: string,
|
||||
fullHistory: IHistoryState[],
|
||||
historyCurrentStep: number,
|
||||
setHistory: Dispatch<SetStateAction<IHistoryState[]>>,
|
||||
setHistoryCurrentStep: Dispatch<SetStateAction<number>>
|
||||
): void {
|
||||
historyCurrentStep: number
|
||||
): IHistoryState[] {
|
||||
const history = GetCurrentHistory(fullHistory, historyCurrentStep);
|
||||
const current = history[history.length - 1];
|
||||
|
||||
|
@ -66,17 +61,14 @@ export function SelectSymbol(
|
|||
symbols: structuredClone(current.symbols),
|
||||
selectedSymbolId: symbolId
|
||||
});
|
||||
setHistory(history);
|
||||
setHistoryCurrentStep(history.length - 1);
|
||||
return history;
|
||||
}
|
||||
|
||||
export function DeleteSymbol(
|
||||
symbolId: string,
|
||||
fullHistory: IHistoryState[],
|
||||
historyCurrentStep: number,
|
||||
setHistory: Dispatch<SetStateAction<IHistoryState[]>>,
|
||||
setHistoryCurrentStep: Dispatch<SetStateAction<number>>
|
||||
): void {
|
||||
historyCurrentStep: number
|
||||
): IHistoryState[] {
|
||||
const history = GetCurrentHistory(fullHistory, historyCurrentStep);
|
||||
const current = history[history.length - 1];
|
||||
|
||||
|
@ -89,7 +81,7 @@ export function DeleteSymbol(
|
|||
|
||||
const newMainContainer = structuredClone(current.mainContainer);
|
||||
|
||||
UnlinkContainers(symbol, newMainContainer);
|
||||
UnlinkSymbolFromContainers(symbol, newMainContainer);
|
||||
|
||||
newSymbols.delete(symbolId);
|
||||
|
||||
|
@ -101,13 +93,17 @@ export function DeleteSymbol(
|
|||
symbols: newSymbols,
|
||||
selectedSymbolId: symbolId
|
||||
});
|
||||
setHistory(history);
|
||||
setHistoryCurrentStep(history.length - 1);
|
||||
return history;
|
||||
}
|
||||
|
||||
function UnlinkContainers(symbol: ISymbolModel, newMainContainer: IContainerModel): void {
|
||||
/**
|
||||
* Unlink a symbol to a container and its children
|
||||
* @param symbol Symbol to remove
|
||||
* @param root Container and its children to remove a symbol from
|
||||
*/
|
||||
function UnlinkSymbolFromContainers(symbol: ISymbolModel, root: IContainerModel): void {
|
||||
symbol.linkedContainers.forEach((containerId) => {
|
||||
const container = FindContainerById(newMainContainer, containerId);
|
||||
const container = FindContainerById(root, containerId);
|
||||
|
||||
if (container === undefined) {
|
||||
return;
|
||||
|
@ -127,10 +123,8 @@ export function OnPropertyChange(
|
|||
key: string,
|
||||
value: string | number | boolean,
|
||||
fullHistory: IHistoryState[],
|
||||
historyCurrentStep: number,
|
||||
setHistory: Dispatch<SetStateAction<IHistoryState[]>>,
|
||||
setHistoryCurrentStep: Dispatch<SetStateAction<number>>
|
||||
): void {
|
||||
historyCurrentStep: number
|
||||
): IHistoryState[] {
|
||||
const history = GetCurrentHistory(fullHistory, historyCurrentStep);
|
||||
const current = history[history.length - 1];
|
||||
|
||||
|
@ -166,6 +160,5 @@ export function OnPropertyChange(
|
|||
symbols: newSymbols,
|
||||
selectedSymbolId: symbol.id
|
||||
});
|
||||
setHistory(history);
|
||||
setHistoryCurrentStep(history.length - 1);
|
||||
return history;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue