Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -1 +1 @@
# pnpm cli tasks lint --stage test
pnpm cli tasks lint --stage test
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,7 @@ export class ConvertElementToComponentPage extends BuilderPage {
async checkComponentHasCorrectElements() {
await expect(this.getBuilderRenderContainer()).toHaveText(textContent)

await this.checkElementTreeStructure([
'Container Root',
'Container',
'Row',
'Column',
'Text',
])
await this.checkElementTreeStructure(['Container', 'Row', 'Column', 'Text'])
}

async convertElementToComponent() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import type { IComponentModel } from '@codelab/frontend/abstract/domain'
import type {
IComponentModel,
IElementModel,
} from '@codelab/frontend/abstract/domain'
import type {
ICreateComponentData,
IRef,
Expand Down Expand Up @@ -27,6 +30,10 @@ export interface IComponentService
// componentDevelopmentService: IComponentDevelopmentService
// moved to builder
// getSelectComponentOptions(): Promise<Array<DefaultOptionType>>
createWithoutRoot(
data: ICreateComponentData,
rootElement: IElementModel,
): Promise<IComponentModel>
importComponent(componentDataFile: File): Promise<Maybe<IComponentModel>>
previewComponent(id: string): void
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import type { IComponentModel } from '@codelab/frontend/abstract/domain'
import type { Maybe } from '@codelab/shared/abstract/types'
import type { Maybe, Nullable } from '@codelab/shared/abstract/types'
import type { Ref } from 'mobx-keystone'

import type { IBaseRuntimeModel } from '../runtime.model.interface'
import type { IRuntimeElementModel } from '../runtime-element'
import type { IRuntimeComponentPropModel } from '../runtime-prop'
import { ReactElement } from 'react'

/**
* Represents runtime model IComponentModel
Expand All @@ -26,6 +27,13 @@ export interface IRuntimeComponentModel extends IBaseRuntimeModel {
component: Ref<IComponentModel>
isChildMapperComponentInstance: boolean
isTypedProp?: boolean
elements: Array<IRuntimeElementModel>
/**
* When clicking an element from component while editing a page or another component we should select element
* from main tree that is being edited
*/
mainTreeElement: Maybe<IRuntimeElementModel>

/**
* Exposed for external use by other models and to preserve structure
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,12 @@ export interface IRuntimeElementModel extends IBaseRuntimeModel {
* The runtime model for IElementModel.closestContainerNode
*/
closestContainerNode: Ref<IRuntimeComponentModel | IRuntimePageModel>

descendantElements: Array<IRuntimeElementModel>

element: Ref<IElementModel>

mainTreeElement: IRuntimeElementModel
parentElement: Maybe<IRuntimeElementModel>
parentElementKey: Nullable<string>
pathFromRoot: Array<IRuntimeElementModel>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ export interface IRuntimeElementService {
currentStylePseudoClass: ElementStylePseudoClass
elements: ObjectMap<IRuntimeElementModel>
elementsList: Array<IRuntimeElementModel>
expandedCompositeKeys: Array<string>
add(
element: IElementModel,
closestContainerNode: IRuntimeComponentModel | IRuntimePageModel,
parentElement: Nullable<IRuntimeElementModel>,
propKey?: string,
): IRuntimeElementModel
getExpandedCompositeKeys(): Array<string>
maybeRuntimeElement(compositeKey: string): Maybe<IRuntimeElementModel>
remove(runtimeElement: IRuntimeElementModel): void
runtimeElement(compositeKey: string): IRuntimeElementModel
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { IPageModel } from '@codelab/frontend/abstract/domain'
import type { Ref } from 'mobx-keystone'
import type { Maybe } from '@codelab/shared/abstract/types'

import type { IBaseRuntimeModel } from '../runtime.model.interface'
import type { IRuntimeElementModel } from '../runtime-element'
Expand All @@ -12,6 +13,12 @@ export interface IRuntimePageModel extends IBaseRuntimeModel {
* Regular page in case the current model is a provider page
*/
childPage?: Ref<IRuntimePageModel>
elements: Array<IRuntimeElementModel>
/**
* When clicking an element from provider page while editing a regular page we should select root element of regular page
* This is the root element of the regular page
*/
mainTreeElement: Maybe<IRuntimeElementModel>
/**
* Page domain model
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@ import type {
RenderTypeSelectOption,
SelectOption,
} from '@codelab/frontend/abstract/types'
import type {
IComponentDto,
ICreateComponentData,
} from '@codelab/shared/abstract/core'
import type { IComponentDto } from '@codelab/shared/abstract/core'
import type { ObjectMap } from 'mobx-keystone'

import type { IHydrateable } from '../shared'
Expand All @@ -16,7 +13,6 @@ export interface IComponentDomainService
componentList: Array<IComponentModel>
components: ObjectMap<IComponentModel>
sortedComponentsList: Array<IComponentModel>
add(data: ICreateComponentData): IComponentModel
component(id: string): IComponentModel
findById(id: string): IComponentModel
getRenderTypeOptions(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ export interface IElementModel extends IModel<IElementDto, IElementModel> {
primary: string
secondary: string | undefined
}
attachAsComponentRoot(component: IRef): void
attachAsFirstChild(parentElement: IElementModel): void
attachAsNextSibling(sibling: IElementModel): void
attachAsPrevSibling(sibling: IElementModel): void
Expand All @@ -118,7 +119,6 @@ export interface IElementModel extends IModel<IElementDto, IElementModel> {
setName(name: string): void
setNextSibling(nextSibling: Ref<IElementModel>): void
setOrderInParent(order: number | null): void
setParentComponent(component: Ref<IComponentModel>): void
setParentElement(parent: Ref<IElementModel>): void
setPrevSibling(prevSibling: Ref<IElementModel>): void
setProps(props: IPropModel): void
Expand Down
4 changes: 4 additions & 0 deletions libs/frontend/abstract/domain/src/shared/constant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ export const DATASET_ELEMENT_ID = 'elementId'

export const DATA_ELEMENT_ID = 'data-element-id'

export const DATA_RUNTIME_ELEMENT_KEY = 'data-runtime-element-key'

export const BUILDER_CONTAINER_ID = 'Builder'

export const BUILDER_NONE_CLASS_NAME = 'Builder-none'
Expand All @@ -23,6 +25,8 @@ export const DATA_GRID = 'DATA-GRID'

export const ROOT_RENDER_CONTAINER_ID = 'render-root'

export const BLUEPRINT_ID_PREFIX = 'blueprint-'

export const LAST_WORD_AFTER_DOT_REGEX = /\.\w+$/

export const WORD_BEFORE_DOT_REGEX = /\w*(\.)?/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { ROOT_RENDER_CONTAINER_ID } from '@codelab/frontend/abstract/domain'
import { HierarchicalCollisionDetector } from '@codelab/frontend-application-dnd/collision-detection'
import {
AutoDragOverlay,
DropIndicator,
DropOverlay,
} from '@codelab/frontend-application-dnd/components'
import { useElementService } from '@codelab/frontend-application-element/services'
Expand Down Expand Up @@ -76,8 +75,6 @@ const BuilderDndContext = ({ children }: PropsWithChildren) => {
sensors={sensors}
>
{children}

<DropIndicator />
<DropOverlay />
<AutoDragOverlay />
</DndContext>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,42 +92,23 @@ export const useDndDropHandler = (): UseDndDropHandler => {
}

const handleMoveElement = async (event: DragEndEvent) => {
const runtimeDraggedElementKey = event.active.id.toString()

const draggedElementId = runtimeElementService.runtimeElement(
runtimeDraggedElementKey,
).element.id

const draggedElementId = event.active.id.toString()
const draggedElement = elementDomainService.element(draggedElementId)
const collisionData = event.collisions?.[0]?.data as Maybe<CollisionData>
const activeElementTree = rendererService.activeElementTree

const runtimePrevSiblingKey =
const prevSiblingId =
collisionData?.childDroppableBeforePointer as Maybe<string>

const runtimeNextSiblingKey =
const nextSiblingId =
collisionData?.childDroppableAfterPointer as Maybe<string>

const runtimeDropTargetKey = event.over?.id.toString()

const prevSiblingId = runtimePrevSiblingKey
? runtimeElementService.maybeRuntimeElement(runtimePrevSiblingKey)
?.element.id
: undefined

const nextSiblingId = runtimeNextSiblingKey
? runtimeElementService.maybeRuntimeElement(runtimeNextSiblingKey)
?.element.id
: undefined
const dropTargetId = event.over?.id.toString()

const parentElementId =
runtimeDropTargetKey === ROOT_RENDER_CONTAINER_ID
dropTargetId === ROOT_RENDER_CONTAINER_ID
? activeElementTree?.rootElement.current.id
: runtimeDropTargetKey
? runtimeElementService.maybeRuntimeElement(runtimeDropTargetKey)
?.element.id
: undefined

const draggedElement = elementDomainService.element(draggedElementId)
: dropTargetId

if (
!parentElementId ||
Expand Down
1 change: 1 addition & 0 deletions libs/frontend/application/builder/src/hooks/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from './useBuilderHotkeys.hook'
export * from './useBuilderResizer.hook'
export * from './useDropIndicator.hook'
export * from './useElementTreeDrop.hook'
export * from './usePropsInspector.hook'
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import type { IElementModel } from '@codelab/frontend/abstract/domain'
import type { HierarchicalCollision } from '@codelab/frontend-application-dnd/collision-detection'
import type React from 'react'

import { useDomainStore } from '@codelab/frontend-infra-mobx/context'
import { useDndContext } from '@dnd-kit/core'

export const DROP_INDICATOR_STYLE = '5px solid #439A56'

const afterStyle: React.CSSProperties = {
borderLeft: DROP_INDICATOR_STYLE,
borderTop: DROP_INDICATOR_STYLE,
boxSizing: 'border-box',
}

const beforeStyle: React.CSSProperties = {
borderBottom: DROP_INDICATOR_STYLE,
borderRight: DROP_INDICATOR_STYLE,
boxSizing: 'border-box',
}

export const useDropIndicator = (element: IElementModel) => {
const { active, collisions } = useDndContext()
const { elementDomainService } = useDomainStore()
const collision = collisions?.[0] as HierarchicalCollision | undefined
const after = collision?.data.childDroppableAfterPointer
const before = collision?.data.childDroppableBeforePointer
const isAfter = after === element.id
const isBefore = before === element.id

const activeElement = active?.id
? elementDomainService.element(String(active.id))
: null

const sameBefore =
activeElement?.prevSibling?.id && activeElement.prevSibling.id === before

const sameAfter =
activeElement?.nextSibling?.id && activeElement.nextSibling.id === after

const sameOrder = sameBefore || sameAfter

if (sameOrder || (!isAfter && !isBefore)) {
return null
}

return isAfter ? afterStyle : beforeStyle
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,10 @@
'use client'

import type {
IElementTreeViewDataNode,
IRuntimeComponentModel,
} from '@codelab/frontend/abstract/application'
import type { IElementTreeViewDataNode } from '@codelab/frontend/abstract/application'
import type { Nullable } from '@codelab/shared/abstract/types'

import {
isRuntimeComponent,
runtimeComponentRef,
} from '@codelab/frontend/abstract/application'
import { isComponent } from '@codelab/frontend/abstract/domain'
import { PageType } from '@codelab/frontend/abstract/types'
import { useComponentService } from '@codelab/frontend-application-component/services'
import {
useCloneElementService,
Expand Down Expand Up @@ -66,7 +60,7 @@ export const ElementContextMenu = observer<
return null
}

const componentInstance = isComponent(element.renderType)
const componentInstance = isComponent(element.renderType.current)

const onAddChild = () => {
createPopover.open(router, { appId, componentId, pageId })
Expand Down Expand Up @@ -105,20 +99,13 @@ export const ElementContextMenu = observer<
}

const onEditComponent = () => {
if (!isComponent(element.renderType)) {
if (!isComponent(element.renderType.current)) {
return
}

const runtimeElement = runtimeElementService.runtimeElement(treeNode.key)

const runtimeComponent = runtimeElement.children.find(
(child): child is IRuntimeComponentModel =>
isRuntimeComponent(child) &&
child.component.id === element.renderType.id,
router.push(
PageType.ComponentBuilder({ componentId: element.renderType.current.id }),
)

runtimeComponent &&
builderService.setSelectedNode(runtimeComponentRef(runtimeComponent))
}

const menuItems = [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export const ElementTreeView = observer<{
autoExpandParent={false}
disabled={isMoving}
draggable={true}
expandedKeys={runtimeElementService.expandedCompositeKeys}
expandedKeys={runtimeElementService.getExpandedCompositeKeys()}
onClick={(event) => {
event.stopPropagation()
}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,13 @@

import type { IComponentModel } from '@codelab/frontend/abstract/domain'

import { ExplorerPaneType, PageType } from '@codelab/frontend/abstract/types'
import { PageType } from '@codelab/frontend/abstract/types'
import { downloadJsonAsFile } from '@codelab/frontend/shared/utils'
import { exportComponentService } from '@codelab/frontend-application-component/use-cases/export-component'
import { useDomainStore } from '@codelab/frontend-infra-mobx/context'
import { slugify } from '@codelab/shared/utils'
import { observer } from 'mobx-react-lite'
import { useRouter } from 'next/navigation'
import queryString from 'query-string'
import { useAsyncFn } from 'react-use'

import { ComponentList } from './ComponentList'
Expand All @@ -25,12 +24,7 @@ export const CustomComponents = observer(() => {
})

const editComponent = (componentId: string) => {
const url = queryString.stringifyUrl({
query: { primarySidebarKey: ExplorerPaneType.Explorer },
url: PageType.ComponentBuilder({ componentId }),
})

router.push(url)
router.push(PageType.ComponentBuilder({ componentId }))
}

const deleteComponent = (componentId: string) => {
Expand Down
Loading