diff --git a/src/Components/Editor/Actions/ContextMenuActions.ts b/src/Components/Editor/Actions/ContextMenuActions.ts index a4c99db..1545359 100644 --- a/src/Components/Editor/Actions/ContextMenuActions.ts +++ b/src/Components/Editor/Actions/ContextMenuActions.ts @@ -39,7 +39,7 @@ export function GetAction( Container: container, PreviousContainer: prev, NextContainer: next, - Action: action.Action, + Action: action, ApplicationState: currentState }; /* eslint-enable */ @@ -59,7 +59,7 @@ export function GetAction( }; } -function GetPreviousAndNextSiblings(container: IContainerModel): { prev: IContainerModel | undefined; next: IContainerModel | undefined; } { +function GetPreviousAndNextSiblings(container: IContainerModel): { prev: IContainerModel | undefined, next: IContainerModel | undefined } { let prev; let next; if (container.parent !== undefined && @@ -85,7 +85,8 @@ function HandleSetContainerList( historyCurrentStep: number, setNewHistory: (newHistory: IHistoryState[]) => void ): void { - switch (action.AddingBehavior) { + const addingBehavior = response.AddingBehavior ?? action.AddingBehavior; + switch (addingBehavior) { case AddMethod.Append: setNewHistory( AddContainers( @@ -98,7 +99,7 @@ function HandleSetContainerList( )); break; case AddMethod.Insert: - break; + throw new Error('Not yet supported'); case AddMethod.Replace: setNewHistory( HandleReplace( @@ -110,6 +111,25 @@ function HandleSetContainerList( ) ); break; + case AddMethod.ReplaceParent: + if (selectedContainer.parent === undefined || selectedContainer.parent === null) { + Swal.fire({ + title: 'Error', + text: 'The selected container has not parent to replace', + icon: 'error' + }); + return; + } + setNewHistory( + HandleReplace( + selectedContainer.parent, + response, + configuration, + history, + historyCurrentStep + ) + ); + break; } } diff --git a/src/Components/Menu/Menu.tsx b/src/Components/Menu/Menu.tsx index 0a15cc9..cd92f5c 100644 --- a/src/Components/Menu/Menu.tsx +++ b/src/Components/Menu/Menu.tsx @@ -88,7 +88,7 @@ export function Menu(props: IMenuProps): JSX.Element { actions.forEach((action, index) => { children.push( action.action(target)} />); diff --git a/src/Enums/AddMethod.ts b/src/Enums/AddMethod.ts index 0c308ba..ce67ed0 100644 --- a/src/Enums/AddMethod.ts +++ b/src/Enums/AddMethod.ts @@ -8,5 +8,6 @@ export enum AddMethod { Append, Insert, - Replace + Replace, + ReplaceParent } diff --git a/src/Interfaces/ISetContainerListRequest.ts b/src/Interfaces/ISetContainerListRequest.ts index 3c03913..2a413a7 100644 --- a/src/Interfaces/ISetContainerListRequest.ts +++ b/src/Interfaces/ISetContainerListRequest.ts @@ -1,10 +1,11 @@ +import { IAction } from './IAction'; import { IContainerModel } from './IContainerModel'; import { IHistoryState } from './IHistoryState'; /* eslint-disable @typescript-eslint/naming-convention */ export interface ISetContainerListRequest { /** Name of the action declared in the API */ - Action: string + Action: IAction /** Selected container */ Container: IContainerModel diff --git a/src/Interfaces/ISetContainerListResponse.ts b/src/Interfaces/ISetContainerListResponse.ts index 96cdccf..4c147fa 100644 --- a/src/Interfaces/ISetContainerListResponse.ts +++ b/src/Interfaces/ISetContainerListResponse.ts @@ -1,6 +1,8 @@ /* eslint-disable @typescript-eslint/naming-convention */ +import { AddMethod } from '../Enums/AddMethod'; import { IAvailableContainer } from './IAvailableContainer'; export interface ISetContainerListResponse { Containers: IAvailableContainer[] + AddingBehavior?: AddMethod } diff --git a/test-server/http.js b/test-server/http.js index 4051628..b5cc6bc 100644 --- a/test-server/http.js +++ b/test-server/http.js @@ -1,62 +1,69 @@ -// http.js -import { serve } from 'bun'; +import http from 'http'; +const host = 'localhost'; +const port = 5000; -serve({ - port: 5000, - async fetch(request) { - console.log(`${request.method}: ${request.url}`); - if (request.method === 'POST') { - const url = new URL(request.url); - let json; - if (url.pathname === '/GetSVGLayoutConfiguration') { - json = GetSVGLayoutConfiguration(); - } else if (url.pathname === '/SetContainerList') { - const bodyParsed = await request.json(); - console.log(bodyParsed); - switch (bodyParsed.Action) { - case 'FillHoleWithChassis': - json = FillHoleWithChassis(bodyParsed); - break; - case 'SplitRemplissage': - json = SplitRemplissage(bodyParsed); - break; - default: - break; - } - } else if (url.pathname === '/GetFeedback') { - const bodyParsed = await request.json(); - console.log(bodyParsed); - json = { - messages: [ - { - text: `${new Date()}`, - type: 3 - } - ] - } - } else { - // TODO: Return 404 rather than this - json = GetSVGLayoutConfiguration(); +const requestListener = async (request, response) => { + response.setHeader('Access-Control-Allow-Origin', '*'); + response.setHeader('Access-Control-Allow-Headers', '*'); + response.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, PATCH, OPTIONS'); + if (request.method === 'POST') { + response.setHeader('Content-Type', 'application/json'); + const url = request.url; + let json; + if (url === '/SetContainerList') { + const buffers = []; + for await (const chunk of request) { + buffers.push(chunk); } - return new Response(JSON.stringify(json), { - status: 200, - headers: { - 'Content-Type': 'application/json', - 'Access-Control-Allow-Origin': '*', - 'Access-Control-Allow-Headers': '*' - } - }); + const data = Buffer.concat(buffers).toString(); + const bodyParsed = JSON.parse(data); + console.log(bodyParsed); + switch (bodyParsed.Action.Action) { + case 'FillHoleWithChassis': + json = FillHoleWithChassis(bodyParsed); + break; + case 'SplitRemplissage': + json = SplitRemplissage(bodyParsed); + break; + case 'SplitRemplissageParent': + json = SplitRemplissage(bodyParsed); + default: + break; + } + } else if (url === '/GetFeedback') { + const buffers = []; + for await (const chunk of request) { + buffers.push(chunk); + } + const data = Buffer.concat(buffers).toString(); + const bodyParsed = JSON.parse(data); + console.log(bodyParsed); + json = { + messages: [ + { + text: `${new Date()}`, + type: 3 + } + ] + } + } else { + json = GetSVGLayoutConfiguration(); } - - return new Response('Welcome to Bun!', { - status: 200, - headers: { - 'Content-Type': 'text/plain', - 'Access-Control-Allow-Origin': '*', - 'Access-Control-Allow-Headers': '*' - } - }); + response.writeHead(200); + return response.end(JSON.stringify(json)); + } else if (request.method === 'OPTIONS') { + response.writeHead(200); + return response.end(); } + + response.setHeader('Content-Type', 'text/plain'); + response.writeHead(200); + return response.end('Hello world'); +}; + +const server = http.createServer(requestListener); +server.listen(port, host, () => { + console.log(`Server is running on http://${host}:${port}`); }); const GetSVGLayoutConfiguration = () => { @@ -64,11 +71,8 @@ const GetSVGLayoutConfiguration = () => { AvailableContainers: [ { Type: 'Chassis', - DisplayedText: 'Chassis?', - Whitelist: ["Trou"], - MaxWidth: 500, - MinWidth: 200, - Width: 200, + DisplayedText: 'Chassis horizontal', + MaxHeight: 200, DefaultChildType: 'Trou', Style: { fillOpacity: 1, @@ -76,8 +80,24 @@ const GetSVGLayoutConfiguration = () => { stroke: 'red', fill: '#d3c9b7', }, - ShowSelfDimensions: true, - IsDimensionBorrower: true, + ShowSelfDimensions: [0, 2], + ShowDimensionWithMarks: [1, 3], + Category: "Stuff" + }, + { + Type: 'ChassisVertical', + Orientation: 1, + DisplayedText: 'Chassis vertical', + MaxWidth: 200, + DefaultChildType: 'Trou', + Style: { + fillOpacity: 1, + strokeWidth: 2, + stroke: 'red', + fill: '#d3c9b7', + }, + ShowSelfDimensions: [0, 2], + ShowDimensionWithMarks: [1, 3], Category: "Stuff" }, { @@ -121,6 +141,19 @@ const GetSVGLayoutConfiguration = () => { Url: "" }, AddingBehavior: 2 + }, + { + Id: "SplitRemplissageParent", + Action: "SplitRemplissageParent", + Label: "Diviser le parent", + Description: "Diviser le remplissage en insérant un montant", + CustomLogo: { + Base64Image: null, + Name: 'Image1', + Svg: null, + Url: "" + }, + AddingBehavior: 3 } ], Style: { @@ -138,8 +171,8 @@ const GetSVGLayoutConfiguration = () => { { Type: 'Montant', Width: 10, - PositionReference: 1, - MarkPositionToDimensionBorrower: true, + PositionReference: 4, + MarkPositionToDimensionBorrower: [0], Style: { fillOpacity: 0, strokeWidth: 2, @@ -147,11 +180,24 @@ const GetSVGLayoutConfiguration = () => { fill: '#713f12', } }, + { + Type: 'Traverse', + Height: 10, + PositionReference: 4, + Orientation: 1, + MarkPositionToDimensionBorrower: [1], + Style: { + fillOpacity: 0, + strokeWidth: 2, + stroke: '#6517fa', + fill: '#6517fa', + } + }, { Type: 'Dilatation', Width: 4, PositionReference: 1, - MarkPositionToDimensionBorrower: true, + MarkPositionToDimensionBorrower: [0], Style: { fillOpacity: 0, strokeWidth: 2, @@ -222,7 +268,13 @@ const GetSVGLayoutConfiguration = () => { MainContainer: { Type: 'main', Width: 800, - Height: 200 + Height: 800, + Orientation: 1, + Style: { + stroke: 'black', + strokeWidth: 2, + fillOpacity: 0 + } } } }; @@ -265,3 +317,5 @@ const SplitRemplissage = (request) => { Containers: lstModels }; }; + + diff --git a/test-server/node-http.js b/test-server/node-http.js deleted file mode 100644 index 262d69d..0000000 --- a/test-server/node-http.js +++ /dev/null @@ -1,306 +0,0 @@ -import http from 'http'; -const host = 'localhost'; -const port = 5000; - -const requestListener = async (request, response) => { - response.setHeader('Access-Control-Allow-Origin', '*'); - response.setHeader('Access-Control-Allow-Headers', '*'); - response.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, PATCH, OPTIONS'); - if (request.method === 'POST') { - response.setHeader('Content-Type', 'application/json'); - const url = request.url; - let json; - if (url === '/SetContainerList') { - const buffers = []; - for await (const chunk of request) { - buffers.push(chunk); - } - const data = Buffer.concat(buffers).toString(); - const bodyParsed = JSON.parse(data); - console.log(bodyParsed); - switch (bodyParsed.Action) { - case 'FillHoleWithChassis': - json = FillHoleWithChassis(bodyParsed); - break; - case 'SplitRemplissage': - json = SplitRemplissage(bodyParsed); - break; - default: - break; - } - } else if (url === '/GetFeedback') { - const buffers = []; - for await (const chunk of request) { - buffers.push(chunk); - } - const data = Buffer.concat(buffers).toString(); - const bodyParsed = JSON.parse(data); - console.log(bodyParsed); - json = { - messages: [ - { - text: `${new Date()}`, - type: 3 - } - ] - } - } else { - json = GetSVGLayoutConfiguration(); - } - response.writeHead(200); - return response.end(JSON.stringify(json)); - } else if (request.method === 'OPTIONS') { - response.writeHead(200); - return response.end(); - } - - response.setHeader('Content-Type', 'text/plain'); - response.writeHead(200); - return response.end('Hello world'); -}; - -const server = http.createServer(requestListener); -server.listen(port, host, () => { - console.log(`Server is running on http://${host}:${port}`); -}); - -const GetSVGLayoutConfiguration = () => { - return { - AvailableContainers: [ - { - Type: 'Chassis', - DisplayedText: 'Chassis horizontal', - MaxHeight: 200, - DefaultChildType: 'Trou', - Style: { - fillOpacity: 1, - strokeWidth: 2, - stroke: 'red', - fill: '#d3c9b7', - }, - ShowSelfDimensions: [0, 2], - ShowDimensionWithMarks: [1, 3], - Category: "Stuff" - }, - { - Type: 'ChassisVertical', - Orientation: 1, - DisplayedText: 'Chassis vertical', - MaxWidth: 200, - DefaultChildType: 'Trou', - Style: { - fillOpacity: 1, - strokeWidth: 2, - stroke: 'red', - fill: '#d3c9b7', - }, - ShowSelfDimensions: [0, 2], - ShowDimensionWithMarks: [1, 3], - Category: "Stuff" - }, - { - Type: 'Trou', - Blacklist: ["Chassis"], - Margin: { - left: 10, - bottom: 10, - top: 10, - right: 10, - }, - DefaultChildType: 'Remplissage', - Style: { - fillOpacity: 1, - strokeWidth: 2, - stroke: 'green', - fill: 'white' - }, - Category: "Stuff" - }, - { - Type: 'Remplissage', - Category: "Other stuff", - CustomSVG: ` - - - - - ` - , - Actions: [ - { - Id: "SplitRemplissage", - Action: "SplitRemplissage", - Label: "Diviser le remplissage", - Description: "Diviser le remplissage en insérant un montant", - CustomLogo: { - Base64Image: null, - Name: 'Image1', - Svg: null, - Url: "" - }, - AddingBehavior: 2 - } - ], - Style: { - fillOpacity: 1, - strokeWidth: 1, - fill: '#bfdbfe' - }, - UserData: { - styleLine: { - transform: "scaleY(0.5) translateY(100%)", - transformBox: "fill-box" - } - } - }, - { - Type: 'Montant', - Width: 10, - PositionReference: 4, - MarkPositionToDimensionBorrower: [0], - Style: { - fillOpacity: 0, - strokeWidth: 2, - stroke: '#713f12', - fill: '#713f12', - } - }, - { - Type: 'Traverse', - Height: 10, - PositionReference: 4, - Orientation: 1, - MarkPositionToDimensionBorrower: [1], - Style: { - fillOpacity: 0, - strokeWidth: 2, - stroke: '#6517fa', - fill: '#6517fa', - } - }, - { - Type: 'Dilatation', - Width: 4, - PositionReference: 1, - MarkPositionToDimensionBorrower: [0], - Style: { - fillOpacity: 0, - strokeWidth: 2, - stroke: '#713f12', - fill: '#713f12', - } - }, - { - Type: '200', - MaxWidth: 500, - MinWidth: 200, - Style: { - fillOpacity: 1, - strokeWidth: 2, - stroke: 'blue', - fill: 'blue', - } - }, - { - Type: '400', - MaxWidth: 500, - MinWidth: 400, - Style: { - fillOpacity: 1, - strokeWidth: 2, - stroke: 'red', - fill: 'red', - } - } - ], - AvailableSymbols: [ - { - Width: 32, - Height: 32, - Image: { - Base64Image: null, - Name: 'Image1', - Svg: null, - Url: 'https://www.manutan.fr/img/S/GRP/ST/AIG3930272.jpg' - }, - Name: 'Poteau structure', - PositionReference: 1 - }, - { - Width: 32, - Height: 32, - Image: { - Base64Image: null, - Name: 'Image2', - Svg: null, - Url: 'https://e7.pngegg.com/pngimages/647/127/png-clipart-svg-working-group-information-world-wide-web-internet-structure.png' - }, - Name: 'Joint de structure', - PositionReference: 0 - } - ], - Categories: [ - { - Type: "Stuff", - DisplayedText: "Stuff made here" - }, - { - Type: "Other stuff", - DisplayedText: "Stuff not made here" - } - ], - Patterns: [], - MainContainer: { - Type: 'main', - Width: 800, - Height: 800, - Orientation: 1, - Style: { - stroke: 'black', - strokeWidth: 2, - fillOpacity: 0 - } - } - } -}; - -const FillHoleWithChassis = (request) => { - const maxWidthChassis = 3000; - const nbChassis = Math.ceil(request.ContainerAction.Width / maxWidthChassis); - const lstModels = []; - for (let i = 0; i <= nbChassis; i++) { - if (i === 1 && request.ContainerAction.ExistOnBefore) { - lstModels.push({ Type: 'Dilatation' }); - } - lstModels.push({ Type: 'Chassis' }); - if (i < nbChassis) { - lstModels.push({ Type: 'Dilatation' }); - } - if (i === nbChassis && request.ContainerAction.ExistOnAfter) { - lstModels.push({ Type: 'Dilatation' }); - } - } - return { - Containers: lstModels - }; -}; - -const SplitRemplissage = (request) => { - const lstModels = [ - { - Type: 'Remplissage' - }, - { - Type: 'Montant' - }, - { - Type: 'Remplissage' - }, - ]; - - return { - Containers: lstModels - }; -}; - -