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 {(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({
|
export default function TrainingUnitSectionsEditor({
|
||||||
sections,
|
sections,
|
||||||
|
|
@ -807,6 +807,22 @@ export default function TrainingUnitSectionsEditor({
|
||||||
if (parsed.kind === 'phaseRun') {
|
if (parsed.kind === 'phaseRun') {
|
||||||
const dragPo = Number(parsed.phaseRunMove.phaseOrderIndex) || 0
|
const dragPo = Number(parsed.phaseRunMove.phaseOrderIndex) || 0
|
||||||
if (dragPo === targetPo) return
|
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) => {
|
patch((prev) => {
|
||||||
const idxs = indicesOfParallelPhase(prev, targetPo)
|
const idxs = indicesOfParallelPhase(prev, targetPo)
|
||||||
const fg = idxs.length ? idxs[0] : -1
|
const fg = idxs.length ? idxs[0] : -1
|
||||||
|
|
@ -818,7 +834,17 @@ export default function TrainingUnitSectionsEditor({
|
||||||
return
|
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
|
const { fromSi } = parsed
|
||||||
patch((prev) => {
|
patch((prev) => {
|
||||||
|
|
@ -854,6 +880,23 @@ export default function TrainingUnitSectionsEditor({
|
||||||
if (parsed.kind === 'phaseRun') {
|
if (parsed.kind === 'phaseRun') {
|
||||||
const dragPo = Number(parsed.phaseRunMove.phaseOrderIndex) || 0
|
const dragPo = Number(parsed.phaseRunMove.phaseOrderIndex) || 0
|
||||||
if (dragPo === targetPo) return
|
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) => {
|
patch((prev) => {
|
||||||
const idxs = indicesOfParallelPhase(prev, targetPo)
|
const idxs = indicesOfParallelPhase(prev, targetPo)
|
||||||
const fg = idxs.length ? idxs[0] : -1
|
const fg = idxs.length ? idxs[0] : -1
|
||||||
|
|
@ -865,7 +908,17 @@ export default function TrainingUnitSectionsEditor({
|
||||||
return
|
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
|
const { fromSi } = parsed
|
||||||
patch((prev) => {
|
patch((prev) => {
|
||||||
|
|
@ -898,9 +951,24 @@ export default function TrainingUnitSectionsEditor({
|
||||||
const fromSlot = typeof data.fromSlot === 'number' ? data.fromSlot : -1
|
const fromSlot = typeof data.fromSlot === 'number' ? data.fromSlot : -1
|
||||||
|
|
||||||
if (phaseRunMove != null && phaseRunMove.phaseOrderIndex != null) {
|
if (phaseRunMove != null && phaseRunMove.phaseOrderIndex != null) {
|
||||||
|
const po = Number(phaseRunMove.phaseOrderIndex) || 0
|
||||||
|
if (
|
||||||
|
typeof onMoveSectionsAcrossSlots === 'function' &&
|
||||||
|
sectionToSlot >= 0 &&
|
||||||
|
fromSlot >= 0 &&
|
||||||
|
fromSlot !== sectionToSlot
|
||||||
|
) {
|
||||||
|
onMoveSectionsAcrossSlots({
|
||||||
|
fromSlot,
|
||||||
|
toSlot: sectionToSlot,
|
||||||
|
toSectionIdx: insertBeforeIdx,
|
||||||
|
parallelPhaseRunOrderIndex: po,
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
patch((prev) => {
|
patch((prev) => {
|
||||||
const po = Number(phaseRunMove.phaseOrderIndex) || 0
|
const poLocal = Number(phaseRunMove.phaseOrderIndex) || 0
|
||||||
let next = moveParallelPhaseRunToInsertBefore(prev, po, insertBeforeIdx)
|
let next = moveParallelPhaseRunToInsertBefore(prev, poLocal, insertBeforeIdx)
|
||||||
if (enableParallelPhaseControls) next = afterSectionReorderParallelGuard(prev, next)
|
if (enableParallelPhaseControls) next = afterSectionReorderParallelGuard(prev, next)
|
||||||
return next
|
return next
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,9 @@ import {
|
||||||
buildPlanPayloadForSave,
|
buildPlanPayloadForSave,
|
||||||
hydrateExercisePlanningRow,
|
hydrateExercisePlanningRow,
|
||||||
reorderBlockIntoParallelStreamEnd,
|
reorderBlockIntoParallelStreamEnd,
|
||||||
|
indicesOfParallelPhase,
|
||||||
|
reorderSectionBeforeParallelRunAsWholeGroup,
|
||||||
|
reorderSectionAsFirstInParallelStream,
|
||||||
} from '../utils/trainingUnitSectionsForm'
|
} from '../utils/trainingUnitSectionsForm'
|
||||||
|
|
||||||
const DND_FW_SLOT = 'application/x-shinkan-framework-slot'
|
const DND_FW_SLOT = 'application/x-shinkan-framework-slot'
|
||||||
|
|
@ -561,7 +564,17 @@ export default function TrainingFrameworkProgramEditPage() {
|
||||||
}
|
}
|
||||||
|
|
||||||
const moveSectionsAcrossFrameworkSlots = useCallback(
|
const moveSectionsAcrossFrameworkSlots = useCallback(
|
||||||
({ fromSlot, fromSectionIdx, toSlot, toSectionIdx, toParallelStream }) => {
|
(payload) => {
|
||||||
|
const {
|
||||||
|
fromSlot,
|
||||||
|
fromSectionIdx,
|
||||||
|
toSlot,
|
||||||
|
toSectionIdx,
|
||||||
|
toParallelStream,
|
||||||
|
parallelPhaseRunOrderIndex,
|
||||||
|
insertBeforeParallelInTarget,
|
||||||
|
firstInParallelStreamInTarget,
|
||||||
|
} = payload
|
||||||
setForm((prev) => {
|
setForm((prev) => {
|
||||||
const slots = prev.slots.map((sl) => ({
|
const slots = prev.slots.map((sl) => ({
|
||||||
...sl,
|
...sl,
|
||||||
|
|
@ -579,15 +592,7 @@ export default function TrainingFrameworkProgramEditPage() {
|
||||||
}
|
}
|
||||||
|
|
||||||
const fromSecs = slots[fromSlot].sections
|
const fromSecs = slots[fromSlot].sections
|
||||||
if (
|
const toSecs = slots[toSlot].sections
|
||||||
typeof fromSectionIdx !== 'number' ||
|
|
||||||
fromSectionIdx < 0 ||
|
|
||||||
fromSectionIdx >= fromSecs.length
|
|
||||||
) {
|
|
||||||
return prev
|
|
||||||
}
|
|
||||||
|
|
||||||
const [block] = fromSecs.splice(fromSectionIdx, 1)
|
|
||||||
|
|
||||||
const applyParallelStreamEnd =
|
const applyParallelStreamEnd =
|
||||||
toParallelStream != null && toParallelStream.po != null && toParallelStream.so != null
|
toParallelStream != null && toParallelStream.po != null && toParallelStream.so != null
|
||||||
|
|
@ -598,6 +603,43 @@ export default function TrainingFrameworkProgramEditPage() {
|
||||||
}
|
}
|
||||||
: null
|
: 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) {
|
if (fromSlot === toSlot) {
|
||||||
let insertAt = toSectionIdx
|
let insertAt = toSectionIdx
|
||||||
if (fromSectionIdx < toSectionIdx) insertAt = toSectionIdx - 1
|
if (fromSectionIdx < toSectionIdx) insertAt = toSectionIdx - 1
|
||||||
|
|
@ -605,15 +647,45 @@ export default function TrainingFrameworkProgramEditPage() {
|
||||||
fromSecs.splice(insertAt, 0, block)
|
fromSecs.splice(insertAt, 0, block)
|
||||||
if (applyParallelStreamEnd) {
|
if (applyParallelStreamEnd) {
|
||||||
slots[fromSlot].sections = applyParallelStreamEnd(fromSecs, insertAt)
|
slots[fromSlot].sections = applyParallelStreamEnd(fromSecs, insertAt)
|
||||||
|
} else {
|
||||||
|
slots[fromSlot].sections = fromSecs
|
||||||
}
|
}
|
||||||
return { ...prev, slots }
|
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))
|
const ia = Math.max(0, Math.min(toSectionIdx, toSecs.length))
|
||||||
toSecs.splice(ia, 0, block)
|
toSecs.splice(ia, 0, block)
|
||||||
if (applyParallelStreamEnd) {
|
if (applyParallelStreamEnd) {
|
||||||
slots[toSlot].sections = applyParallelStreamEnd(toSecs, ia)
|
slots[toSlot].sections = applyParallelStreamEnd(toSecs, ia)
|
||||||
|
} else {
|
||||||
|
slots[toSlot].sections = toSecs
|
||||||
}
|
}
|
||||||
return { ...prev, slots }
|
return { ...prev, slots }
|
||||||
})
|
})
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user