Merged PR 164: Clear the leftover TODOs
All checks were successful
continuous-integration/drone/push Build is passing

- Remove nullable type from container.properties.parentId
- Add Swal when trying to delete main container
- Moved default editor state to default.ts
- Moved default symbol model to default.ts
This commit is contained in:
Eric Nguyen 2022-08-22 15:03:46 +00:00
parent 66ea3b1b64
commit 29625dce28
6 changed files with 81 additions and 48 deletions

View file

@ -1,10 +1,9 @@
import { Dispatch, SetStateAction } from 'react';
import { IConfiguration } from '../../../Interfaces/IConfiguration';
import { ContainerModel } from '../../../Interfaces/IContainerModel';
import { fetchConfiguration } from '../../API/api';
import { IEditorState } from '../../../Interfaces/IEditorState';
import { LoadState } from './Load';
import { DEFAULT_MAINCONTAINER_PROPS } from '../../../utils/default';
import { GetDefaultEditorState } from '../../../utils/default';
export function NewEditor(
setEditorState: Dispatch<SetStateAction<IEditorState>>,
@ -13,38 +12,12 @@ export function NewEditor(
// Fetch the configuration from the API
fetchConfiguration()
.then((configuration: IConfiguration) => {
// Set the main container from the given properties of the API
const MainContainer = new ContainerModel(
null,
{
...DEFAULT_MAINCONTAINER_PROPS,
width: Number(configuration.MainContainer.Width),
height: Number(configuration.MainContainer.Height)
}
);
// Set the editor from the given properties of the API
const editorState: IEditorState = GetDefaultEditorState(configuration);
// Save the configuration and the new MainContainer
// and default the selected container to it
// TODO: Put this in default.ts
const editorState: IEditorState = {
configuration,
history:
[
{
LastAction: '',
MainContainer,
SelectedContainerId: MainContainer.properties.id,
TypeCounters: {},
Symbols: new Map(),
SelectedSymbolId: ''
}
],
historyCurrentStep: 0
};
setEditorState(editorState);
setLoaded(true);
}, (error) => {
// TODO: Implement an alert component
console.warn('[NewEditor] Could not fetch resource from API. Using default.', error);
setLoaded(true);
});

View file

@ -9,6 +9,7 @@ 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';
import Swal from 'sweetalert2';
/**
* Select a container
@ -64,7 +65,11 @@ export function DeleteContainer(
if (container === mainContainerClone ||
container.parent === undefined ||
container.parent === null) {
// TODO: Implement alert
Swal.fire({
title: 'Oops...',
text: 'Deleting the main container is not allowed!',
icon: 'error'
});
throw new Error('[DeleteContainer] Tried to delete the main container! Deleting the main container is not allowed!');
}

View file

@ -3,7 +3,7 @@ import { IConfiguration } from '../../../Interfaces/IConfiguration';
import { IContainerModel } from '../../../Interfaces/IContainerModel';
import { IHistoryState } from '../../../Interfaces/IHistoryState';
import { ISymbolModel } from '../../../Interfaces/ISymbolModel';
import { DEFAULT_SYMBOL_HEIGHT, DEFAULT_SYMBOL_WIDTH } from '../../../utils/default';
import { GetDefaultSymbolModel } from '../../../utils/default';
import { findContainerById } from '../../../utils/itertools';
import { restoreX } from '../../../utils/svg';
import { ApplyBehaviors } from '../Behaviors/Behaviors';
@ -31,16 +31,7 @@ export function AddSymbol(
UpdateCounters(newCounters, type);
const newSymbols = structuredClone(current.Symbols);
// TODO: Put this in default.ts as GetDefaultConfig
const newSymbol: ISymbolModel = {
id: `${name}-${newCounters[type]}`,
type: name,
config: structuredClone(symbolConfig),
x: 0,
width: symbolConfig.Width ?? DEFAULT_SYMBOL_WIDTH,
height: symbolConfig.Height ?? DEFAULT_SYMBOL_HEIGHT,
linkedContainers: new Set()
};
const newSymbol: ISymbolModel = GetDefaultSymbolModel(name, newCounters, type, symbolConfig);
newSymbol.x = restoreX(newSymbol.x, newSymbol.width, newSymbol.config.XPositionReference);
newSymbols.set(newSymbol.id, newSymbol);
@ -114,7 +105,7 @@ export function DeleteSymbol(
setHistoryCurrentStep(history.length - 1);
}
function UnlinkContainers(symbol: ISymbolModel, newMainContainer: IContainerModel) {
function UnlinkContainers(symbol: ISymbolModel, newMainContainer: IContainerModel): void {
symbol.linkedContainers.forEach((containerId) => {
const container = findContainerById(newMainContainer, containerId);

View file

@ -15,7 +15,7 @@ describe.concurrent('Elements sidebar', () => {
parent: null,
properties: {
id: 'main',
parentId: null,
parentId: '',
linkedSymbolId: '',
displayedText: 'main',
x: 0,

View file

@ -8,9 +8,8 @@ export default interface IContainerProperties {
/** id of the container */
id: string
// TODO: replace null by empty string
/** id of the parent container (null when there is no parent) */
parentId: string | null
parentId: string
/** id of the linked symbol ('' when there is no parent) */
linkedSymbolId: string

View file

@ -1,8 +1,11 @@
import { XPositionReference } from '../Enums/XPositionReference';
import { IAvailableContainer } from '../Interfaces/IAvailableContainer';
import { IAvailableSymbol } from '../Interfaces/IAvailableSymbol';
import { IConfiguration } from '../Interfaces/IConfiguration';
import { IContainerModel } from '../Interfaces/IContainerModel';
import { ContainerModel, IContainerModel } from '../Interfaces/IContainerModel';
import IContainerProperties from '../Interfaces/IContainerProperties';
import { IEditorState } from '../Interfaces/IEditorState';
import { ISymbolModel } from '../Interfaces/ISymbolModel';
/// CONTAINER DEFAULTS ///
@ -29,6 +32,38 @@ export const ENABLE_SHORTCUTS = true;
export const MAX_HISTORY = 200;
export const APPLY_BEHAVIORS_ON_CHILDREN = true;
/**
* Returns the default editor state given the configuration
*/
export const GetDefaultEditorState = (configuration: IConfiguration): IEditorState => {
const mainContainer = new ContainerModel(
null,
{
...DEFAULT_MAINCONTAINER_PROPS,
width: Number(configuration.MainContainer.Width),
height: Number(configuration.MainContainer.Height)
}
);
return {
configuration,
history: [
{
LastAction: '',
MainContainer: mainContainer,
SelectedContainerId: mainContainer.properties.id,
TypeCounters: {},
Symbols: new Map(),
SelectedSymbolId: ''
}
],
historyCurrentStep: 0
};
};
/**
* Default config when the API is not available
*/
export const DEFAULT_CONFIG: IConfiguration = {
AvailableContainers: [
{
@ -53,9 +88,12 @@ export const DEFAULT_CONFIG: IConfiguration = {
}
};
/**
* Default Main container properties
*/
export const DEFAULT_MAINCONTAINER_PROPS: IContainerProperties = {
id: 'main',
parentId: 'null',
parentId: '',
linkedSymbolId: '',
displayedText: 'main',
x: 0,
@ -72,6 +110,16 @@ export const DEFAULT_MAINCONTAINER_PROPS: IContainerProperties = {
}
};
/**
* Returns the default properties of a newly created container
* @param type Type of the container
* @param typeCount index of the container
* @param parent Parent of the container
* @param x horizontal offset
* @param y vertical offset
* @param containerConfig default config of the container sent by the API
* @returns {IContainerProperties} Default properties of a newly created container
*/
export const GetDefaultContainerProps = (
type: string,
typeCount: number,
@ -96,3 +144,20 @@ export const GetDefaultContainerProps = (
style: structuredClone(containerConfig.Style),
userData: structuredClone(containerConfig.UserData)
});
export const GetDefaultSymbolModel = (
name: string,
newCounters: Record<string, number>,
type: string,
symbolConfig: IAvailableSymbol
): ISymbolModel => {
return {
id: `${name}-${newCounters[type]}`,
type: name,
config: structuredClone(symbolConfig),
x: 0,
width: symbolConfig.Width ?? DEFAULT_SYMBOL_WIDTH,
height: symbolConfig.Height ?? DEFAULT_SYMBOL_HEIGHT,
linkedContainers: new Set()
};
};