Merged PR 163: Remove the static form + rename some components for clarity
All checks were successful
continuous-integration/drone/push Build is passing

The static form is hard to maintain so I am removing it + rename some components for clarity + moved some utils files
This commit is contained in:
Eric Nguyen 2022-08-22 14:37:25 +00:00
parent 7e3ccdee99
commit 66ea3b1b64
21 changed files with 150 additions and 523 deletions

View file

@ -1,329 +0,0 @@
import { Dispatch, SetStateAction } from 'react';
import { IHistoryState } from '../../Interfaces/IHistoryState';
import { IConfiguration } from '../../Interfaces/IConfiguration';
import { ContainerModel, IContainerModel } from '../../Interfaces/IContainerModel';
import { findContainerById, MakeIterator } from '../../utils/itertools';
import { getCurrentHistory, UpdateCounters } from './Editor';
import { AddMethod } from '../../Enums/AddMethod';
import { IAvailableContainer } from '../../Interfaces/IAvailableContainer';
import { GetDefaultContainerProps, DEFAULTCHILDTYPE_ALLOW_CYCLIC, DEFAULTCHILDTYPE_MAX_DEPTH } from '../../utils/default';
import { ApplyBehaviors } from './Behaviors/Behaviors';
import { ISymbolModel } from '../../Interfaces/ISymbolModel';
/**
* Select a container
* @param container Selected container
*/
export function SelectContainer(
containerId: string,
fullHistory: IHistoryState[],
historyCurrentStep: number,
setHistory: Dispatch<SetStateAction<IHistoryState[]>>,
setHistoryCurrentStep: Dispatch<SetStateAction<number>>
): void {
const history = getCurrentHistory(fullHistory, historyCurrentStep);
const current = history[history.length - 1];
history.push({
LastAction: `Select ${containerId}`,
MainContainer: structuredClone(current.MainContainer),
SelectedContainerId: containerId,
TypeCounters: Object.assign({}, current.TypeCounters),
Symbols: structuredClone(current.Symbols),
SelectedSymbolId: current.SelectedSymbolId
});
setHistory(history);
setHistoryCurrentStep(history.length - 1);
}
/**
* Delete a container
* @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
*/
export function DeleteContainer(
containerId: string,
fullHistory: IHistoryState[],
historyCurrentStep: number,
setHistory: Dispatch<SetStateAction<IHistoryState[]>>,
setHistoryCurrentStep: Dispatch<SetStateAction<number>>
): void {
const history = getCurrentHistory(fullHistory, historyCurrentStep);
const current = history[history.length - 1];
const mainContainerClone: IContainerModel = structuredClone(current.MainContainer);
const container = findContainerById(mainContainerClone, containerId);
if (container === undefined) {
throw new Error(`[DeleteContainer] Tried to delete a container that is not present in the main container: ${containerId}`);
}
if (container === mainContainerClone ||
container.parent === undefined ||
container.parent === null) {
// TODO: Implement alert
throw new Error('[DeleteContainer] Tried to delete the main container! Deleting the main container is not allowed!');
}
if (container === null || container === undefined) {
throw new Error('[DeleteContainer] Container model was not found among children of the main container!');
}
const newSymbols = structuredClone(current.Symbols)
UnlinkSymbol(newSymbols, container);
const index = container.parent.children.indexOf(container);
if (index > -1) {
container.parent.children.splice(index, 1);
} else {
throw new Error('[DeleteContainer] Could not find container among parent\'s children');
}
// Select the previous container
// or select the one above
const SelectedContainer = findContainerById(mainContainerClone, current.SelectedContainerId) ??
container.parent.children.at(index - 1) ??
container.parent;
const SelectedContainerId = SelectedContainer.properties.id;
history.push({
LastAction: `Delete ${containerId}`,
MainContainer: mainContainerClone,
SelectedContainerId,
TypeCounters: Object.assign({}, current.TypeCounters),
Symbols: newSymbols,
SelectedSymbolId: current.SelectedSymbolId
});
setHistory(history);
setHistoryCurrentStep(history.length - 1);
}
function UnlinkSymbol(symbols: Map<string, ISymbolModel>, container: IContainerModel): void {
const it = MakeIterator(container);
for (const child of it) {
const symbol = symbols.get(child.properties.linkedSymbolId);
if (symbol === undefined) {
continue;
}
symbol.linkedContainers.delete(child.properties.id);
}
}
/**
* Add a new container to a selected container
* @param type The type of container
* @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(
type: string,
selected: IContainerModel | undefined,
configuration: IConfiguration,
fullHistory: IHistoryState[],
historyCurrentStep: number,
setHistory: Dispatch<SetStateAction<IHistoryState[]>>,
setHistoryCurrentStep: Dispatch<SetStateAction<number>>
): void {
if (selected === null ||
selected === undefined) {
return;
}
const parent = selected;
AddContainer(
parent.children.length,
type,
parent.properties.id,
configuration,
fullHistory,
historyCurrentStep,
setHistory,
setHistoryCurrentStep
);
}
/**
* 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
* @param setHistory State setter of History
* @param setHistoryCurrentStep State setter of the current step
* @returns void
*/
export function AddContainer(
index: number,
type: string,
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
);
if (parentClone === null || parentClone === undefined) {
throw new Error('[AddContainer] Container model was not found among children of the main container!');
}
let x = containerConfig.DefaultX ?? 0;
const y = containerConfig.DefaultY ?? 0;
x = ApplyAddMethod(index, containerConfig, parentClone, x);
const defaultProperties = GetDefaultContainerProps(
type,
count,
parentClone,
x,
y,
containerConfig
);
// Create the container
const newContainer = new ContainerModel(
parentClone,
defaultProperties,
[],
{
type
}
);
ApplyBehaviors(newContainer, current.Symbols);
// And push it the the parent children
if (index === parentClone.children.length) {
parentClone.children.push(newContainer);
} else {
parentClone.children.splice(index, 0, newContainer);
}
InitializeDefaultChild(configuration, containerConfig, newContainer, newCounters);
// 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);
}
function InitializeDefaultChild(
configuration: IConfiguration,
containerConfig: IAvailableContainer,
newContainer: ContainerModel,
newCounters: Record<string, number>
): void {
if (containerConfig.DefaultChildType === undefined) {
return;
}
let currentConfig = configuration.AvailableContainers
.find(option => option.Type === containerConfig.DefaultChildType);
let parent = newContainer;
let depth = 0;
const seen = new Set<string>([containerConfig.Type]);
while (currentConfig !== undefined &&
depth <= DEFAULTCHILDTYPE_MAX_DEPTH
) {
if (!DEFAULTCHILDTYPE_ALLOW_CYCLIC && seen.has(currentConfig.Type)) {
return;
}
seen.add(currentConfig.Type);
const x = currentConfig.DefaultX ?? 0;
const y = currentConfig.DefaultY ?? 0;
UpdateCounters(newCounters, currentConfig.Type);
const count = newCounters[currentConfig.Type];
const defaultChildProperties = GetDefaultContainerProps(
currentConfig.Type,
count,
parent,
x,
y,
currentConfig
);
// Create the container
const newChildContainer = new ContainerModel(
parent,
defaultChildProperties,
[],
{
type: currentConfig.Type
}
);
// And push it the the parent children
parent.children.push(newChildContainer);
// iterate
depth++;
parent = newChildContainer;
currentConfig = configuration.AvailableContainers
.find(option => option.Type === (currentConfig as IAvailableContainer).DefaultChildType);
}
}
/**
* Returns a new offset by applying an Add method (append, insert etc.)
* See AddMethod
* @param index Index of the container
* @param containerConfig Configuration of a container
* @param parent Parent container
* @param x Additionnal offset
* @returns New offset
*/
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);
if (lastChild !== undefined) {
x += (lastChild.properties.x + lastChild.properties.width);
}
}
return x;
}