Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
E
experience_builder
Manage
Activity
Members
Labels
Plan
Wiki
Custom issue tracker
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Model registry
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
project
experience_builder
Commits
25e3f689
Commit
25e3f689
authored
6 months ago
by
Jesse Baker
Committed by
Harumi Jang
6 months ago
Browse files
Options
Downloads
Patches
Plain Diff
Issue
#3486120
by jessebaker: Tighten up TS definitions around LayoutNodes/RootNodes etc
parent
355530a9
Branches
Branches containing commit
Tags
Tags containing commit
1 merge request
!397
#3486120 Introduce more accurate TS definitions
Pipeline
#337208
passed
6 months ago
Stage: development
Stage: build
Stage: validate
Stage: test
Changes
3
Pipelines
2
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
ui/src/features/layout/layoutModelSlice.ts
+20
-19
20 additions, 19 deletions
ui/src/features/layout/layoutModelSlice.ts
ui/src/features/layout/layoutUtils.ts
+30
-29
30 additions, 29 deletions
ui/src/features/layout/layoutUtils.ts
ui/src/services/layout.ts
+2
-7
2 additions, 7 deletions
ui/src/services/layout.ts
with
52 additions
and
55 deletions
ui/src/features/layout/layoutModelSlice.ts
+
20
−
19
View file @
25e3f689
...
...
@@ -20,23 +20,26 @@ export interface RootNode {
name
?:
string
;
nodeType
:
'
root
'
;
uuid
:
'
root
'
;
children
:
Layout
Node
[];
children
:
Node
[];
}
export
interface
LayoutNode
{
export
interface
Node
{
name
?:
string
;
uuid
:
UUID
;
nodeType
:
'
slot
'
|
'
component
'
|
'
root
'
;
nodeType
:
'
slot
'
|
'
component
'
;
type
?:
string
;
children
:
Layout
Node
[];
children
:
Node
[];
props
?:
{}
|
undefined
;
}
export
interface
LayoutModel
{
layout
:
LayoutNode
|
RootNode
;
export
type
LayoutNode
=
RootNode
|
Node
;
export
interface
RootLayoutModel
{
layout
:
RootNode
;
model
:
ComponentModels
;
}
export
interface
LayoutModelSliceState
extends
LayoutModel
{
export
interface
LayoutModelSliceState
extends
Root
LayoutModel
{
initialized
:
boolean
;
}
...
...
@@ -75,7 +78,7 @@ type DuplicateNodePayload = {
type
InsertMultipleNodesPayload
=
{
to
:
number
[]
|
undefined
;
layoutModel
:
LayoutModel
;
layoutModel
:
Root
LayoutModel
;
/**
* Pass an optional UUID that will be assigned to the last, top level node being inserted. Allows you to define the UUID
* so that you can then do something with the newly inserted node using that UUID.
...
...
@@ -118,7 +121,7 @@ export const layoutModelSlice = createSlice({
for
(
const
uuid
of
removableModelsUuids
)
{
if
(
state
.
model
[
uuid
])
delete
state
.
model
[
uuid
];
}
state
.
layout
=
removeNodeByUuid
(
state
.
layout
,
action
.
payload
);
state
.
layout
=
removeNodeByUuid
(
state
.
layout
,
action
.
payload
)
as
RootNode
;
}),
duplicateNode
:
create
.
reducer
(
(
state
,
action
:
PayloadAction
<
DuplicateNodePayload
>
)
=>
{
...
...
@@ -146,7 +149,11 @@ export const layoutModelSlice = createSlice({
return
;
}
nodePath
[
nodePath
.
length
-
1
]
++
;
state
.
layout
=
insertNodeAtPath
(
state
.
layout
,
nodePath
,
updatedNode
);
state
.
layout
=
insertNodeAtPath
(
state
.
layout
,
nodePath
,
updatedNode
,
)
as
RootNode
;
},
),
moveNode
:
create
.
reducer
(
...
...
@@ -166,12 +173,6 @@ export const layoutModelSlice = createSlice({
(
state
,
action
:
PayloadAction
<
InsertMultipleNodesPayload
>
)
=>
{
const
{
layoutModel
,
to
,
useUUID
}
=
action
.
payload
;
if
(
layoutModel
.
layout
.
nodeType
!==
'
root
'
)
{
console
.
error
(
'
Insert nodes should be passed a root layout node with children as a wrapper for the nodes you want to insert.
'
,
);
}
if
(
!
Array
.
isArray
(
to
))
{
console
.
error
(
`Cannot insert nodes. Invalid parameters: newNodes:
${
layoutModel
}
, to:
${
to
}
.`
,
...
...
@@ -180,7 +181,7 @@ export const layoutModelSlice = createSlice({
}
let
updatedModel
:
ComponentModels
=
{
...
state
.
model
};
let
newLayout
:
Layou
tNode
=
_
.
cloneDeep
(
state
.
layout
);
let
newLayout
:
Roo
tNode
=
_
.
cloneDeep
(
state
.
layout
);
const
rootNode
=
layoutModel
.
layout
;
const
model
=
layoutModel
.
model
;
...
...
@@ -285,7 +286,7 @@ export const addNewComponentToLayout =
// @todo Remove this limitation in https://www.drupal.org/project/experience_builder/issues/3467954
const
initialData
:
ComponentModel
=
{
name
:
payload
.
component
.
name
};
const
children
:
Layout
Node
[]
=
[];
const
children
:
Node
[]
=
[];
const
uuid
=
'
to_be_replaced
'
;
// Populate the model data with the default values
...
...
@@ -310,7 +311,7 @@ export const addNewComponentToLayout =
});
}
const
layoutModel
:
LayoutModel
=
{
const
layoutModel
:
Root
LayoutModel
=
{
layout
:
{
children
:
[
{
...
...
This diff is collapsed.
Click to expand it.
ui/src/features/layout/layoutUtils.ts
+
30
−
29
View file @
25e3f689
import
_
from
'
lodash
'
;
import
type
{
ComponentModels
,
LayoutNode
}
from
'
./layoutModelSlice
'
;
import
type
{
ComponentModels
,
LayoutNode
,
Node
,
RootNode
,
}
from
'
./layoutModelSlice
'
;
import
{
v4
as
uuidv4
}
from
'
uuid
'
;
// recurseNodes,
// findNodeByUuid,
// findNodePathByUuid,
// insertNodeAtPath,
// removeNodeByUuid,
// moveNodeToPath,
type
NodeFunction
=
(
node
:
LayoutNode
,
index
:
number
,
...
...
@@ -50,11 +48,11 @@ export function recurseNodes(
* @param uuid - The UUID of the node to find.
* @returns The found node or null if not found.
*/
export
function
findNodeByUuid
(
node
:
LayoutNode
,
uuid
:
string
,
):
LayoutNode
|
null
{
export
function
findNodeByUuid
(
node
:
LayoutNode
,
uuid
:
string
):
Node
|
null
{
if
(
node
.
uuid
===
uuid
)
{
if
(
node
.
nodeType
===
'
root
'
)
{
return
null
;
}
return
node
;
}
if
(
node
.
children
)
{
...
...
@@ -110,7 +108,10 @@ export function findNodePathByUuid(
* @param uuid - The UUID of the node to remove.
* @returns A deep clone of the node with the node matching the uuid removed.
*/
export
function
removeNodeByUuid
(
node
:
LayoutNode
,
uuid
:
string
):
LayoutNode
{
export
function
removeNodeByUuid
<
T
extends
LayoutNode
>
(
node
:
T
,
uuid
:
string
,
):
T
{
const
newState
=
_
.
cloneDeep
(
node
);
const
path
=
findNodePathByUuid
(
newState
,
uuid
);
...
...
@@ -134,11 +135,11 @@ export function removeNodeByUuid(node: LayoutNode, uuid: string): LayoutNode {
* @param newNode - The new node to insert.
* @returns A deep clone of the node with the newNode inserted at path.
*/
export
function
insertNodeAtPath
(
layoutNode
:
LayoutNode
,
export
function
insertNodeAtPath
<
T
extends
LayoutNode
>
(
layoutNode
:
T
,
path
:
number
[],
newNode
:
Layout
Node
,
):
LayoutNode
{
newNode
:
Node
,
):
T
{
const
newState
=
_
.
cloneDeep
(
layoutNode
);
if
(
path
.
length
===
0
)
{
...
...
@@ -166,24 +167,24 @@ export function insertNodeAtPath(
newState
.
children
[
currentIndex
],
restOfPath
,
newNode
,
);
)
as
Node
;
return
newState
;
}
/**
* Move a node to a new path.
* @param
n
ode - The root node of the layout.
* @param
rootN
ode - The root node of the layout.
* @param uuid - The UUID of the node to move.
* @param path - The path to move the node to.
* @returns A deep clone of the `
n
ode` with the node matching the `uuid` moved to the `path`.
* @returns A deep clone of the `
rootN
ode` with the node matching the `uuid` moved to the `path`.
*/
export
function
moveNodeToPath
(
layou
tNode
:
Layou
tNode
,
roo
tNode
:
Roo
tNode
,
uuid
:
string
,
path
:
number
[],
):
Layou
tNode
{
const
child
=
findNodeByUuid
(
layou
tNode
,
uuid
);
):
Roo
tNode
{
const
child
=
findNodeByUuid
(
roo
tNode
,
uuid
);
if
(
!
child
)
{
throw
new
Error
(
`Node with UUID
${
uuid
}
not found.`
);
}
...
...
@@ -193,7 +194,7 @@ export function moveNodeToPath(
child
.
uuid
=
child
.
uuid
+
'
_remove
'
;
// Insert the clone at toPath
const
newState
=
insertNodeAtPath
(
layou
tNode
,
path
,
clone
);
const
newState
=
insertNodeAtPath
(
roo
tNode
,
path
,
clone
);
// Remove the original node by finding it by uuid (which is now `${child.uuid}_remove`)
return
removeNodeByUuid
(
newState
,
child
.
uuid
);
...
...
@@ -236,22 +237,22 @@ export function getNodeDepth(layoutNode: LayoutNode, uuid: string | undefined) {
* @returns An updated model and an updated state.
*/
export
function
replaceUUIDsAndUpdateModel
(
node
:
Layout
Node
,
node
:
Node
,
model
:
ComponentModels
,
newUUID
?:
string
,
):
{
updatedNode
:
Layout
Node
;
updatedNode
:
Node
;
updatedModel
:
ComponentModels
;
}
{
const
oldToNewUUIDMap
:
Record
<
string
,
string
>
=
{};
const
updatedModel
:
ComponentModels
=
{};
const
replaceUUIDs
=
(
node
:
Layout
Node
,
node
:
Node
,
parentUuid
?:
string
,
newUuid
?:
string
,
):
Layout
Node
=>
{
const
newNode
:
Layout
Node
=
{
...
node
,
uuid
:
newUuid
||
uuidv4
()
};
):
Node
=>
{
const
newNode
:
Node
=
{
...
node
,
uuid
:
newUuid
||
uuidv4
()
};
if
(
newNode
.
nodeType
===
'
slot
'
)
{
newNode
.
uuid
=
`
${
parentUuid
}
-slot-
${
newNode
.
name
}
`
;
}
...
...
This diff is collapsed.
Click to expand it.
ui/src/services/layout.ts
+
2
−
7
View file @
25e3f689
// Need to use the React-specific entry point to import createApi
import
{
createApi
}
from
'
@reduxjs/toolkit/query/react
'
;
import
type
{
Layout
N
ode
}
from
'
@/features/layout/layoutModelSlice
'
;
import
type
{
Root
Layout
M
ode
l
}
from
'
@/features/layout/layoutModelSlice
'
;
import
{
baseQuery
}
from
'
@/services/baseQuery
'
;
export
interface
LayoutResponse
{
model
:
{};
layout
:
LayoutNode
;
}
// Define a service using a base URL and expected endpoints
export
const
layoutApi
=
createApi
({
reducerPath
:
'
layoutApi
'
,
baseQuery
,
endpoints
:
(
builder
)
=>
({
getLayoutById
:
builder
.
query
<
Layout
Response
,
string
>
({
getLayoutById
:
builder
.
query
<
Root
Layout
Model
,
string
>
({
query
:
(
nodeId
)
=>
`api/layout/{entity_type}/
${
nodeId
}
`
,
}),
}),
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment