Skip to content

Commit

Permalink
feat(ui): remove legacy react beautiful dnd part 1 (#1686)
Browse files Browse the repository at this point in the history
* chore: add framer-motion

* refactor(projects): replace react-beautiful-dnd in deployment-rules

* refactor(ui): replace react-beautiful-dnd in stage-order-modal
  • Loading branch information
ctjhoa authored Sep 24, 2024
1 parent 26a48d0 commit bc8bccd
Show file tree
Hide file tree
Showing 10 changed files with 208 additions and 190 deletions.
Original file line number Diff line number Diff line change
@@ -1,13 +1,6 @@
import { Reorder } from 'framer-motion'
import { type Cluster, type ProjectDeploymentRule } from 'qovery-typescript-axios'
import { useEffect, useState } from 'react'
import {
DragDropContext,
Draggable,
type DraggableProvided,
type DropResult,
Droppable,
type DroppableProvided,
} from 'react-beautiful-dnd'
import { useNavigate } from 'react-router-dom'
import { Button, Icon } from '@qovery/shared/ui'
import DeploymentRuleItem from '../deployment-rule-item/deployment-rule-item'
Expand Down Expand Up @@ -35,20 +28,9 @@ export function PageDeploymentRules({
const navigate = useNavigate()
const [listRules, setListRules] = useState<ProjectDeploymentRule[]>(deploymentRules || [])

const onDragEnd = (result: DropResult) => {
const { destination, source } = result

if (!destination) return

if (destination.droppableId === source.droppableId && destination.index === source.index) return

const currentList = [...listRules]
const ruleToMove = currentList[source.index]
currentList.splice(source.index, 1)
currentList.splice(destination.index, 0, ruleToMove)

setListRules(currentList)
updateDeploymentRulesOrder(currentList)
const handleReorder = (deploymentRules: ProjectDeploymentRule[]) => {
setListRules(deploymentRules)
updateDeploymentRulesOrder(deploymentRules)
}

useEffect(() => {
Expand Down Expand Up @@ -82,37 +64,22 @@ export function PageDeploymentRules({
Deployment Rules
</h2>
</div>
<DragDropContext onDragEnd={onDragEnd}>
<Droppable droppableId="rules-list">
{(provided: DroppableProvided) => (
<div {...provided.droppableProps} ref={provided.innerRef}>
{listRules?.map((rule: ProjectDeploymentRule, index) => (
<Draggable draggableId={index.toString()} key={index} index={index}>
{(providedDraggble: DraggableProvided) => (
<div
{...providedDraggble.draggableProps}
{...providedDraggble.dragHandleProps}
ref={providedDraggble.innerRef}
>
<DeploymentRuleItem
id={rule.id}
name={rule.name}
startTime={rule.start_time}
stopTime={rule.stop_time}
weekDays={rule.weekdays}
isLast={index === listRules.length - 1 ? true : false}
isLoading={isLoading}
removeDeploymentRule={deleteDeploymentRule}
/>
</div>
)}
</Draggable>
))}
{provided.placeholder}
</div>
)}
</Droppable>
</DragDropContext>
<Reorder.Group axis="y" values={listRules} onReorder={handleReorder}>
{listRules.map((rule, index) => (
<Reorder.Item key={rule.id} value={rule}>
<DeploymentRuleItem
id={rule.id}
name={rule.name}
startTime={rule.start_time}
stopTime={rule.stop_time}
weekDays={rule.weekdays}
isLast={index === listRules.length - 1 ? true : false}
isLoading={isLoading}
removeDeploymentRule={deleteDeploymentRule}
/>
</Reorder.Item>
))}
</Reorder.Group>
</div>
</div>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,10 @@ export function StageOrderModalFeature(props: StageOrderModalFeatureProps) {
const onSubmit = async (stageId: string, targetStageId: string, after: boolean) => {
const result = await moveDeploymentStageRequested({ stageId, targetStageId, after })
setCurrentStages(result)
return result
}

return (
<StageOrderModal
currentStages={currentStages}
setCurrentStages={setCurrentStages}
onClose={props.onClose}
onSubmit={onSubmit}
/>
)
return <StageOrderModal currentStages={currentStages} onClose={props.onClose} onSubmit={onSubmit} />
}

export default StageOrderModalFeature
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { type DeploymentStageResponse } from 'qovery-typescript-axios'
import { move, reorderService, reorderStage } from './utils'
import { move, reorderService } from './utils'

describe('PageSettingsDeploymentPipeline/utils', () => {
it('should reorder the services within a stage', () => {
Expand Down Expand Up @@ -57,52 +57,6 @@ describe('PageSettingsDeploymentPipeline/utils', () => {
expect(result).toEqual(expectedStages)
})

it('should reorder the stages', () => {
const stages: DeploymentStageResponse[] = [
{
id: '1',
created_at: '',
environment: {
id: '1',
},
services: [],
},
{
id: '2',
created_at: '',
environment: {
id: '1',
},
services: [],
},
]

const expectedStages: DeploymentStageResponse[] = [
{
id: '2',
created_at: '',
environment: {
id: '1',
},
services: [],
},
{
id: '1',
created_at: '',
environment: {
id: '1',
},
services: [],
},
]
const startIndex = 1
const endIndex = 0

const result = reorderStage(stages, startIndex, endIndex)

expect(result).toEqual(expectedStages)
})

it('should move a service between stages', () => {
const stages: DeploymentStageResponse[] = [
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,6 @@ export const reorderService = (
return result
}

export const reorderStage = (
stages: DeploymentStageResponse[],
startIndex: number,
endIndex: number
): DeploymentStageResponse[] => {
const cloneStages = [...stages]
const currentStage = [...cloneStages]

const [removed] = currentStage.splice(startIndex, 1)
currentStage.splice(endIndex, 0, removed)

return currentStage
}

export const move = (
stages: DeploymentStageResponse[],
droppableSource: DraggableLocation,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,87 +1,66 @@
import { Reorder } from 'framer-motion'
import { type DeploymentStageResponse } from 'qovery-typescript-axios'
import { type Dispatch, type SetStateAction } from 'react'
import { DragDropContext, Draggable, type DropResult, Droppable } from 'react-beautiful-dnd'
import { useState } from 'react'
import { BadgeDeploymentOrder, Button, ScrollShadowWrapper } from '@qovery/shared/ui'
import { reorderStage } from '../../../feature/page-settings-deployment-pipeline-feature/utils/utils'
import { findMovedIndices } from '@qovery/shared/util-js'

export interface StageOrderModalProps {
onClose: () => void
onSubmit: (stageId: string, beforeOrAfterStageId: string, after: boolean) => void
setCurrentStages: Dispatch<SetStateAction<DeploymentStageResponse[] | undefined>>
onSubmit: (
stageId: string,
beforeOrAfterStageId: string,
after: boolean
) => Promise<DeploymentStageResponse[] | undefined>
currentStages?: DeploymentStageResponse[]
}

export function StageOrderModal(props: StageOrderModalProps) {
const onDragEnd = (result: DropResult) => {
const { source, destination } = result
export function StageOrderModal({ currentStages = [], onClose, onSubmit }: StageOrderModalProps) {
const [localStages, setLocalStages] = useState(currentStages)

if (!destination) {
const handleDrop = async () => {
const movedIndices = findMovedIndices(currentStages, localStages, (a, b) => a.id === b.id)
if (!movedIndices) {
return
}

if (props.currentStages && source.index !== destination.index) {
// reorder locally without waiting the api response
const newStages = reorderStage(props.currentStages, source.index, destination.index)
props.setCurrentStages(newStages)
// submit the reorder for the api
props.onSubmit(
props.currentStages[source.index].id,
props.currentStages[destination.index].id,
source.index < destination.index
)
const [sourceIndex, destinationIndex] = movedIndices
const result = await onSubmit(
currentStages[sourceIndex].id,
currentStages[destinationIndex].id,
sourceIndex < destinationIndex
)
if (result) {
setLocalStages(result)
}
}

const classNameItem = (isDragging: boolean) =>
`flex items-center w-full text-neutral-400 text-ssm font-medium rounded p-4 border ${
isDragging ? 'border-2 border-green-500 bg-neutral-50' : 'border-neutral-250 bg-neutral-100'
}`

return (
<DragDropContext onDragEnd={onDragEnd}>
<div className="p-6">
<h2 className="h4 mb-1 max-w-sm truncate text-neutral-400">Edit execution order</h2>
<p className="mb-6 text-sm text-neutral-350">You can drag and drop stages to modify their order.</p>
<ScrollShadowWrapper className="max-h-[500px]">
<Droppable droppableId="0">
{(provided) => (
<div className="select-none" {...provided.droppableProps} ref={provided.innerRef}>
{props.currentStages?.map((stage, index) => (
<Draggable key={stage.id} draggableId={stage.id} index={index}>
{(provided, snapshot) => (
<div
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}
className="!left-[auto] !top-[auto] mb-1 flex items-center"
>
<div
className={`mr-3 h-5 w-5 text-center text-sm text-neutral-400 ${
snapshot.isDragging ? 'opacity-0' : ''
}`}
>
{index}
</div>
<div className={snapshot && classNameItem(snapshot.isDragging)}>
<BadgeDeploymentOrder order={stage.deployment_order} />
<span className="ml-1 block">{stage.name}</span>
</div>
</div>
)}
</Draggable>
))}
{provided.placeholder}
</div>
)}
</Droppable>
</ScrollShadowWrapper>
<div className="mt-6 flex justify-end gap-3">
<Button data-testid="cancel-button" size="lg" color="neutral" variant="plain" onClick={() => props.onClose()}>
Cancel
</Button>
</div>
<div className="p-6">
<h2 className="h4 mb-1 max-w-sm truncate text-neutral-400">Edit execution order</h2>
<p className="mb-6 text-sm text-neutral-350">You can drag and drop stages to modify their order.</p>
<ScrollShadowWrapper className="max-h-[500px]">
<Reorder.Group axis="y" values={localStages} onReorder={setLocalStages} className="flex flex-col gap-1">
{localStages?.map((stage) => (
<Reorder.Item
key={stage.id}
value={stage}
initial={{ cursor: 'grab' }}
exit={{ cursor: 'grab' }}
whileDrag={{ cursor: 'grabbing', borderColor: '#44C979', borderWidth: '2px' }}
onDragEnd={handleDrop}
className="flex w-full items-center rounded border border-neutral-250 bg-neutral-100 p-4 text-ssm font-medium text-neutral-400"
>
<BadgeDeploymentOrder order={stage.deployment_order} />
<span className="ml-1 block">{stage.name}</span>
</Reorder.Item>
))}
</Reorder.Group>
</ScrollShadowWrapper>
<div className="mt-6 flex justify-end gap-3">
<Button data-testid="cancel-button" size="lg" color="neutral" variant="plain" onClick={() => onClose()}>
Cancel
</Button>
</div>
</DragDropContext>
</div>
)
}

Expand Down
1 change: 1 addition & 0 deletions libs/shared/util-js/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@ export * from './lib/trim-id'
export * from './lib/uppercase-first-letter'
export * from './lib/url-code-editor'
export * from './lib/parse-cmd'
export * from './lib/find-moved-indices'
Loading

0 comments on commit bc8bccd

Please sign in to comment.