Enhance section movement functionality in TrainingUnitSectionsEditor
All checks were successful
Deploy Development / deploy (push) Successful in 42s
Test Suite / pytest-backend (push) Successful in 38s
Test Suite / lint-backend (push) Successful in 0s
Test Suite / build-frontend (push) Successful in 13s
Test Suite / k6 /health Baseline (push) Successful in 33s
Test Suite / playwright-tests (push) Successful in 1m8s
Test Suite / pytest-backend (pull_request) Successful in 34s
Test Suite / lint-backend (pull_request) Successful in 0s
Test Suite / build-frontend (pull_request) Successful in 12s
Test Suite / k6 /health Baseline (pull_request) Successful in 33s
Test Suite / playwright-tests (pull_request) Successful in 1m8s
All checks were successful
Deploy Development / deploy (push) Successful in 42s
Test Suite / pytest-backend (push) Successful in 38s
Test Suite / lint-backend (push) Successful in 0s
Test Suite / build-frontend (push) Successful in 13s
Test Suite / k6 /health Baseline (push) Successful in 33s
Test Suite / playwright-tests (push) Successful in 1m8s
Test Suite / pytest-backend (pull_request) Successful in 34s
Test Suite / lint-backend (pull_request) Successful in 0s
Test Suite / build-frontend (pull_request) Successful in 12s
Test Suite / k6 /health Baseline (pull_request) Successful in 33s
Test Suite / playwright-tests (pull_request) Successful in 1m8s
- Updated the onMoveSectionsAcrossSlots function to support additional parameters for improved section movement across slots, including handling for parallel phase indices and insertion points. - Refined logic for moving sections between slots, ensuring proper handling of parallel streams and enhancing the overall section management experience.
This commit is contained in:
parent
7d2661a8e8
commit
8c07cf36ee
|
|
@ -245,7 +245,7 @@ function reorderBlocksImmutable(blocks, fromI, toBeforeIdx) {
|
|||
|
||||
/**
|
||||
* @param {(updater: (prev: Array) => Array) => void} props.onSectionsChange — wie React setState
|
||||
* @param {(p: { fromSlot: number, fromSectionIdx: number, toSlot: number, toSectionIdx: number, toParallelStream?: { po: number, so: number } }) => void} [props.onMoveSectionsAcrossSlots] — Rahmenprogramm: Abschnitt zwischen Slots verschieben
|
||||
* @param {(p: { fromSlot: number, fromSectionIdx?: number, toSlot: number, toSectionIdx: number, toParallelStream?: { po: number, so: number }, parallelPhaseRunOrderIndex?: number, insertBeforeParallelInTarget?: number, firstInParallelStreamInTarget?: { po: number, so: number } }) => void} [props.onMoveSectionsAcrossSlots] — Rahmenprogramm: Abschnitt(e) zwischen Slots verschieben
|
||||
*/
|
||||
export default function TrainingUnitSectionsEditor({
|
||||
sections,
|
||||
|
|
@ -807,6 +807,22 @@ export default function TrainingUnitSectionsEditor({
|
|||
if (parsed.kind === 'phaseRun') {
|
||||
const dragPo = Number(parsed.phaseRunMove.phaseOrderIndex) || 0
|
||||
if (dragPo === targetPo) return
|
||||
const fs = typeof parsed.fromSlot === 'number' ? parsed.fromSlot : -1
|
||||
if (
|
||||
typeof onMoveSectionsAcrossSlots === 'function' &&
|
||||
sectionToSlot >= 0 &&
|
||||
fs >= 0 &&
|
||||
fs !== sectionToSlot
|
||||
) {
|
||||
const ins = indicesOfParallelPhase(list, targetPo)[0] ?? list.length
|
||||
onMoveSectionsAcrossSlots({
|
||||
fromSlot: fs,
|
||||
toSlot: sectionToSlot,
|
||||
toSectionIdx: ins,
|
||||
parallelPhaseRunOrderIndex: dragPo,
|
||||
})
|
||||
return
|
||||
}
|
||||
patch((prev) => {
|
||||
const idxs = indicesOfParallelPhase(prev, targetPo)
|
||||
const fg = idxs.length ? idxs[0] : -1
|
||||
|
|
@ -818,7 +834,17 @@ export default function TrainingUnitSectionsEditor({
|
|||
return
|
||||
}
|
||||
|
||||
if (parsed.kind === 'crossSlot') return
|
||||
if (parsed.kind === 'crossSlot') {
|
||||
if (typeof onMoveSectionsAcrossSlots !== 'function') return
|
||||
onMoveSectionsAcrossSlots({
|
||||
fromSlot: parsed.fromSlot,
|
||||
fromSectionIdx: parsed.fromSi,
|
||||
toSlot: sectionToSlot,
|
||||
toSectionIdx: 0,
|
||||
insertBeforeParallelInTarget: targetPo,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
const { fromSi } = parsed
|
||||
patch((prev) => {
|
||||
|
|
@ -854,6 +880,23 @@ export default function TrainingUnitSectionsEditor({
|
|||
if (parsed.kind === 'phaseRun') {
|
||||
const dragPo = Number(parsed.phaseRunMove.phaseOrderIndex) || 0
|
||||
if (dragPo === targetPo) return
|
||||
const fs = typeof parsed.fromSlot === 'number' ? parsed.fromSlot : -1
|
||||
if (
|
||||
typeof onMoveSectionsAcrossSlots === 'function' &&
|
||||
sectionToSlot >= 0 &&
|
||||
fs >= 0 &&
|
||||
fs !== sectionToSlot
|
||||
) {
|
||||
const si = sectionIndicesForParallelStream(list, targetPo, targetSo)
|
||||
const ins = si.length ? si[0] : indicesOfParallelPhase(list, targetPo)[0] ?? list.length
|
||||
onMoveSectionsAcrossSlots({
|
||||
fromSlot: fs,
|
||||
toSlot: sectionToSlot,
|
||||
toSectionIdx: ins,
|
||||
parallelPhaseRunOrderIndex: dragPo,
|
||||
})
|
||||
return
|
||||
}
|
||||
patch((prev) => {
|
||||
const idxs = indicesOfParallelPhase(prev, targetPo)
|
||||
const fg = idxs.length ? idxs[0] : -1
|
||||
|
|
@ -865,7 +908,17 @@ export default function TrainingUnitSectionsEditor({
|
|||
return
|
||||
}
|
||||
|
||||
if (parsed.kind === 'crossSlot') return
|
||||
if (parsed.kind === 'crossSlot') {
|
||||
if (typeof onMoveSectionsAcrossSlots !== 'function') return
|
||||
onMoveSectionsAcrossSlots({
|
||||
fromSlot: parsed.fromSlot,
|
||||
fromSectionIdx: parsed.fromSi,
|
||||
toSlot: sectionToSlot,
|
||||
toSectionIdx: 0,
|
||||
firstInParallelStreamInTarget: { po: targetPo, so: targetSo },
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
const { fromSi } = parsed
|
||||
patch((prev) => {
|
||||
|
|
@ -898,9 +951,24 @@ export default function TrainingUnitSectionsEditor({
|
|||
const fromSlot = typeof data.fromSlot === 'number' ? data.fromSlot : -1
|
||||
|
||||
if (phaseRunMove != null && phaseRunMove.phaseOrderIndex != null) {
|
||||
patch((prev) => {
|
||||
const po = Number(phaseRunMove.phaseOrderIndex) || 0
|
||||
let next = moveParallelPhaseRunToInsertBefore(prev, po, insertBeforeIdx)
|
||||
if (
|
||||
typeof onMoveSectionsAcrossSlots === 'function' &&
|
||||
sectionToSlot >= 0 &&
|
||||
fromSlot >= 0 &&
|
||||
fromSlot !== sectionToSlot
|
||||
) {
|
||||
onMoveSectionsAcrossSlots({
|
||||
fromSlot,
|
||||
toSlot: sectionToSlot,
|
||||
toSectionIdx: insertBeforeIdx,
|
||||
parallelPhaseRunOrderIndex: po,
|
||||
})
|
||||
return
|
||||
}
|
||||
patch((prev) => {
|
||||
const poLocal = Number(phaseRunMove.phaseOrderIndex) || 0
|
||||
let next = moveParallelPhaseRunToInsertBefore(prev, poLocal, insertBeforeIdx)
|
||||
if (enableParallelPhaseControls) next = afterSectionReorderParallelGuard(prev, next)
|
||||
return next
|
||||
})
|
||||
|
|
|
|||
|
|
@ -15,6 +15,9 @@ import {
|
|||
buildPlanPayloadForSave,
|
||||
hydrateExercisePlanningRow,
|
||||
reorderBlockIntoParallelStreamEnd,
|
||||
indicesOfParallelPhase,
|
||||
reorderSectionBeforeParallelRunAsWholeGroup,
|
||||
reorderSectionAsFirstInParallelStream,
|
||||
} from '../utils/trainingUnitSectionsForm'
|
||||
|
||||
const DND_FW_SLOT = 'application/x-shinkan-framework-slot'
|
||||
|
|
@ -561,7 +564,17 @@ export default function TrainingFrameworkProgramEditPage() {
|
|||
}
|
||||
|
||||
const moveSectionsAcrossFrameworkSlots = useCallback(
|
||||
({ fromSlot, fromSectionIdx, toSlot, toSectionIdx, toParallelStream }) => {
|
||||
(payload) => {
|
||||
const {
|
||||
fromSlot,
|
||||
fromSectionIdx,
|
||||
toSlot,
|
||||
toSectionIdx,
|
||||
toParallelStream,
|
||||
parallelPhaseRunOrderIndex,
|
||||
insertBeforeParallelInTarget,
|
||||
firstInParallelStreamInTarget,
|
||||
} = payload
|
||||
setForm((prev) => {
|
||||
const slots = prev.slots.map((sl) => ({
|
||||
...sl,
|
||||
|
|
@ -579,15 +592,7 @@ export default function TrainingFrameworkProgramEditPage() {
|
|||
}
|
||||
|
||||
const fromSecs = slots[fromSlot].sections
|
||||
if (
|
||||
typeof fromSectionIdx !== 'number' ||
|
||||
fromSectionIdx < 0 ||
|
||||
fromSectionIdx >= fromSecs.length
|
||||
) {
|
||||
return prev
|
||||
}
|
||||
|
||||
const [block] = fromSecs.splice(fromSectionIdx, 1)
|
||||
const toSecs = slots[toSlot].sections
|
||||
|
||||
const applyParallelStreamEnd =
|
||||
toParallelStream != null && toParallelStream.po != null && toParallelStream.so != null
|
||||
|
|
@ -598,6 +603,43 @@ export default function TrainingFrameworkProgramEditPage() {
|
|||
}
|
||||
: null
|
||||
|
||||
/** Gesamten Parallel-Lauf aus fromSlot an toSectionIdx in toSlot legen */
|
||||
if (parallelPhaseRunOrderIndex != null && parallelPhaseRunOrderIndex !== '') {
|
||||
const po = Number(parallelPhaseRunOrderIndex) || 0
|
||||
const idxs = indicesOfParallelPhase(fromSecs, po)
|
||||
if (!idxs.length) {
|
||||
return prev
|
||||
}
|
||||
const blocks = idxs.map((i) => fromSecs[i])
|
||||
for (const i of [...idxs].sort((a, b) => b - a)) {
|
||||
fromSecs.splice(i, 1)
|
||||
}
|
||||
if (fromSlot === toSlot) {
|
||||
let insertAt = Number(toSectionIdx) || 0
|
||||
for (const i of idxs) {
|
||||
if (i < insertAt) insertAt -= 1
|
||||
}
|
||||
insertAt = Math.max(0, Math.min(insertAt, fromSecs.length))
|
||||
fromSecs.splice(insertAt, 0, ...blocks)
|
||||
slots[fromSlot].sections = fromSecs
|
||||
return { ...prev, slots }
|
||||
}
|
||||
const insertAt = Math.max(0, Math.min(Number(toSectionIdx) || 0, toSecs.length))
|
||||
toSecs.splice(insertAt, 0, ...blocks)
|
||||
slots[toSlot].sections = toSecs
|
||||
return { ...prev, slots }
|
||||
}
|
||||
|
||||
if (
|
||||
typeof fromSectionIdx !== 'number' ||
|
||||
fromSectionIdx < 0 ||
|
||||
fromSectionIdx >= fromSecs.length
|
||||
) {
|
||||
return prev
|
||||
}
|
||||
|
||||
const [block] = fromSecs.splice(fromSectionIdx, 1)
|
||||
|
||||
if (fromSlot === toSlot) {
|
||||
let insertAt = toSectionIdx
|
||||
if (fromSectionIdx < toSectionIdx) insertAt = toSectionIdx - 1
|
||||
|
|
@ -605,15 +647,45 @@ export default function TrainingFrameworkProgramEditPage() {
|
|||
fromSecs.splice(insertAt, 0, block)
|
||||
if (applyParallelStreamEnd) {
|
||||
slots[fromSlot].sections = applyParallelStreamEnd(fromSecs, insertAt)
|
||||
} else {
|
||||
slots[fromSlot].sections = fromSecs
|
||||
}
|
||||
return { ...prev, slots }
|
||||
}
|
||||
|
||||
const toSecs = slots[toSlot].sections
|
||||
if (insertBeforeParallelInTarget != null && insertBeforeParallelInTarget !== '') {
|
||||
const tpo = Number(insertBeforeParallelInTarget) || 0
|
||||
const pIdxs = indicesOfParallelPhase(toSecs, tpo)
|
||||
const ins = pIdxs.length ? pIdxs[0] : toSecs.length
|
||||
toSecs.splice(ins, 0, block)
|
||||
slots[toSlot].sections = reorderSectionBeforeParallelRunAsWholeGroup(toSecs, ins, tpo)
|
||||
return { ...prev, slots }
|
||||
}
|
||||
|
||||
if (
|
||||
firstInParallelStreamInTarget != null &&
|
||||
firstInParallelStreamInTarget.po != null &&
|
||||
firstInParallelStreamInTarget.so != null
|
||||
) {
|
||||
const fpo = Number(firstInParallelStreamInTarget.po) || 0
|
||||
const fso = Number(firstInParallelStreamInTarget.so) || 0
|
||||
const nextSecs = [...toSecs, block]
|
||||
const movedFromI = nextSecs.length - 1
|
||||
slots[toSlot].sections = reorderSectionAsFirstInParallelStream(
|
||||
nextSecs,
|
||||
movedFromI,
|
||||
fpo,
|
||||
fso
|
||||
)
|
||||
return { ...prev, slots }
|
||||
}
|
||||
|
||||
const ia = Math.max(0, Math.min(toSectionIdx, toSecs.length))
|
||||
toSecs.splice(ia, 0, block)
|
||||
if (applyParallelStreamEnd) {
|
||||
slots[toSlot].sections = applyParallelStreamEnd(toSecs, ia)
|
||||
} else {
|
||||
slots[toSlot].sections = toSecs
|
||||
}
|
||||
return { ...prev, slots }
|
||||
})
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user