@lv-x-software-house/x_view 1.2.6 → 1.2.7-dev.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +694 -518
- package/dist/index.mjs +694 -518
- package/package.json +1 -1
- package/dist/server.js +0 -480
- package/dist/server.mjs +0 -445
package/dist/index.js
CHANGED
|
@@ -15789,7 +15789,11 @@ function XViewScene({
|
|
|
15789
15789
|
};
|
|
15790
15790
|
const tweenToTarget = (0, import_react33.useCallback)(
|
|
15791
15791
|
(target, zoomFactor = 1, forcedDirection = null) => {
|
|
15792
|
-
const {
|
|
15792
|
+
const {
|
|
15793
|
+
camera: sceneCamera,
|
|
15794
|
+
controls: sceneControls,
|
|
15795
|
+
tweenGroup
|
|
15796
|
+
} = stateRef.current;
|
|
15793
15797
|
if (!sceneCamera || !sceneControls || !tweenGroup) return;
|
|
15794
15798
|
const targetPos = target instanceof THREE3.Mesh ? target.getWorldPosition(new THREE3.Vector3()) : target;
|
|
15795
15799
|
const controlsTween = new import_tween2.Tween(sceneControls.target).to(targetPos, 1500).easing(import_tween2.Easing.Cubic.Out);
|
|
@@ -16346,341 +16350,372 @@ function XViewScene({
|
|
|
16346
16350
|
},
|
|
16347
16351
|
[]
|
|
16348
16352
|
);
|
|
16349
|
-
const handleActivateReshapeLens = (0, import_react33.useCallback)(
|
|
16350
|
-
|
|
16351
|
-
|
|
16352
|
-
|
|
16353
|
-
|
|
16354
|
-
|
|
16355
|
-
|
|
16356
|
-
|
|
16357
|
-
|
|
16358
|
-
|
|
16359
|
-
if (mesh && mesh.material) {
|
|
16360
|
-
const opacityTween = new import_tween2.Tween(mesh.material).to({ opacity: 1 }, 1200).easing(import_tween2.Easing.Cubic.Out);
|
|
16361
|
-
tweenGroup.add(opacityTween);
|
|
16362
|
-
opacityTween.start();
|
|
16363
|
-
}
|
|
16364
|
-
if (mesh && mesh.userData && mesh.userData.labelObject) {
|
|
16365
|
-
mesh.userData.labelObject.visible = true;
|
|
16366
|
-
}
|
|
16367
|
-
});
|
|
16368
|
-
if (type === "Column") {
|
|
16369
|
-
const colSpacing = 80;
|
|
16370
|
-
const rowSpacing = 80;
|
|
16371
|
-
const numCols = columns || 4;
|
|
16372
|
-
activeNodeIds.forEach((id, index) => {
|
|
16373
|
-
const mesh = nodeObjects[id];
|
|
16374
|
-
const col = index % numCols;
|
|
16375
|
-
const row = Math.floor(index / numCols);
|
|
16376
|
-
const targetX = (col - (numCols - 1) / 2) * colSpacing;
|
|
16377
|
-
const targetY = -(row * rowSpacing) + 50;
|
|
16378
|
-
const posTween = new import_tween2.Tween(mesh.position).to({ x: targetX, y: targetY, z: 0 }, 1500).easing(import_tween2.Easing.Cubic.InOut);
|
|
16379
|
-
tweenGroup.add(posTween);
|
|
16380
|
-
posTween.start();
|
|
16381
|
-
if (mesh.userData.labelObject) {
|
|
16382
|
-
const labelTarget = new THREE3.Vector3(targetX, targetY, 0).add(mesh.userData.labelOffset || new THREE3.Vector3(0, 3.8, 0));
|
|
16383
|
-
const lblTween = new import_tween2.Tween(mesh.userData.labelObject.position).to(labelTarget, 1500).easing(import_tween2.Easing.Cubic.InOut);
|
|
16384
|
-
tweenGroup.add(lblTween);
|
|
16385
|
-
lblTween.start();
|
|
16386
|
-
}
|
|
16387
|
-
sumX += targetX;
|
|
16388
|
-
sumY += targetY;
|
|
16389
|
-
nodeCount++;
|
|
16390
|
-
});
|
|
16391
|
-
} else if (type === "Circle") {
|
|
16392
|
-
const total = activeNodeIds.length;
|
|
16393
|
-
const radius = Math.max(80, total * 8);
|
|
16394
|
-
activeNodeIds.forEach((id, index) => {
|
|
16353
|
+
const handleActivateReshapeLens = (0, import_react33.useCallback)(
|
|
16354
|
+
({ type, columns, centerNodeId }) => {
|
|
16355
|
+
const { nodeObjects, tweenGroup, camera, controls } = stateRef.current;
|
|
16356
|
+
if (!nodeObjects || !tweenGroup || !camera || !controls) return;
|
|
16357
|
+
const activeNodeIds = Object.keys(nodeObjects);
|
|
16358
|
+
if (activeNodeIds.length === 0) return;
|
|
16359
|
+
let sumX = 0;
|
|
16360
|
+
let sumY = 0;
|
|
16361
|
+
let nodeCount = 0;
|
|
16362
|
+
activeNodeIds.forEach((id) => {
|
|
16395
16363
|
const mesh = nodeObjects[id];
|
|
16396
|
-
|
|
16397
|
-
|
|
16398
|
-
|
|
16399
|
-
|
|
16400
|
-
|
|
16401
|
-
|
|
16402
|
-
|
|
16403
|
-
const labelTarget = new THREE3.Vector3(targetX, targetY, 0).add(mesh.userData.labelOffset || new THREE3.Vector3(0, 3.8, 0));
|
|
16404
|
-
const lblTween = new import_tween2.Tween(mesh.userData.labelObject.position).to(labelTarget, 1500).easing(import_tween2.Easing.Cubic.InOut);
|
|
16405
|
-
tweenGroup.add(lblTween);
|
|
16406
|
-
lblTween.start();
|
|
16407
|
-
}
|
|
16408
|
-
sumX += targetX;
|
|
16409
|
-
sumY += targetY;
|
|
16410
|
-
nodeCount++;
|
|
16411
|
-
});
|
|
16412
|
-
} else if (type === "Star") {
|
|
16413
|
-
const centerMesh = centerNodeId ? nodeObjects[String(centerNodeId)] : null;
|
|
16414
|
-
const orbitingNodeIds = activeNodeIds.filter((id) => id !== String(centerNodeId));
|
|
16415
|
-
const totalOrbiting = orbitingNodeIds.length;
|
|
16416
|
-
const radius = Math.max(80, totalOrbiting * 10);
|
|
16417
|
-
if (centerMesh) {
|
|
16418
|
-
const posTween = new import_tween2.Tween(centerMesh.position).to({ x: 0, y: 0, z: 0 }, 1500).easing(import_tween2.Easing.Cubic.InOut);
|
|
16419
|
-
tweenGroup.add(posTween);
|
|
16420
|
-
posTween.start();
|
|
16421
|
-
if (centerMesh.userData.labelObject) {
|
|
16422
|
-
const labelTarget = new THREE3.Vector3(0, 0, 0).add(centerMesh.userData.labelOffset || new THREE3.Vector3(0, 3.8, 0));
|
|
16423
|
-
const lblTween = new import_tween2.Tween(centerMesh.userData.labelObject.position).to(labelTarget, 1500).easing(import_tween2.Easing.Cubic.InOut);
|
|
16424
|
-
tweenGroup.add(lblTween);
|
|
16425
|
-
lblTween.start();
|
|
16364
|
+
if (mesh && mesh.material) {
|
|
16365
|
+
const opacityTween = new import_tween2.Tween(mesh.material).to({ opacity: 1 }, 1200).easing(import_tween2.Easing.Cubic.Out);
|
|
16366
|
+
tweenGroup.add(opacityTween);
|
|
16367
|
+
opacityTween.start();
|
|
16368
|
+
}
|
|
16369
|
+
if (mesh && mesh.userData && mesh.userData.labelObject) {
|
|
16370
|
+
mesh.userData.labelObject.visible = true;
|
|
16426
16371
|
}
|
|
16427
|
-
sumX += 0;
|
|
16428
|
-
sumY += 0;
|
|
16429
|
-
nodeCount++;
|
|
16430
|
-
}
|
|
16431
|
-
orbitingNodeIds.forEach((id, index) => {
|
|
16432
|
-
const mesh = nodeObjects[id];
|
|
16433
|
-
const angle = totalOrbiting > 0 ? index / totalOrbiting * Math.PI * 2 : 0;
|
|
16434
|
-
const targetX = Math.cos(angle) * radius;
|
|
16435
|
-
const targetY = Math.sin(angle) * radius;
|
|
16436
|
-
const posTween = new import_tween2.Tween(mesh.position).to({ x: targetX, y: targetY, z: 0 }, 1500).easing(import_tween2.Easing.Cubic.InOut);
|
|
16437
|
-
tweenGroup.add(posTween);
|
|
16438
|
-
posTween.start();
|
|
16439
|
-
if (mesh.userData.labelObject) {
|
|
16440
|
-
const labelTarget = new THREE3.Vector3(targetX, targetY, 0).add(mesh.userData.labelOffset || new THREE3.Vector3(0, 3.8, 0));
|
|
16441
|
-
const lblTween = new import_tween2.Tween(mesh.userData.labelObject.position).to(labelTarget, 1500).easing(import_tween2.Easing.Cubic.InOut);
|
|
16442
|
-
tweenGroup.add(lblTween);
|
|
16443
|
-
lblTween.start();
|
|
16444
|
-
}
|
|
16445
|
-
sumX += targetX;
|
|
16446
|
-
sumY += targetY;
|
|
16447
|
-
nodeCount++;
|
|
16448
16372
|
});
|
|
16449
|
-
}
|
|
16450
|
-
if (nodeCount > 0) {
|
|
16451
|
-
const centerX = sumX / nodeCount;
|
|
16452
|
-
const centerY = sumY / nodeCount;
|
|
16453
|
-
const targetFocus = new THREE3.Vector3(centerX, centerY, 0);
|
|
16454
|
-
const targetTween = new import_tween2.Tween(controls.target).to({ x: targetFocus.x, y: targetFocus.y, z: targetFocus.z }, 1500).easing(import_tween2.Easing.Cubic.InOut);
|
|
16455
|
-
tweenGroup.add(targetTween);
|
|
16456
|
-
targetTween.start();
|
|
16457
|
-
let zoomZ = 140;
|
|
16458
16373
|
if (type === "Column") {
|
|
16459
|
-
const
|
|
16460
|
-
|
|
16461
|
-
|
|
16462
|
-
|
|
16463
|
-
|
|
16464
|
-
|
|
16465
|
-
|
|
16466
|
-
|
|
16467
|
-
|
|
16468
|
-
|
|
16469
|
-
|
|
16470
|
-
|
|
16471
|
-
|
|
16472
|
-
|
|
16473
|
-
|
|
16474
|
-
|
|
16475
|
-
|
|
16476
|
-
|
|
16477
|
-
|
|
16478
|
-
|
|
16479
|
-
|
|
16480
|
-
|
|
16481
|
-
|
|
16482
|
-
|
|
16483
|
-
|
|
16484
|
-
|
|
16485
|
-
|
|
16486
|
-
|
|
16487
|
-
|
|
16488
|
-
|
|
16489
|
-
|
|
16490
|
-
|
|
16491
|
-
|
|
16492
|
-
|
|
16493
|
-
|
|
16374
|
+
const colSpacing = 80;
|
|
16375
|
+
const rowSpacing = 80;
|
|
16376
|
+
const numCols = columns || 4;
|
|
16377
|
+
activeNodeIds.forEach((id, index) => {
|
|
16378
|
+
const mesh = nodeObjects[id];
|
|
16379
|
+
const col = index % numCols;
|
|
16380
|
+
const row = Math.floor(index / numCols);
|
|
16381
|
+
const targetX = (col - (numCols - 1) / 2) * colSpacing;
|
|
16382
|
+
const targetY = -(row * rowSpacing) + 50;
|
|
16383
|
+
const posTween = new import_tween2.Tween(mesh.position).to({ x: targetX, y: targetY, z: 0 }, 1500).easing(import_tween2.Easing.Cubic.InOut);
|
|
16384
|
+
tweenGroup.add(posTween);
|
|
16385
|
+
posTween.start();
|
|
16386
|
+
if (mesh.userData.labelObject) {
|
|
16387
|
+
const labelTarget = new THREE3.Vector3(targetX, targetY, 0).add(
|
|
16388
|
+
mesh.userData.labelOffset || new THREE3.Vector3(0, 3.8, 0)
|
|
16389
|
+
);
|
|
16390
|
+
const lblTween = new import_tween2.Tween(mesh.userData.labelObject.position).to(labelTarget, 1500).easing(import_tween2.Easing.Cubic.InOut);
|
|
16391
|
+
tweenGroup.add(lblTween);
|
|
16392
|
+
lblTween.start();
|
|
16393
|
+
}
|
|
16394
|
+
sumX += targetX;
|
|
16395
|
+
sumY += targetY;
|
|
16396
|
+
nodeCount++;
|
|
16397
|
+
});
|
|
16398
|
+
} else if (type === "Circle") {
|
|
16399
|
+
const total = activeNodeIds.length;
|
|
16400
|
+
const radius = Math.max(80, total * 8);
|
|
16401
|
+
activeNodeIds.forEach((id, index) => {
|
|
16402
|
+
const mesh = nodeObjects[id];
|
|
16403
|
+
const angle = index / total * Math.PI * 2;
|
|
16404
|
+
const targetX = Math.cos(angle) * radius;
|
|
16405
|
+
const targetY = Math.sin(angle) * radius;
|
|
16406
|
+
const posTween = new import_tween2.Tween(mesh.position).to({ x: targetX, y: targetY, z: 0 }, 1500).easing(import_tween2.Easing.Cubic.InOut);
|
|
16407
|
+
tweenGroup.add(posTween);
|
|
16408
|
+
posTween.start();
|
|
16409
|
+
if (mesh.userData.labelObject) {
|
|
16410
|
+
const labelTarget = new THREE3.Vector3(targetX, targetY, 0).add(
|
|
16411
|
+
mesh.userData.labelOffset || new THREE3.Vector3(0, 3.8, 0)
|
|
16412
|
+
);
|
|
16413
|
+
const lblTween = new import_tween2.Tween(mesh.userData.labelObject.position).to(labelTarget, 1500).easing(import_tween2.Easing.Cubic.InOut);
|
|
16414
|
+
tweenGroup.add(lblTween);
|
|
16415
|
+
lblTween.start();
|
|
16416
|
+
}
|
|
16417
|
+
sumX += targetX;
|
|
16418
|
+
sumY += targetY;
|
|
16419
|
+
nodeCount++;
|
|
16420
|
+
});
|
|
16421
|
+
} else if (type === "Star") {
|
|
16422
|
+
const centerMesh = centerNodeId ? nodeObjects[String(centerNodeId)] : null;
|
|
16423
|
+
const orbitingNodeIds = activeNodeIds.filter(
|
|
16424
|
+
(id) => id !== String(centerNodeId)
|
|
16425
|
+
);
|
|
16426
|
+
const totalOrbiting = orbitingNodeIds.length;
|
|
16427
|
+
const radius = Math.max(80, totalOrbiting * 10);
|
|
16428
|
+
if (centerMesh) {
|
|
16429
|
+
const posTween = new import_tween2.Tween(centerMesh.position).to({ x: 0, y: 0, z: 0 }, 1500).easing(import_tween2.Easing.Cubic.InOut);
|
|
16430
|
+
tweenGroup.add(posTween);
|
|
16431
|
+
posTween.start();
|
|
16432
|
+
if (centerMesh.userData.labelObject) {
|
|
16433
|
+
const labelTarget = new THREE3.Vector3(0, 0, 0).add(
|
|
16434
|
+
centerMesh.userData.labelOffset || new THREE3.Vector3(0, 3.8, 0)
|
|
16435
|
+
);
|
|
16436
|
+
const lblTween = new import_tween2.Tween(centerMesh.userData.labelObject.position).to(labelTarget, 1500).easing(import_tween2.Easing.Cubic.InOut);
|
|
16437
|
+
tweenGroup.add(lblTween);
|
|
16438
|
+
lblTween.start();
|
|
16439
|
+
}
|
|
16440
|
+
sumX += 0;
|
|
16441
|
+
sumY += 0;
|
|
16442
|
+
nodeCount++;
|
|
16443
|
+
}
|
|
16444
|
+
orbitingNodeIds.forEach((id, index) => {
|
|
16445
|
+
const mesh = nodeObjects[id];
|
|
16446
|
+
const angle = totalOrbiting > 0 ? index / totalOrbiting * Math.PI * 2 : 0;
|
|
16447
|
+
const targetX = Math.cos(angle) * radius;
|
|
16448
|
+
const targetY = Math.sin(angle) * radius;
|
|
16449
|
+
const posTween = new import_tween2.Tween(mesh.position).to({ x: targetX, y: targetY, z: 0 }, 1500).easing(import_tween2.Easing.Cubic.InOut);
|
|
16450
|
+
tweenGroup.add(posTween);
|
|
16451
|
+
posTween.start();
|
|
16452
|
+
if (mesh.userData.labelObject) {
|
|
16453
|
+
const labelTarget = new THREE3.Vector3(targetX, targetY, 0).add(
|
|
16454
|
+
mesh.userData.labelOffset || new THREE3.Vector3(0, 3.8, 0)
|
|
16455
|
+
);
|
|
16456
|
+
const lblTween = new import_tween2.Tween(mesh.userData.labelObject.position).to(labelTarget, 1500).easing(import_tween2.Easing.Cubic.InOut);
|
|
16457
|
+
tweenGroup.add(lblTween);
|
|
16458
|
+
lblTween.start();
|
|
16459
|
+
}
|
|
16460
|
+
sumX += targetX;
|
|
16461
|
+
sumY += targetY;
|
|
16462
|
+
nodeCount++;
|
|
16463
|
+
});
|
|
16494
16464
|
}
|
|
16495
|
-
|
|
16496
|
-
|
|
16497
|
-
|
|
16498
|
-
|
|
16499
|
-
|
|
16500
|
-
|
|
16501
|
-
|
|
16502
|
-
|
|
16503
|
-
if (
|
|
16504
|
-
|
|
16505
|
-
|
|
16465
|
+
if (nodeCount > 0) {
|
|
16466
|
+
const centerX = sumX / nodeCount;
|
|
16467
|
+
const centerY = sumY / nodeCount;
|
|
16468
|
+
const targetFocus = new THREE3.Vector3(centerX, centerY, 0);
|
|
16469
|
+
const targetTween = new import_tween2.Tween(controls.target).to({ x: targetFocus.x, y: targetFocus.y, z: targetFocus.z }, 1500).easing(import_tween2.Easing.Cubic.InOut);
|
|
16470
|
+
tweenGroup.add(targetTween);
|
|
16471
|
+
targetTween.start();
|
|
16472
|
+
let zoomZ = 140;
|
|
16473
|
+
if (type === "Column") {
|
|
16474
|
+
const numRows = Math.ceil(nodeCount / (columns || 4));
|
|
16475
|
+
zoomZ = Math.max(140, numRows * 50);
|
|
16476
|
+
} else if (type === "Circle" || type === "Star") {
|
|
16477
|
+
const radius = Math.max(80, nodeCount * 8);
|
|
16478
|
+
zoomZ = radius * 2.5;
|
|
16479
|
+
}
|
|
16480
|
+
const camTween = new import_tween2.Tween(camera.position).to({ x: targetFocus.x, y: targetFocus.y, z: zoomZ }, 1500).easing(import_tween2.Easing.Cubic.InOut);
|
|
16481
|
+
tweenGroup.add(camTween);
|
|
16482
|
+
camTween.start();
|
|
16506
16483
|
}
|
|
16507
|
-
}
|
|
16508
|
-
|
|
16509
|
-
|
|
16510
|
-
|
|
16511
|
-
|
|
16512
|
-
|
|
16513
|
-
|
|
16514
|
-
|
|
16515
|
-
|
|
16516
|
-
|
|
16517
|
-
|
|
16518
|
-
|
|
16519
|
-
|
|
16520
|
-
|
|
16521
|
-
questsInCol.forEach((q, rowIndex) => {
|
|
16522
|
-
const timeInfo = questTimeInfos.get(String(q.id)) || { isUndated: true };
|
|
16523
|
-
let nodeY;
|
|
16524
|
-
if (!timeInfo.isUndated) {
|
|
16525
|
-
nodeY = timeToYMap.get(timeInfo.startDate.getTime());
|
|
16526
|
-
} else {
|
|
16527
|
-
const undatedOffset = sortedTimePoints.length > 0 ? sortedTimePoints.length * 5 : 0;
|
|
16528
|
-
nodeY = -40 - rowIndex * QUEST_LENS_ROW_SPACING - undatedOffset;
|
|
16529
|
-
}
|
|
16530
|
-
const posKey = `${statusName}_${nodeY}`;
|
|
16531
|
-
if (!positionGroups.has(posKey)) positionGroups.set(posKey, []);
|
|
16532
|
-
positionGroups.get(posKey).push(String(q.id));
|
|
16484
|
+
},
|
|
16485
|
+
[]
|
|
16486
|
+
);
|
|
16487
|
+
const handleActivateQuestLens = (0, import_react33.useCallback)(
|
|
16488
|
+
({ assigneeId, status: status2, milestoneId }) => {
|
|
16489
|
+
var _a2;
|
|
16490
|
+
const { nodeObjects, tweenGroup, graphGroup } = stateRef.current;
|
|
16491
|
+
if (!nodeObjects || !tweenGroup || !graphGroup) return;
|
|
16492
|
+
const allQuests = ((_a2 = sceneDataRef.current) == null ? void 0 : _a2.quest_nodes) || [];
|
|
16493
|
+
const filteredQuests = allQuests.filter((q) => {
|
|
16494
|
+
const matchAssignee = !assigneeId || String(q.assignee_id) === String(assigneeId);
|
|
16495
|
+
const matchStatus = !status2 ? q.status !== "Done" : String(q.status) === String(status2);
|
|
16496
|
+
const matchMilestone = !milestoneId || q.milestone_ids && q.milestone_ids.includes(milestoneId);
|
|
16497
|
+
return matchAssignee && matchStatus && matchMilestone;
|
|
16533
16498
|
});
|
|
16534
|
-
|
|
16535
|
-
|
|
16536
|
-
|
|
16537
|
-
if (oldLabel) {
|
|
16538
|
-
mesh.remove(oldLabel);
|
|
16539
|
-
if (oldLabel.material) oldLabel.material.dispose();
|
|
16540
|
-
}
|
|
16541
|
-
if (mesh.userData.timelineIntervalBar) {
|
|
16542
|
-
if (graphGroup) graphGroup.remove(mesh.userData.timelineIntervalBar);
|
|
16543
|
-
mesh.userData.timelineIntervalBar = null;
|
|
16544
|
-
}
|
|
16545
|
-
if (mesh.userData.timelineEndLabel) {
|
|
16546
|
-
if (graphGroup) graphGroup.remove(mesh.userData.timelineEndLabel);
|
|
16547
|
-
mesh.userData.timelineEndLabel = null;
|
|
16548
|
-
}
|
|
16549
|
-
});
|
|
16550
|
-
const nonFilteredNodeIds = Object.keys(nodeObjects).filter((id) => !filteredQuests.some((q) => String(q.id) === String(id)));
|
|
16551
|
-
const COMMON_START_X = startX - 100;
|
|
16552
|
-
const COMMON_COL_SPACING = 30;
|
|
16553
|
-
const COMMON_ROW_SPACING = 35;
|
|
16554
|
-
const MAX_COMMON_ROWS = 15;
|
|
16555
|
-
nonFilteredNodeIds.forEach((id, idx) => {
|
|
16556
|
-
const mesh = nodeObjects[id];
|
|
16557
|
-
if (!mesh) return;
|
|
16558
|
-
const col = Math.floor(idx / MAX_COMMON_ROWS);
|
|
16559
|
-
const row = idx % MAX_COMMON_ROWS;
|
|
16560
|
-
const targetX = COMMON_START_X - col * COMMON_COL_SPACING;
|
|
16561
|
-
const targetY = -(row * COMMON_ROW_SPACING) + 50;
|
|
16562
|
-
const targetZ = 0;
|
|
16563
|
-
if (mesh.material) {
|
|
16564
|
-
const opacityTween = new import_tween2.Tween(mesh.material).to({ opacity: 1 }, 1200).easing(import_tween2.Easing.Cubic.Out);
|
|
16565
|
-
tweenGroup.add(opacityTween);
|
|
16566
|
-
opacityTween.start();
|
|
16567
|
-
}
|
|
16568
|
-
if (mesh.userData.labelObject) {
|
|
16569
|
-
mesh.userData.labelObject.visible = true;
|
|
16570
|
-
const labelTargetPos = new THREE3.Vector3(targetX, targetY, targetZ).add(
|
|
16571
|
-
mesh.userData.labelOffset || new THREE3.Vector3(0, 3.8, 0)
|
|
16572
|
-
);
|
|
16573
|
-
const labelTween = new import_tween2.Tween(mesh.userData.labelObject.position).to(labelTargetPos, 1500).easing(import_tween2.Easing.Cubic.InOut);
|
|
16574
|
-
tweenGroup.add(labelTween);
|
|
16575
|
-
labelTween.start();
|
|
16499
|
+
if (filteredQuests.length === 0) {
|
|
16500
|
+
console.warn("Nenhuma quest encontrada para os filtros selecionados.");
|
|
16501
|
+
return;
|
|
16576
16502
|
}
|
|
16577
|
-
const
|
|
16578
|
-
|
|
16579
|
-
|
|
16580
|
-
|
|
16581
|
-
|
|
16582
|
-
|
|
16583
|
-
|
|
16584
|
-
if (
|
|
16585
|
-
|
|
16586
|
-
tweenGroup.add(fadeInTween);
|
|
16587
|
-
fadeInTween.start();
|
|
16503
|
+
const questsByStatus = {
|
|
16504
|
+
Backlog: [],
|
|
16505
|
+
"In Progress": [],
|
|
16506
|
+
Review: [],
|
|
16507
|
+
Done: []
|
|
16508
|
+
};
|
|
16509
|
+
filteredQuests.forEach((q) => {
|
|
16510
|
+
if (questsByStatus[q.status]) {
|
|
16511
|
+
questsByStatus[q.status].push(q);
|
|
16588
16512
|
}
|
|
16589
|
-
|
|
16590
|
-
|
|
16513
|
+
});
|
|
16514
|
+
const questTimeInfos = /* @__PURE__ */ new Map();
|
|
16515
|
+
const allActiveTimePoints = /* @__PURE__ */ new Set();
|
|
16516
|
+
filteredQuests.forEach((q) => {
|
|
16517
|
+
const info = parseDateProp(q.Date);
|
|
16518
|
+
questTimeInfos.set(String(q.id), info);
|
|
16519
|
+
if (!info.isUndated) {
|
|
16520
|
+
allActiveTimePoints.add(info.startDate.getTime());
|
|
16521
|
+
if (info.endDate && info.type === "interval") {
|
|
16522
|
+
allActiveTimePoints.add(info.endDate.getTime());
|
|
16523
|
+
}
|
|
16591
16524
|
}
|
|
16592
|
-
}
|
|
16593
|
-
|
|
16594
|
-
|
|
16595
|
-
|
|
16596
|
-
const
|
|
16597
|
-
|
|
16598
|
-
|
|
16599
|
-
|
|
16600
|
-
|
|
16601
|
-
|
|
16602
|
-
|
|
16603
|
-
|
|
16604
|
-
|
|
16605
|
-
|
|
16606
|
-
|
|
16607
|
-
|
|
16608
|
-
|
|
16609
|
-
|
|
16610
|
-
|
|
16611
|
-
|
|
16612
|
-
|
|
16613
|
-
|
|
16614
|
-
|
|
16615
|
-
|
|
16616
|
-
|
|
16617
|
-
|
|
16618
|
-
tweenGroup.add(lensTween);
|
|
16619
|
-
lensTween.start();
|
|
16620
|
-
sumX += finalX;
|
|
16621
|
-
sumY += targetY;
|
|
16622
|
-
questCount++;
|
|
16623
|
-
if (!timeInfo.isUndated && timeInfo.label && !mesh.getObjectByName("questDateLabel")) {
|
|
16624
|
-
const dateSprite = createTextSprite(timeInfo.label, 36);
|
|
16625
|
-
dateSprite.name = "questDateLabel";
|
|
16626
|
-
dateSprite.position.set(0, -5.5, 0);
|
|
16627
|
-
mesh.add(dateSprite);
|
|
16628
|
-
}
|
|
16629
|
-
if (timeInfo.type === "interval" && timeToYMap.has(timeInfo.endDate.getTime())) {
|
|
16630
|
-
const endY = timeToYMap.get(timeInfo.endDate.getTime());
|
|
16631
|
-
if (Math.abs(endY - targetY) > 0.1) {
|
|
16632
|
-
const barHeight = Math.abs(endY - targetY);
|
|
16633
|
-
const barGeometry = new THREE3.CylinderGeometry(
|
|
16634
|
-
TIMELINE_INTERVAL_BAR_RADIUS,
|
|
16635
|
-
TIMELINE_INTERVAL_BAR_RADIUS,
|
|
16636
|
-
1,
|
|
16637
|
-
16
|
|
16638
|
-
);
|
|
16639
|
-
const barMaterial = new THREE3.MeshStandardMaterial({
|
|
16640
|
-
color: TIMELINE_GOLD_COLOR,
|
|
16641
|
-
emissive: 12092939,
|
|
16642
|
-
emissiveIntensity: 0.4,
|
|
16643
|
-
transparent: true,
|
|
16644
|
-
opacity: TIMELINE_INTERVAL_BAR_OPACITY,
|
|
16645
|
-
roughness: 0.3,
|
|
16646
|
-
metalness: 0.8
|
|
16647
|
-
});
|
|
16648
|
-
const intervalBar = new THREE3.Mesh(barGeometry, barMaterial);
|
|
16649
|
-
intervalBar.userData.associatedNodeId = mesh.userData.id;
|
|
16650
|
-
intervalBar.position.set(finalX, (targetY + endY) / 2, -0.5);
|
|
16651
|
-
intervalBar.scale.y = barHeight;
|
|
16652
|
-
graphGroup.add(intervalBar);
|
|
16653
|
-
mesh.userData.timelineIntervalBar = intervalBar;
|
|
16654
|
-
const endLabel = createTextSprite(timeInfo.label.split(" - ")[1] || "", 30);
|
|
16655
|
-
endLabel.name = "timelineEndLabel";
|
|
16656
|
-
endLabel.position.set(finalX, endY + 4, 0);
|
|
16657
|
-
graphGroup.add(endLabel);
|
|
16658
|
-
mesh.userData.timelineEndLabel = endLabel;
|
|
16525
|
+
});
|
|
16526
|
+
const sortedTimePoints = Array.from(allActiveTimePoints).sort(
|
|
16527
|
+
(a, b) => a - b
|
|
16528
|
+
);
|
|
16529
|
+
const timeToYMap = /* @__PURE__ */ new Map();
|
|
16530
|
+
sortedTimePoints.forEach((ms, idx) => {
|
|
16531
|
+
timeToYMap.set(ms, idx * TIMELINE_LAYER_SPACING_Y);
|
|
16532
|
+
});
|
|
16533
|
+
const startX = -((QUEST_STATUS_ORDER.length - 1) * QUEST_LENS_COLUMN_SPACING) / 2;
|
|
16534
|
+
let sumX = 0;
|
|
16535
|
+
let sumY = 0;
|
|
16536
|
+
let questCount = 0;
|
|
16537
|
+
const positionGroups = /* @__PURE__ */ new Map();
|
|
16538
|
+
const NODE_X_GAP = 22;
|
|
16539
|
+
QUEST_STATUS_ORDER.forEach((statusName) => {
|
|
16540
|
+
const questsInCol = questsByStatus[statusName];
|
|
16541
|
+
questsInCol.forEach((q, rowIndex) => {
|
|
16542
|
+
const timeInfo = questTimeInfos.get(String(q.id)) || {
|
|
16543
|
+
isUndated: true
|
|
16544
|
+
};
|
|
16545
|
+
let nodeY;
|
|
16546
|
+
if (!timeInfo.isUndated) {
|
|
16547
|
+
nodeY = timeToYMap.get(timeInfo.startDate.getTime());
|
|
16548
|
+
} else {
|
|
16549
|
+
const undatedOffset = sortedTimePoints.length > 0 ? sortedTimePoints.length * 5 : 0;
|
|
16550
|
+
nodeY = -40 - rowIndex * QUEST_LENS_ROW_SPACING - undatedOffset;
|
|
16659
16551
|
}
|
|
16552
|
+
const posKey = `${statusName}_${nodeY}`;
|
|
16553
|
+
if (!positionGroups.has(posKey)) positionGroups.set(posKey, []);
|
|
16554
|
+
positionGroups.get(posKey).push(String(q.id));
|
|
16555
|
+
});
|
|
16556
|
+
});
|
|
16557
|
+
Object.values(nodeObjects).forEach((mesh) => {
|
|
16558
|
+
const oldLabel = mesh.getObjectByName("questDateLabel") || mesh.getObjectByName("timelineLabel");
|
|
16559
|
+
if (oldLabel) {
|
|
16560
|
+
mesh.remove(oldLabel);
|
|
16561
|
+
if (oldLabel.material) oldLabel.material.dispose();
|
|
16562
|
+
}
|
|
16563
|
+
if (mesh.userData.timelineIntervalBar) {
|
|
16564
|
+
if (graphGroup) graphGroup.remove(mesh.userData.timelineIntervalBar);
|
|
16565
|
+
mesh.userData.timelineIntervalBar = null;
|
|
16566
|
+
}
|
|
16567
|
+
if (mesh.userData.timelineEndLabel) {
|
|
16568
|
+
if (graphGroup) graphGroup.remove(mesh.userData.timelineEndLabel);
|
|
16569
|
+
mesh.userData.timelineEndLabel = null;
|
|
16570
|
+
}
|
|
16571
|
+
});
|
|
16572
|
+
const nonFilteredNodeIds = Object.keys(nodeObjects).filter(
|
|
16573
|
+
(id) => !filteredQuests.some((q) => String(q.id) === String(id))
|
|
16574
|
+
);
|
|
16575
|
+
const COMMON_START_X = startX - 100;
|
|
16576
|
+
const COMMON_COL_SPACING = 30;
|
|
16577
|
+
const COMMON_ROW_SPACING = 35;
|
|
16578
|
+
const MAX_COMMON_ROWS = 15;
|
|
16579
|
+
nonFilteredNodeIds.forEach((id, idx) => {
|
|
16580
|
+
const mesh = nodeObjects[id];
|
|
16581
|
+
if (!mesh) return;
|
|
16582
|
+
const col = Math.floor(idx / MAX_COMMON_ROWS);
|
|
16583
|
+
const row = idx % MAX_COMMON_ROWS;
|
|
16584
|
+
const targetX = COMMON_START_X - col * COMMON_COL_SPACING;
|
|
16585
|
+
const targetY = -(row * COMMON_ROW_SPACING) + 50;
|
|
16586
|
+
const targetZ = 0;
|
|
16587
|
+
if (mesh.material) {
|
|
16588
|
+
const opacityTween = new import_tween2.Tween(mesh.material).to({ opacity: 1 }, 1200).easing(import_tween2.Easing.Cubic.Out);
|
|
16589
|
+
tweenGroup.add(opacityTween);
|
|
16590
|
+
opacityTween.start();
|
|
16660
16591
|
}
|
|
16661
16592
|
if (mesh.userData.labelObject) {
|
|
16662
|
-
|
|
16663
|
-
|
|
16664
|
-
|
|
16593
|
+
mesh.userData.labelObject.visible = true;
|
|
16594
|
+
const labelTargetPos = new THREE3.Vector3(
|
|
16595
|
+
targetX,
|
|
16596
|
+
targetY,
|
|
16597
|
+
targetZ
|
|
16598
|
+
).add(mesh.userData.labelOffset || new THREE3.Vector3(0, 3.8, 0));
|
|
16665
16599
|
const labelTween = new import_tween2.Tween(mesh.userData.labelObject.position).to(labelTargetPos, 1500).easing(import_tween2.Easing.Cubic.InOut);
|
|
16666
16600
|
tweenGroup.add(labelTween);
|
|
16667
16601
|
labelTween.start();
|
|
16668
16602
|
}
|
|
16603
|
+
const sideTween = new import_tween2.Tween(mesh.position).to({ x: targetX, y: targetY, z: targetZ }, 1500).easing(import_tween2.Easing.Cubic.InOut);
|
|
16604
|
+
tweenGroup.add(sideTween);
|
|
16605
|
+
sideTween.start();
|
|
16669
16606
|
});
|
|
16670
|
-
|
|
16671
|
-
|
|
16672
|
-
|
|
16673
|
-
|
|
16674
|
-
|
|
16675
|
-
|
|
16676
|
-
|
|
16677
|
-
|
|
16678
|
-
|
|
16679
|
-
|
|
16680
|
-
|
|
16681
|
-
|
|
16682
|
-
|
|
16683
|
-
|
|
16607
|
+
filteredQuests.forEach((q) => {
|
|
16608
|
+
const mesh = nodeObjects[String(q.id)];
|
|
16609
|
+
if (mesh) {
|
|
16610
|
+
if (mesh.material) {
|
|
16611
|
+
const fadeInTween = new import_tween2.Tween(mesh.material).to({ opacity: 1 }, 1200).easing(import_tween2.Easing.Cubic.Out);
|
|
16612
|
+
tweenGroup.add(fadeInTween);
|
|
16613
|
+
fadeInTween.start();
|
|
16614
|
+
}
|
|
16615
|
+
if (mesh.userData.labelObject) {
|
|
16616
|
+
mesh.userData.labelObject.visible = true;
|
|
16617
|
+
}
|
|
16618
|
+
}
|
|
16619
|
+
});
|
|
16620
|
+
QUEST_STATUS_ORDER.forEach((statusName, colIndex) => {
|
|
16621
|
+
if (status2 && status2 !== statusName) return;
|
|
16622
|
+
const questsInCol = questsByStatus[statusName];
|
|
16623
|
+
const colX = startX + colIndex * QUEST_LENS_COLUMN_SPACING;
|
|
16624
|
+
questsInCol.forEach((q, rowIndex) => {
|
|
16625
|
+
const nodeId = String(q.id);
|
|
16626
|
+
let mesh = nodeObjects[nodeId];
|
|
16627
|
+
const timeInfo = questTimeInfos.get(nodeId) || { isUndated: true };
|
|
16628
|
+
let targetY;
|
|
16629
|
+
if (!timeInfo.isUndated) {
|
|
16630
|
+
targetY = timeToYMap.get(timeInfo.startDate.getTime());
|
|
16631
|
+
} else {
|
|
16632
|
+
const undatedOffset = sortedTimePoints.length > 0 ? sortedTimePoints.length * 5 : 0;
|
|
16633
|
+
targetY = -40 - rowIndex * QUEST_LENS_ROW_SPACING - undatedOffset;
|
|
16634
|
+
}
|
|
16635
|
+
const posKey = `${statusName}_${targetY}`;
|
|
16636
|
+
const group = positionGroups.get(posKey) || [nodeId];
|
|
16637
|
+
const indexInGroup = group.indexOf(nodeId);
|
|
16638
|
+
const xOffset = (indexInGroup - (group.length - 1) / 2) * NODE_X_GAP;
|
|
16639
|
+
const finalX = colX + xOffset;
|
|
16640
|
+
if (!mesh) {
|
|
16641
|
+
mesh = addOrUpdateNodeMesh(
|
|
16642
|
+
q,
|
|
16643
|
+
new THREE3.Vector3(finalX, 150, 0),
|
|
16644
|
+
true
|
|
16645
|
+
);
|
|
16646
|
+
}
|
|
16647
|
+
const lensTween = new import_tween2.Tween(mesh.position).to({ x: finalX, y: targetY, z: 0 }, 1500).easing(import_tween2.Easing.Cubic.InOut);
|
|
16648
|
+
tweenGroup.add(lensTween);
|
|
16649
|
+
lensTween.start();
|
|
16650
|
+
sumX += finalX;
|
|
16651
|
+
sumY += targetY;
|
|
16652
|
+
questCount++;
|
|
16653
|
+
if (!timeInfo.isUndated && timeInfo.label && !mesh.getObjectByName("questDateLabel")) {
|
|
16654
|
+
const dateSprite = createTextSprite(timeInfo.label, 36);
|
|
16655
|
+
dateSprite.name = "questDateLabel";
|
|
16656
|
+
dateSprite.position.set(0, -5.5, 0);
|
|
16657
|
+
mesh.add(dateSprite);
|
|
16658
|
+
}
|
|
16659
|
+
if (timeInfo.type === "interval" && timeToYMap.has(timeInfo.endDate.getTime())) {
|
|
16660
|
+
const endY = timeToYMap.get(timeInfo.endDate.getTime());
|
|
16661
|
+
if (Math.abs(endY - targetY) > 0.1) {
|
|
16662
|
+
const barHeight = Math.abs(endY - targetY);
|
|
16663
|
+
const barGeometry = new THREE3.CylinderGeometry(
|
|
16664
|
+
TIMELINE_INTERVAL_BAR_RADIUS,
|
|
16665
|
+
TIMELINE_INTERVAL_BAR_RADIUS,
|
|
16666
|
+
1,
|
|
16667
|
+
16
|
|
16668
|
+
);
|
|
16669
|
+
const barMaterial = new THREE3.MeshStandardMaterial({
|
|
16670
|
+
color: TIMELINE_GOLD_COLOR,
|
|
16671
|
+
emissive: 12092939,
|
|
16672
|
+
emissiveIntensity: 0.4,
|
|
16673
|
+
transparent: true,
|
|
16674
|
+
opacity: TIMELINE_INTERVAL_BAR_OPACITY,
|
|
16675
|
+
roughness: 0.3,
|
|
16676
|
+
metalness: 0.8
|
|
16677
|
+
});
|
|
16678
|
+
const intervalBar = new THREE3.Mesh(barGeometry, barMaterial);
|
|
16679
|
+
intervalBar.userData.associatedNodeId = mesh.userData.id;
|
|
16680
|
+
intervalBar.position.set(finalX, (targetY + endY) / 2, -0.5);
|
|
16681
|
+
intervalBar.scale.y = barHeight;
|
|
16682
|
+
graphGroup.add(intervalBar);
|
|
16683
|
+
mesh.userData.timelineIntervalBar = intervalBar;
|
|
16684
|
+
const endLabel = createTextSprite(
|
|
16685
|
+
timeInfo.label.split(" - ")[1] || "",
|
|
16686
|
+
30
|
|
16687
|
+
);
|
|
16688
|
+
endLabel.name = "timelineEndLabel";
|
|
16689
|
+
endLabel.position.set(finalX, endY + 4, 0);
|
|
16690
|
+
graphGroup.add(endLabel);
|
|
16691
|
+
mesh.userData.timelineEndLabel = endLabel;
|
|
16692
|
+
}
|
|
16693
|
+
}
|
|
16694
|
+
if (mesh.userData.labelObject) {
|
|
16695
|
+
const labelTargetPos = new THREE3.Vector3(finalX, targetY, 0).add(
|
|
16696
|
+
mesh.userData.labelOffset || new THREE3.Vector3(0, 3.8, 0)
|
|
16697
|
+
);
|
|
16698
|
+
const labelTween = new import_tween2.Tween(mesh.userData.labelObject.position).to(labelTargetPos, 1500).easing(import_tween2.Easing.Cubic.InOut);
|
|
16699
|
+
tweenGroup.add(labelTween);
|
|
16700
|
+
labelTween.start();
|
|
16701
|
+
}
|
|
16702
|
+
});
|
|
16703
|
+
});
|
|
16704
|
+
if (questCount > 0) {
|
|
16705
|
+
const { camera: sceneCamera, controls: sceneControls } = stateRef.current;
|
|
16706
|
+
const centerX = sumX / questCount;
|
|
16707
|
+
const centerY = sumY / questCount;
|
|
16708
|
+
const targetFocus = new THREE3.Vector3(centerX, centerY, 0);
|
|
16709
|
+
const targetTween = new import_tween2.Tween(sceneControls.target).to({ x: targetFocus.x, y: targetFocus.y, z: targetFocus.z }, 1500).easing(import_tween2.Easing.Cubic.InOut);
|
|
16710
|
+
tweenGroup.add(targetTween);
|
|
16711
|
+
targetTween.start();
|
|
16712
|
+
const camTween = new import_tween2.Tween(sceneCamera.position).to({ x: targetFocus.x, y: targetFocus.y, z: 140 }, 1500).easing(import_tween2.Easing.Cubic.InOut);
|
|
16713
|
+
tweenGroup.add(camTween);
|
|
16714
|
+
camTween.start();
|
|
16715
|
+
}
|
|
16716
|
+
},
|
|
16717
|
+
[addOrUpdateNodeMesh]
|
|
16718
|
+
);
|
|
16684
16719
|
(0, import_react33.useEffect)(() => {
|
|
16685
16720
|
if (!isInitialized || !sceneDataRef.current) return;
|
|
16686
16721
|
const currentMount = mountRef.current;
|
|
@@ -17065,7 +17100,9 @@ function XViewScene({
|
|
|
17065
17100
|
const clickedNodeId = String(clickedNode.userData.id);
|
|
17066
17101
|
const parentId = String(currentSelectedParent);
|
|
17067
17102
|
if (clickedNodeId === parentId) {
|
|
17068
|
-
alert(
|
|
17103
|
+
alert(
|
|
17104
|
+
"Erro: N\xE3o \xE9 poss\xEDvel adicionar um Node como filho dele mesmo."
|
|
17105
|
+
);
|
|
17069
17106
|
return;
|
|
17070
17107
|
}
|
|
17071
17108
|
const parentInfo = stateRef.current.nodeIdToParentFileMap.get(clickedNodeId);
|
|
@@ -17414,7 +17451,11 @@ function XViewScene({
|
|
|
17414
17451
|
ancestryData: ancestryDataRef.current
|
|
17415
17452
|
});
|
|
17416
17453
|
(_b2 = stateRef.current.tweenGroup) == null ? void 0 : _b2.update(time);
|
|
17417
|
-
const {
|
|
17454
|
+
const {
|
|
17455
|
+
keysPressed,
|
|
17456
|
+
controls: sceneControls,
|
|
17457
|
+
camera: sceneCamera
|
|
17458
|
+
} = stateRef.current;
|
|
17418
17459
|
if (sceneControls && keysPressed) {
|
|
17419
17460
|
const panSpeed = 1.5;
|
|
17420
17461
|
const rotateSpeed = 0.02;
|
|
@@ -17438,10 +17479,18 @@ function XViewScene({
|
|
|
17438
17479
|
offset.multiplyScalar(factor);
|
|
17439
17480
|
sceneCamera.position.copy(sceneControls.target).add(offset);
|
|
17440
17481
|
} else if (!isCtrl && !isShift && (dirX !== 0 || dirY !== 0)) {
|
|
17441
|
-
const distance = sceneCamera.position.distanceTo(
|
|
17482
|
+
const distance = sceneCamera.position.distanceTo(
|
|
17483
|
+
sceneControls.target
|
|
17484
|
+
);
|
|
17442
17485
|
const currentPanSpeed = panSpeed * (distance / 100);
|
|
17443
|
-
const vecX = new THREE3.Vector3().setFromMatrixColumn(
|
|
17444
|
-
|
|
17486
|
+
const vecX = new THREE3.Vector3().setFromMatrixColumn(
|
|
17487
|
+
sceneCamera.matrix,
|
|
17488
|
+
0
|
|
17489
|
+
);
|
|
17490
|
+
const vecY = new THREE3.Vector3().setFromMatrixColumn(
|
|
17491
|
+
sceneCamera.matrix,
|
|
17492
|
+
1
|
|
17493
|
+
);
|
|
17445
17494
|
vecX.multiplyScalar(dirX * currentPanSpeed);
|
|
17446
17495
|
vecY.multiplyScalar(dirY * currentPanSpeed);
|
|
17447
17496
|
sceneCamera.position.add(vecX).add(vecY);
|
|
@@ -17838,115 +17887,143 @@ function XViewScene({
|
|
|
17838
17887
|
const handleStartVersioning = (nodeData) => {
|
|
17839
17888
|
userActionHandlers.handleStartVersioning(actionHandlerContext, nodeData);
|
|
17840
17889
|
};
|
|
17841
|
-
const handleStartQuestQuick = (0, import_react33.useCallback)(
|
|
17842
|
-
|
|
17843
|
-
|
|
17844
|
-
|
|
17845
|
-
|
|
17846
|
-
|
|
17847
|
-
|
|
17848
|
-
|
|
17849
|
-
|
|
17850
|
-
|
|
17851
|
-
|
|
17852
|
-
|
|
17853
|
-
|
|
17854
|
-
|
|
17855
|
-
|
|
17856
|
-
|
|
17857
|
-
|
|
17858
|
-
|
|
17859
|
-
|
|
17860
|
-
|
|
17861
|
-
|
|
17862
|
-
|
|
17863
|
-
|
|
17864
|
-
|
|
17865
|
-
|
|
17866
|
-
|
|
17867
|
-
|
|
17868
|
-
|
|
17869
|
-
|
|
17870
|
-
|
|
17871
|
-
|
|
17872
|
-
|
|
17873
|
-
|
|
17874
|
-
|
|
17875
|
-
|
|
17876
|
-
|
|
17877
|
-
|
|
17878
|
-
|
|
17879
|
-
|
|
17880
|
-
|
|
17881
|
-
|
|
17882
|
-
|
|
17883
|
-
|
|
17884
|
-
|
|
17885
|
-
|
|
17886
|
-
|
|
17887
|
-
}
|
|
17888
|
-
|
|
17889
|
-
|
|
17890
|
-
|
|
17891
|
-
|
|
17892
|
-
|
|
17893
|
-
|
|
17894
|
-
|
|
17895
|
-
|
|
17896
|
-
|
|
17897
|
-
|
|
17898
|
-
|
|
17899
|
-
|
|
17900
|
-
|
|
17901
|
-
|
|
17902
|
-
|
|
17903
|
-
|
|
17904
|
-
|
|
17905
|
-
|
|
17906
|
-
|
|
17890
|
+
const handleStartQuestQuick = (0, import_react33.useCallback)(
|
|
17891
|
+
(questNode) => {
|
|
17892
|
+
var _a2, _b2, _c2;
|
|
17893
|
+
if (!questNode || !actionHandlerContext) return;
|
|
17894
|
+
const allParentNodes = Object.values(parentDataRef.current).flatMap(
|
|
17895
|
+
(fileData) => fileData.nodes || []
|
|
17896
|
+
);
|
|
17897
|
+
const blockCheck = isQuestBlocked(questNode, allParentNodes);
|
|
17898
|
+
if (blockCheck.isBlocked) {
|
|
17899
|
+
alert(
|
|
17900
|
+
`Esta quest n\xE3o pode ser iniciada pois possui depend\xEAncias pendentes: ${blockCheck.pendingDependencies.map((d) => d.raw_title || d.name).join(", ")}`
|
|
17901
|
+
);
|
|
17902
|
+
return;
|
|
17903
|
+
}
|
|
17904
|
+
const {
|
|
17905
|
+
labelObject,
|
|
17906
|
+
labelOffset,
|
|
17907
|
+
aura,
|
|
17908
|
+
borderRing,
|
|
17909
|
+
timelineIntervalBar,
|
|
17910
|
+
timelineEndLabel,
|
|
17911
|
+
...cleanQuestNode
|
|
17912
|
+
} = questNode;
|
|
17913
|
+
const newTimeline = [
|
|
17914
|
+
...cleanQuestNode.timeline || [],
|
|
17915
|
+
createTimelineEntry(
|
|
17916
|
+
((_a2 = session == null ? void 0 : session.user) == null ? void 0 : _a2.id) || "unknown",
|
|
17917
|
+
`Status "In Progress" - Respons\xE1vel: ${((_b2 = session == null ? void 0 : session.user) == null ? void 0 : _b2.name) || "usu\xE1rio"}`,
|
|
17918
|
+
"status_changed"
|
|
17919
|
+
)
|
|
17920
|
+
];
|
|
17921
|
+
const updatedNode = {
|
|
17922
|
+
...cleanQuestNode,
|
|
17923
|
+
status: "In Progress",
|
|
17924
|
+
color: "#eab308",
|
|
17925
|
+
assignee_id: (_c2 = session == null ? void 0 : session.user) == null ? void 0 : _c2.id,
|
|
17926
|
+
timeline: newTimeline
|
|
17927
|
+
};
|
|
17928
|
+
if (userActionHandlers.handleSaveNodeDetails) {
|
|
17929
|
+
userActionHandlers.handleSaveNodeDetails(
|
|
17930
|
+
actionHandlerContext,
|
|
17931
|
+
updatedNode,
|
|
17932
|
+
true
|
|
17933
|
+
);
|
|
17934
|
+
}
|
|
17935
|
+
setDetailsNode(updatedNode);
|
|
17936
|
+
},
|
|
17937
|
+
[session, actionHandlerContext]
|
|
17938
|
+
);
|
|
17939
|
+
const handleFinishQuestQuick = (0, import_react33.useCallback)(
|
|
17940
|
+
(questNode) => {
|
|
17941
|
+
var _a2, _b2, _c2, _d2;
|
|
17942
|
+
if (!questNode || !actionHandlerContext) return;
|
|
17943
|
+
const {
|
|
17944
|
+
labelObject,
|
|
17945
|
+
labelOffset,
|
|
17946
|
+
aura,
|
|
17947
|
+
borderRing,
|
|
17948
|
+
timelineIntervalBar,
|
|
17949
|
+
timelineEndLabel,
|
|
17950
|
+
...cleanQuestNode
|
|
17951
|
+
} = questNode;
|
|
17952
|
+
let nextAssigneeId = cleanQuestNode.assignee_id;
|
|
17953
|
+
let nextStatus = "Done";
|
|
17954
|
+
let newTimeline = [...cleanQuestNode.timeline || []];
|
|
17955
|
+
const reviewStack = [...cleanQuestNode.reviewStack || []];
|
|
17956
|
+
const currentReviewerIdx = reviewStack.findIndex(
|
|
17957
|
+
(r) => r.status !== "completed"
|
|
17958
|
+
);
|
|
17959
|
+
let nextIdxToAssign = 0;
|
|
17960
|
+
if (currentReviewerIdx !== -1 && reviewStack[currentReviewerIdx].userId === cleanQuestNode.assignee_id) {
|
|
17961
|
+
reviewStack[currentReviewerIdx].status = "completed";
|
|
17962
|
+
nextIdxToAssign = currentReviewerIdx + 1;
|
|
17907
17963
|
} else {
|
|
17908
|
-
|
|
17909
|
-
|
|
17910
|
-
|
|
17964
|
+
nextIdxToAssign = currentReviewerIdx !== -1 ? currentReviewerIdx : reviewStack.length;
|
|
17965
|
+
}
|
|
17966
|
+
if (nextIdxToAssign < reviewStack.length) {
|
|
17967
|
+
const remainingMandatory = reviewStack.slice(nextIdxToAssign).some((r) => r.mandatory);
|
|
17968
|
+
const hasAnyMandatory = reviewStack.some((r) => r.mandatory);
|
|
17969
|
+
if (!hasAnyMandatory || remainingMandatory) {
|
|
17970
|
+
const nextReviewer = reviewStack[nextIdxToAssign];
|
|
17971
|
+
nextAssigneeId = nextReviewer.userId;
|
|
17972
|
+
nextStatus = "Review";
|
|
17973
|
+
} else {
|
|
17974
|
+
nextStatus = "Done";
|
|
17975
|
+
for (let i = nextIdxToAssign; i < reviewStack.length; i++) {
|
|
17976
|
+
reviewStack[i].status = "skipped";
|
|
17977
|
+
}
|
|
17911
17978
|
}
|
|
17979
|
+
} else {
|
|
17980
|
+
nextStatus = "Done";
|
|
17912
17981
|
}
|
|
17913
|
-
|
|
17914
|
-
|
|
17915
|
-
|
|
17916
|
-
|
|
17917
|
-
|
|
17918
|
-
|
|
17919
|
-
|
|
17920
|
-
|
|
17921
|
-
|
|
17922
|
-
|
|
17923
|
-
)
|
|
17924
|
-
|
|
17925
|
-
|
|
17926
|
-
|
|
17927
|
-
|
|
17928
|
-
|
|
17929
|
-
|
|
17930
|
-
(
|
|
17931
|
-
|
|
17932
|
-
|
|
17933
|
-
|
|
17934
|
-
|
|
17935
|
-
|
|
17936
|
-
|
|
17937
|
-
|
|
17938
|
-
|
|
17939
|
-
|
|
17940
|
-
|
|
17941
|
-
|
|
17942
|
-
|
|
17943
|
-
|
|
17944
|
-
|
|
17945
|
-
|
|
17946
|
-
|
|
17947
|
-
|
|
17948
|
-
|
|
17949
|
-
|
|
17982
|
+
if (nextStatus === "Review") {
|
|
17983
|
+
const nextReviewerName = ((_a2 = viewMembers.find((m) => m.id === nextAssigneeId)) == null ? void 0 : _a2.name) || "revisor";
|
|
17984
|
+
newTimeline.push(
|
|
17985
|
+
createTimelineEntry(
|
|
17986
|
+
"system",
|
|
17987
|
+
`Status "Review" - Respons\xE1vel: ${nextReviewerName}`,
|
|
17988
|
+
"status_changed",
|
|
17989
|
+
{ metadata: { to_assignee_id: nextAssigneeId } }
|
|
17990
|
+
)
|
|
17991
|
+
);
|
|
17992
|
+
} else if (nextStatus === "Done") {
|
|
17993
|
+
const finisherName = ((_b2 = viewMembers.find(
|
|
17994
|
+
(m) => {
|
|
17995
|
+
var _a3;
|
|
17996
|
+
return m.id === (((_a3 = session == null ? void 0 : session.user) == null ? void 0 : _a3.id) || cleanQuestNode.assignee_id);
|
|
17997
|
+
}
|
|
17998
|
+
)) == null ? void 0 : _b2.name) || ((_c2 = session == null ? void 0 : session.user) == null ? void 0 : _c2.name) || "respons\xE1vel";
|
|
17999
|
+
newTimeline.push(
|
|
18000
|
+
createTimelineEntry(
|
|
18001
|
+
((_d2 = session == null ? void 0 : session.user) == null ? void 0 : _d2.id) || cleanQuestNode.assignee_id,
|
|
18002
|
+
`Status "Done" - Finalizado por ${finisherName}`,
|
|
18003
|
+
"status_changed"
|
|
18004
|
+
)
|
|
18005
|
+
);
|
|
18006
|
+
}
|
|
18007
|
+
const updatedNode = {
|
|
18008
|
+
...cleanQuestNode,
|
|
18009
|
+
status: nextStatus,
|
|
18010
|
+
color: nextStatus === "Done" ? "#22c55e" : "#a855f7",
|
|
18011
|
+
assignee_id: nextAssigneeId,
|
|
18012
|
+
reviewStack,
|
|
18013
|
+
timeline: newTimeline
|
|
18014
|
+
};
|
|
18015
|
+
if (userActionHandlers.handleSaveNodeDetails) {
|
|
18016
|
+
userActionHandlers.handleSaveNodeDetails(
|
|
18017
|
+
actionHandlerContext,
|
|
18018
|
+
updatedNode
|
|
18019
|
+
);
|
|
18020
|
+
}
|
|
18021
|
+
if (detailsNode && String(detailsNode.id) === String(cleanQuestNode.id)) {
|
|
18022
|
+
setDetailsNode(null);
|
|
18023
|
+
}
|
|
18024
|
+
},
|
|
18025
|
+
[session, actionHandlerContext, viewMembers, detailsNode]
|
|
18026
|
+
);
|
|
17950
18027
|
const handleCancelQuest = (0, import_react33.useCallback)(() => {
|
|
17951
18028
|
const { graphGroup, ghostElements } = stateRef.current;
|
|
17952
18029
|
if (ghostElements.node && graphGroup) {
|
|
@@ -17997,48 +18074,56 @@ function XViewScene({
|
|
|
17997
18074
|
if (questNodeId && sceneConfigId) {
|
|
17998
18075
|
const sceneData = sceneDataRef.current;
|
|
17999
18076
|
if (sceneData && sceneData.quest_nodes) {
|
|
18000
|
-
const questIndex = sceneData.quest_nodes.findIndex(
|
|
18077
|
+
const questIndex = sceneData.quest_nodes.findIndex(
|
|
18078
|
+
(q) => String(q.id) === String(questNodeId)
|
|
18079
|
+
);
|
|
18001
18080
|
if (questIndex !== -1) {
|
|
18002
18081
|
sceneData.quest_nodes[questIndex].quest_tree = formattedTree;
|
|
18003
18082
|
sceneData.quest_nodes[questIndex].quest_abstraction_tree = formattedAbstractionTree;
|
|
18004
18083
|
if (parentDataRef.current[sceneConfigId]) {
|
|
18005
|
-
const parentIndex = parentDataRef.current[sceneConfigId].nodes.findIndex(
|
|
18006
|
-
(q) => String(q.id) === String(questNodeId)
|
|
18007
|
-
);
|
|
18084
|
+
const parentIndex = parentDataRef.current[sceneConfigId].nodes.findIndex((q) => String(q.id) === String(questNodeId));
|
|
18008
18085
|
if (parentIndex !== -1) {
|
|
18009
18086
|
parentDataRef.current[sceneConfigId].nodes[parentIndex].quest_tree = formattedTree;
|
|
18010
18087
|
parentDataRef.current[sceneConfigId].nodes[parentIndex].quest_abstraction_tree = formattedAbstractionTree;
|
|
18011
18088
|
}
|
|
18012
18089
|
}
|
|
18013
|
-
|
|
18014
|
-
|
|
18015
|
-
|
|
18016
|
-
|
|
18017
|
-
|
|
18018
|
-
|
|
18019
|
-
|
|
18020
|
-
|
|
18021
|
-
|
|
18022
|
-
|
|
18023
|
-
|
|
18024
|
-
|
|
18025
|
-
|
|
18026
|
-
|
|
18027
|
-
|
|
18028
|
-
|
|
18029
|
-
|
|
18030
|
-
|
|
18031
|
-
|
|
18032
|
-
|
|
18033
|
-
|
|
18034
|
-
|
|
18035
|
-
|
|
18036
|
-
|
|
18037
|
-
|
|
18038
|
-
|
|
18039
|
-
|
|
18040
|
-
|
|
18090
|
+
const sceneFileData = {
|
|
18091
|
+
...sceneData,
|
|
18092
|
+
nodes: sceneData.nodes || [],
|
|
18093
|
+
links: sceneData.links || [],
|
|
18094
|
+
quest_counter: sceneData.quest_counter || 1
|
|
18095
|
+
};
|
|
18096
|
+
delete sceneFileData.quest_nodes;
|
|
18097
|
+
delete sceneFileData.quest_links;
|
|
18098
|
+
delete sceneFileData.milestones;
|
|
18099
|
+
const questFileData = {
|
|
18100
|
+
nodes: sceneData.quest_nodes || [],
|
|
18101
|
+
links: sceneData.quest_links || [],
|
|
18102
|
+
milestones: sceneData.milestones || []
|
|
18103
|
+
};
|
|
18104
|
+
await save_view_data(sceneSaveUrl, sceneFileData);
|
|
18105
|
+
const questSaveUrl = sceneSaveUrl.replace(
|
|
18106
|
+
"x_view_scenes",
|
|
18107
|
+
"x_view_quests"
|
|
18108
|
+
);
|
|
18109
|
+
await save_view_data(questSaveUrl, questFileData);
|
|
18110
|
+
}
|
|
18111
|
+
const updatedNodeData = sceneData.quest_nodes[questIndex];
|
|
18112
|
+
const nodeMesh = (_a2 = stateRef.current.nodeObjects) == null ? void 0 : _a2[String(questNodeId)];
|
|
18113
|
+
if (nodeMesh) {
|
|
18114
|
+
nodeMesh.userData = {
|
|
18115
|
+
...nodeMesh.userData,
|
|
18116
|
+
...updatedNodeData
|
|
18117
|
+
};
|
|
18041
18118
|
}
|
|
18119
|
+
if (detailsNode && String(detailsNode.id) === String(questNodeId)) {
|
|
18120
|
+
setDetailsNode((prev) => ({
|
|
18121
|
+
...prev,
|
|
18122
|
+
quest_tree: formattedTree,
|
|
18123
|
+
quest_abstraction_tree: formattedAbstractionTree
|
|
18124
|
+
}));
|
|
18125
|
+
}
|
|
18126
|
+
setSceneVersion((v) => v + 1);
|
|
18042
18127
|
}
|
|
18043
18128
|
}
|
|
18044
18129
|
};
|
|
@@ -18100,21 +18185,33 @@ function XViewScene({
|
|
|
18100
18185
|
graphDataRef2.current[sceneConfigId2].nodes.push(newNode);
|
|
18101
18186
|
const sceneFileData = {
|
|
18102
18187
|
...sceneDataRef2.current,
|
|
18103
|
-
quest_nodes: graphDataRef2.current[sceneConfigId2].nodes,
|
|
18104
|
-
quest_links: graphDataRef2.current[sceneConfigId2].links,
|
|
18105
18188
|
quest_counter: currentCounter + 1
|
|
18106
18189
|
};
|
|
18190
|
+
delete sceneFileData.quest_nodes;
|
|
18191
|
+
delete sceneFileData.quest_links;
|
|
18192
|
+
delete sceneFileData.milestones;
|
|
18193
|
+
const questFileData = {
|
|
18194
|
+
nodes: graphDataRef2.current[sceneConfigId2].nodes,
|
|
18195
|
+
links: graphDataRef2.current[sceneConfigId2].links,
|
|
18196
|
+
milestones: sceneDataRef2.current.milestones || []
|
|
18197
|
+
};
|
|
18107
18198
|
try {
|
|
18108
18199
|
await actions.save_view_data(sceneSaveUrl2, sceneFileData);
|
|
18200
|
+
const questSaveUrl = sceneSaveUrl2.replace("x_view_scenes", "x_view_quests");
|
|
18201
|
+
await actions.save_view_data(questSaveUrl, questFileData);
|
|
18109
18202
|
sceneDataRef2.current.quest_counter = currentCounter + 1;
|
|
18110
18203
|
stateRef2.current.nodeIdToParentFileMap.set(String(newNode.id), {
|
|
18111
18204
|
parentFileId: sceneConfigId2,
|
|
18112
18205
|
ownerId: ownerId2,
|
|
18113
18206
|
datasetName: "Quests Internas (View)"
|
|
18114
18207
|
});
|
|
18115
|
-
sceneDataRef2.current.quest_nodes = [
|
|
18208
|
+
sceneDataRef2.current.quest_nodes = [
|
|
18209
|
+
...graphDataRef2.current[sceneConfigId2].nodes
|
|
18210
|
+
];
|
|
18116
18211
|
if (parentDataRef.current[sceneConfigId2]) {
|
|
18117
|
-
parentDataRef.current[sceneConfigId2].nodes = [
|
|
18212
|
+
parentDataRef.current[sceneConfigId2].nodes = [
|
|
18213
|
+
...graphDataRef2.current[sceneConfigId2].nodes
|
|
18214
|
+
];
|
|
18118
18215
|
}
|
|
18119
18216
|
const finalPosition = stateRef2.current.ghostElements.node ? stateRef2.current.ghostElements.node.position.clone() : stateRef2.current.controls.target.clone();
|
|
18120
18217
|
const { graphGroup, ghostElements } = stateRef2.current;
|
|
@@ -18179,11 +18276,22 @@ function XViewScene({
|
|
|
18179
18276
|
specificParentData.links.push(newLink);
|
|
18180
18277
|
const viewFilePayload = {
|
|
18181
18278
|
...sceneDataRef2.current,
|
|
18182
|
-
quest_nodes: specificParentData.nodes,
|
|
18183
|
-
quest_links: specificParentData.links,
|
|
18184
18279
|
quest_counter: sceneDataRef2.current.quest_counter || 1
|
|
18185
18280
|
};
|
|
18281
|
+
delete viewFilePayload.quest_nodes;
|
|
18282
|
+
delete viewFilePayload.quest_links;
|
|
18283
|
+
delete viewFilePayload.milestones;
|
|
18284
|
+
const questFilePayload = {
|
|
18285
|
+
nodes: specificParentData.nodes,
|
|
18286
|
+
links: specificParentData.links,
|
|
18287
|
+
milestones: sceneDataRef2.current.milestones || []
|
|
18288
|
+
};
|
|
18186
18289
|
await context.actions.save_view_data(sceneSaveUrl2, viewFilePayload);
|
|
18290
|
+
const questSaveUrl = sceneSaveUrl2.replace(
|
|
18291
|
+
"x_view_scenes",
|
|
18292
|
+
"x_view_quests"
|
|
18293
|
+
);
|
|
18294
|
+
await context.actions.save_view_data(questSaveUrl, questFilePayload);
|
|
18187
18295
|
} else {
|
|
18188
18296
|
const specificParentData = JSON.parse(
|
|
18189
18297
|
JSON.stringify(graphDataRef2.current[parentFileIdToSave])
|
|
@@ -18216,9 +18324,7 @@ function XViewScene({
|
|
|
18216
18324
|
if (line.material) line.material.dispose();
|
|
18217
18325
|
});
|
|
18218
18326
|
renderedAncestries.splice(renderIndex, 1);
|
|
18219
|
-
stateRef.current.ancestryLinks = renderedAncestries.flatMap(
|
|
18220
|
-
(a) => a.lines
|
|
18221
|
-
);
|
|
18327
|
+
stateRef.current.ancestryLinks = renderedAncestries.flatMap((a) => a.lines);
|
|
18222
18328
|
}
|
|
18223
18329
|
}, []);
|
|
18224
18330
|
const handleRenderAncestry = (0, import_react33.useCallback)(
|
|
@@ -18791,9 +18897,7 @@ function XViewScene({
|
|
|
18791
18897
|
});
|
|
18792
18898
|
};
|
|
18793
18899
|
renderVertical(fullTree, rootNodeMesh, rootTargetPos, 1);
|
|
18794
|
-
stateRef.current.ancestryLinks = renderedAncestries.flatMap(
|
|
18795
|
-
(a) => a.lines
|
|
18796
|
-
);
|
|
18900
|
+
stateRef.current.ancestryLinks = renderedAncestries.flatMap((a) => a.lines);
|
|
18797
18901
|
tweenToTarget(rootTargetPos, 0.7);
|
|
18798
18902
|
},
|
|
18799
18903
|
[
|
|
@@ -18928,10 +19032,7 @@ function XViewScene({
|
|
|
18928
19032
|
};
|
|
18929
19033
|
const descriptionText = targetAncestryInfo.description || "";
|
|
18930
19034
|
const savedSections = targetAncestryInfo.description_sections || [];
|
|
18931
|
-
const sections = parseDescriptionSections(
|
|
18932
|
-
descriptionText,
|
|
18933
|
-
savedSections
|
|
18934
|
-
);
|
|
19035
|
+
const sections = parseDescriptionSections(descriptionText, savedSections);
|
|
18935
19036
|
let focusTargetId = null;
|
|
18936
19037
|
if (popped && popped.nodeId) {
|
|
18937
19038
|
const mentionTag = `[[MENTION:node:${popped.nodeId}]]`;
|
|
@@ -19544,16 +19645,26 @@ function XViewScene({
|
|
|
19544
19645
|
const result = await save_view_data(finalSaveUrl, masterAncestryList);
|
|
19545
19646
|
if (result.success && isExternalSave && isEditMode && currentAncestryId && ancestry_save_url && get_ancestry_file) {
|
|
19546
19647
|
try {
|
|
19547
|
-
const viewDbResponse = await get_ancestry_file(
|
|
19648
|
+
const viewDbResponse = await get_ancestry_file(
|
|
19649
|
+
sceneConfigId,
|
|
19650
|
+
ownerId
|
|
19651
|
+
);
|
|
19548
19652
|
if (viewDbResponse.success && Array.isArray(viewDbResponse.data)) {
|
|
19549
|
-
const hasInViewDb = viewDbResponse.data.some(
|
|
19653
|
+
const hasInViewDb = viewDbResponse.data.some(
|
|
19654
|
+
(anc) => String(anc.ancestry_id) === String(currentAncestryId)
|
|
19655
|
+
);
|
|
19550
19656
|
if (hasInViewDb) {
|
|
19551
|
-
const updatedViewDb = viewDbResponse.data.filter(
|
|
19657
|
+
const updatedViewDb = viewDbResponse.data.filter(
|
|
19658
|
+
(anc) => String(anc.ancestry_id) !== String(currentAncestryId)
|
|
19659
|
+
);
|
|
19552
19660
|
await save_view_data(ancestry_save_url, updatedViewDb);
|
|
19553
19661
|
}
|
|
19554
19662
|
}
|
|
19555
19663
|
} catch (fallbackErr) {
|
|
19556
|
-
console.error(
|
|
19664
|
+
console.error(
|
|
19665
|
+
"Falha ao limpar c\xF3pia residual na edi\xE7\xE3o:",
|
|
19666
|
+
fallbackErr
|
|
19667
|
+
);
|
|
19557
19668
|
}
|
|
19558
19669
|
}
|
|
19559
19670
|
if (result.success) {
|
|
@@ -19664,7 +19775,10 @@ function XViewScene({
|
|
|
19664
19775
|
try {
|
|
19665
19776
|
let updatedAncestriesForFile;
|
|
19666
19777
|
if (get_ancestry_file && isExternalSave) {
|
|
19667
|
-
const remoteResponse = await get_ancestry_file(
|
|
19778
|
+
const remoteResponse = await get_ancestry_file(
|
|
19779
|
+
sourceFileId,
|
|
19780
|
+
sourceOwnerId
|
|
19781
|
+
);
|
|
19668
19782
|
if (remoteResponse.success && Array.isArray(remoteResponse.data)) {
|
|
19669
19783
|
updatedAncestriesForFile = remoteResponse.data.filter(
|
|
19670
19784
|
(anc) => String(anc.ancestry_id) !== String(ancestryIdToDelete)
|
|
@@ -19679,11 +19793,16 @@ function XViewScene({
|
|
|
19679
19793
|
(anc) => anc._source_file_id === sourceFileId && String(anc.ancestry_id) !== String(ancestryIdToDelete)
|
|
19680
19794
|
);
|
|
19681
19795
|
}
|
|
19682
|
-
const result = await save_view_data(
|
|
19796
|
+
const result = await save_view_data(
|
|
19797
|
+
finalSaveUrl,
|
|
19798
|
+
updatedAncestriesForFile
|
|
19799
|
+
);
|
|
19683
19800
|
if (result.success) {
|
|
19684
19801
|
success = true;
|
|
19685
19802
|
} else {
|
|
19686
|
-
throw new Error(
|
|
19803
|
+
throw new Error(
|
|
19804
|
+
result.error || "Ocorreu um erro desconhecido ao excluir."
|
|
19805
|
+
);
|
|
19687
19806
|
}
|
|
19688
19807
|
} catch (error) {
|
|
19689
19808
|
deletionError = error;
|
|
@@ -19692,15 +19811,25 @@ function XViewScene({
|
|
|
19692
19811
|
try {
|
|
19693
19812
|
const viewDbResponse = await get_ancestry_file(sceneConfigId, ownerId);
|
|
19694
19813
|
if (viewDbResponse.success && Array.isArray(viewDbResponse.data)) {
|
|
19695
|
-
const hasInViewDb = viewDbResponse.data.some(
|
|
19814
|
+
const hasInViewDb = viewDbResponse.data.some(
|
|
19815
|
+
(anc) => String(anc.ancestry_id) === String(ancestryIdToDelete)
|
|
19816
|
+
);
|
|
19696
19817
|
if (hasInViewDb) {
|
|
19697
|
-
const updatedViewDb = viewDbResponse.data.filter(
|
|
19698
|
-
|
|
19818
|
+
const updatedViewDb = viewDbResponse.data.filter(
|
|
19819
|
+
(anc) => String(anc.ancestry_id) !== String(ancestryIdToDelete)
|
|
19820
|
+
);
|
|
19821
|
+
const fallbackResult = await save_view_data(
|
|
19822
|
+
ancestry_save_url,
|
|
19823
|
+
updatedViewDb
|
|
19824
|
+
);
|
|
19699
19825
|
if (fallbackResult.success) success = true;
|
|
19700
19826
|
}
|
|
19701
19827
|
}
|
|
19702
19828
|
} catch (fallbackErr) {
|
|
19703
|
-
console.error(
|
|
19829
|
+
console.error(
|
|
19830
|
+
"Falha ao limpar c\xF3pia residual da View DB:",
|
|
19831
|
+
fallbackErr
|
|
19832
|
+
);
|
|
19704
19833
|
}
|
|
19705
19834
|
}
|
|
19706
19835
|
if (!success && deletionError) {
|
|
@@ -19878,23 +20007,28 @@ function XViewScene({
|
|
|
19878
20007
|
...sceneDataRef.current,
|
|
19879
20008
|
nodes: sceneDataRef.current.nodes || [],
|
|
19880
20009
|
links: sceneDataRef.current.links || [],
|
|
19881
|
-
|
|
19882
|
-
|
|
19883
|
-
|
|
20010
|
+
quest_counter: sceneDataRef.current.quest_counter || 1
|
|
20011
|
+
};
|
|
20012
|
+
delete sceneFileData.quest_nodes;
|
|
20013
|
+
delete sceneFileData.quest_links;
|
|
20014
|
+
delete sceneFileData.milestones;
|
|
20015
|
+
const questFileData = {
|
|
20016
|
+
nodes: ((_b2 = parentDataRef.current[sceneConfigId]) == null ? void 0 : _b2.nodes) || sceneDataRef.current.quest_nodes || [],
|
|
20017
|
+
links: ((_c2 = parentDataRef.current[sceneConfigId]) == null ? void 0 : _c2.links) || sceneDataRef.current.quest_links || [],
|
|
19884
20018
|
milestones: newMilestones
|
|
19885
20019
|
};
|
|
19886
20020
|
try {
|
|
19887
20021
|
await save_view_data(sceneSaveUrl, sceneFileData);
|
|
20022
|
+
const questSaveUrl = sceneSaveUrl.replace(
|
|
20023
|
+
"x_view_scenes",
|
|
20024
|
+
"x_view_quests"
|
|
20025
|
+
);
|
|
20026
|
+
await save_view_data(questSaveUrl, questFileData);
|
|
19888
20027
|
} catch (error) {
|
|
19889
20028
|
console.error("Erro ao salvar milestones:", error);
|
|
19890
20029
|
}
|
|
19891
20030
|
},
|
|
19892
|
-
[
|
|
19893
|
-
sceneConfigId,
|
|
19894
|
-
sceneSaveUrl,
|
|
19895
|
-
save_view_data,
|
|
19896
|
-
viewParams == null ? void 0 : viewParams.type
|
|
19897
|
-
]
|
|
20031
|
+
[sceneConfigId, sceneSaveUrl, save_view_data, viewParams == null ? void 0 : viewParams.type]
|
|
19898
20032
|
);
|
|
19899
20033
|
const handleSaveCurrentView = (0, import_react33.useCallback)(async () => {
|
|
19900
20034
|
var _a2, _b2, _c2;
|
|
@@ -19928,13 +20062,25 @@ function XViewScene({
|
|
|
19928
20062
|
...sceneDataRef.current,
|
|
19929
20063
|
nodes: currentNodes,
|
|
19930
20064
|
links: currentLinks,
|
|
19931
|
-
|
|
19932
|
-
|
|
19933
|
-
|
|
20065
|
+
quest_counter: sceneDataRef.current.quest_counter || 1
|
|
20066
|
+
};
|
|
20067
|
+
delete sceneFileData.quest_nodes;
|
|
20068
|
+
delete sceneFileData.quest_links;
|
|
20069
|
+
delete sceneFileData.milestones;
|
|
20070
|
+
const questFileData = {
|
|
20071
|
+
nodes: isView ? ((_b2 = parentDataRef.current[sceneConfigId]) == null ? void 0 : _b2.nodes) || [] : sceneDataRef.current.quest_nodes || [],
|
|
20072
|
+
links: isView ? ((_c2 = parentDataRef.current[sceneConfigId]) == null ? void 0 : _c2.links) || [] : sceneDataRef.current.quest_links || [],
|
|
19934
20073
|
milestones: sceneDataRef.current.milestones || []
|
|
19935
20074
|
};
|
|
19936
20075
|
try {
|
|
19937
20076
|
await save_view_data(sceneSaveUrl, sceneFileData);
|
|
20077
|
+
if (isView) {
|
|
20078
|
+
const questSaveUrl = sceneSaveUrl.replace(
|
|
20079
|
+
"x_view_scenes",
|
|
20080
|
+
"x_view_quests"
|
|
20081
|
+
);
|
|
20082
|
+
await save_view_data(questSaveUrl, questFileData);
|
|
20083
|
+
}
|
|
19938
20084
|
} catch (error) {
|
|
19939
20085
|
console.error("Erro na chamada de save_view_data:", error);
|
|
19940
20086
|
}
|
|
@@ -20051,7 +20197,12 @@ function XViewScene({
|
|
|
20051
20197
|
if (isUiClear) {
|
|
20052
20198
|
const isView = ((_c2 = viewParams == null ? void 0 : viewParams.type) == null ? void 0 : _c2.toLowerCase()) === "view";
|
|
20053
20199
|
if (!isView) return;
|
|
20054
|
-
const {
|
|
20200
|
+
const {
|
|
20201
|
+
graphGroup,
|
|
20202
|
+
glowTexture,
|
|
20203
|
+
controls: sceneControls,
|
|
20204
|
+
nodeObjects
|
|
20205
|
+
} = stateRef.current;
|
|
20055
20206
|
if (graphGroup) {
|
|
20056
20207
|
let ghostPosition = sceneControls.target.clone();
|
|
20057
20208
|
const existingNodes = Object.values(nodeObjects);
|
|
@@ -20107,7 +20258,12 @@ function XViewScene({
|
|
|
20107
20258
|
setQuestMode({ isActive: true });
|
|
20108
20259
|
}
|
|
20109
20260
|
}
|
|
20110
|
-
const isArrowKey = [
|
|
20261
|
+
const isArrowKey = [
|
|
20262
|
+
"ArrowUp",
|
|
20263
|
+
"ArrowDown",
|
|
20264
|
+
"ArrowLeft",
|
|
20265
|
+
"ArrowRight"
|
|
20266
|
+
].includes(event.key);
|
|
20111
20267
|
if (isArrowKey) {
|
|
20112
20268
|
const isUiClear = !stateRef.current.creation.isActive && !stateRef.current.connection.isActive && !stateRef.current.relink.isActive && !stateRef.current.ancestry.isActive && !((_d2 = context.versionMode) == null ? void 0 : _d2.isActive) && !contextMenu.visible && !multiContextMenu.visible && !relationshipMenu.visible && !readingMode.isActive && !isImportModalOpen && !isBoardsOpen && !isSidebarOpen && !isMilestoneManagerOpen && !detailsNode && !detailsLink && !ancestryLinkDetails && !imageViewer.visible && !editingAncestryRel.visible && !questMode.isActive;
|
|
20113
20269
|
if (isUiClear) {
|
|
@@ -20153,7 +20309,12 @@ function XViewScene({
|
|
|
20153
20309
|
if (isLoading || status === "loading" || permissionStatus === "loading") {
|
|
20154
20310
|
return /* @__PURE__ */ import_react33.default.createElement(LoadingScreen, null);
|
|
20155
20311
|
}
|
|
20156
|
-
const overlayHiddenStyle = questTreeMode.isActive ? {
|
|
20312
|
+
const overlayHiddenStyle = questTreeMode.isActive ? {
|
|
20313
|
+
opacity: 0,
|
|
20314
|
+
pointerEvents: "none",
|
|
20315
|
+
transform: "translateX(30px)",
|
|
20316
|
+
transition: "all 300ms ease-in-out"
|
|
20317
|
+
} : {};
|
|
20157
20318
|
if (permissionStatus === "denied") {
|
|
20158
20319
|
return /* @__PURE__ */ import_react33.default.createElement("div", { className: "flex flex-col items-center justify-center min-h-screen w-full bg-slate-950 text-white" }, /* @__PURE__ */ import_react33.default.createElement("div", { className: "bg-slate-900/50 p-8 rounded-2xl border border-slate-800 shadow-2xl text-center max-w-md" }, /* @__PURE__ */ import_react33.default.createElement("div", { className: "mb-4 text-red-500" }, /* @__PURE__ */ import_react33.default.createElement(
|
|
20159
20320
|
"svg",
|
|
@@ -20618,18 +20779,12 @@ function XViewScene({
|
|
|
20618
20779
|
data: multiContextMenu,
|
|
20619
20780
|
userRole: userPermissionRole,
|
|
20620
20781
|
onClose: () => setMultiContextMenu((prev) => ({ ...prev, visible: false })),
|
|
20621
|
-
onDismissNodes: (ids) => userActionHandlers.handleDismissMultipleNodes(
|
|
20622
|
-
actionHandlerContext,
|
|
20623
|
-
ids
|
|
20624
|
-
),
|
|
20782
|
+
onDismissNodes: (ids) => userActionHandlers.handleDismissMultipleNodes(actionHandlerContext, ids),
|
|
20625
20783
|
onDismissOtherNodes: (ids) => userActionHandlers.handleDismissOtherMultipleNodes(
|
|
20626
20784
|
actionHandlerContext,
|
|
20627
20785
|
ids
|
|
20628
20786
|
),
|
|
20629
|
-
onDeleteNodes: (ids) => userActionHandlers.handleDeleteMultipleNodes(
|
|
20630
|
-
actionHandlerContext,
|
|
20631
|
-
ids
|
|
20632
|
-
)
|
|
20787
|
+
onDeleteNodes: (ids) => userActionHandlers.handleDeleteMultipleNodes(actionHandlerContext, ids)
|
|
20633
20788
|
}
|
|
20634
20789
|
),
|
|
20635
20790
|
/* @__PURE__ */ import_react33.default.createElement(
|
|
@@ -20782,7 +20937,7 @@ async function save_view_data_logic(db_services, filename, data) {
|
|
|
20782
20937
|
}
|
|
20783
20938
|
}
|
|
20784
20939
|
async function get_scene_view_data_logic(db_services, scene_config, owner_id, type, session, focusNodeId = null, focusAncestryId = null) {
|
|
20785
|
-
var _a, _b;
|
|
20940
|
+
var _a, _b, _c;
|
|
20786
20941
|
try {
|
|
20787
20942
|
if (!session || !session.user) {
|
|
20788
20943
|
return { success: false, error: "Usu\xE1rio n\xE3o autenticado." };
|
|
@@ -20805,28 +20960,44 @@ async function get_scene_view_data_logic(db_services, scene_config, owner_id, ty
|
|
|
20805
20960
|
parentDbObjects.push({ db_id: scene_config, owner_id });
|
|
20806
20961
|
}
|
|
20807
20962
|
}
|
|
20963
|
+
const isView = type && type.toLowerCase() === "view";
|
|
20808
20964
|
const parentResponsesPromises = parentDbObjects.map(
|
|
20809
20965
|
(db_info) => db_services.get_file(`x_view_dbs/${db_info.owner_id}/${db_info.db_id}`)
|
|
20810
20966
|
);
|
|
20967
|
+
if (isView) {
|
|
20968
|
+
parentResponsesPromises.push(
|
|
20969
|
+
db_services.get_file(`x_view_quests/${owner_id}/${scene_config}`)
|
|
20970
|
+
);
|
|
20971
|
+
}
|
|
20811
20972
|
const parentResponsesResults = await Promise.allSettled(parentResponsesPromises);
|
|
20812
20973
|
const parentData = {};
|
|
20974
|
+
let questDataObj = null;
|
|
20813
20975
|
for (let i = 0; i < parentResponsesResults.length; i++) {
|
|
20814
20976
|
const result = parentResponsesResults[i];
|
|
20977
|
+
if (isView && i === parentResponsesResults.length - 1) {
|
|
20978
|
+
if (result.status === "fulfilled" && ((_a = result.value) == null ? void 0 : _a.success)) {
|
|
20979
|
+
questDataObj = result.value.data;
|
|
20980
|
+
}
|
|
20981
|
+
continue;
|
|
20982
|
+
}
|
|
20815
20983
|
const db_info = parentDbObjects[i];
|
|
20816
|
-
if (result.status === "fulfilled" && ((
|
|
20984
|
+
if (result.status === "fulfilled" && ((_b = result.value) == null ? void 0 : _b.success)) {
|
|
20817
20985
|
parentData[db_info.db_id] = result.value.data;
|
|
20818
20986
|
} else {
|
|
20819
20987
|
console.warn(
|
|
20820
20988
|
`Arquivo pai n\xE3o carregado: ${db_info.db_id}. Pode ter sido deletado.`,
|
|
20821
|
-
result.status === "rejected" ? result.reason : (
|
|
20989
|
+
result.status === "rejected" ? result.reason : (_c = result.value) == null ? void 0 : _c.error
|
|
20822
20990
|
);
|
|
20823
20991
|
}
|
|
20824
20992
|
}
|
|
20825
|
-
|
|
20993
|
+
const currentQuestNodes = (questDataObj == null ? void 0 : questDataObj.nodes) || sceneData.quest_nodes || [];
|
|
20994
|
+
const currentQuestLinks = (questDataObj == null ? void 0 : questDataObj.links) || sceneData.quest_links || [];
|
|
20995
|
+
const currentMilestones = (questDataObj == null ? void 0 : questDataObj.milestones) || sceneData.milestones || [];
|
|
20996
|
+
if (isView) {
|
|
20826
20997
|
parentData[scene_config] = {
|
|
20827
20998
|
dataset_name: "Quests Internas (View)",
|
|
20828
|
-
nodes:
|
|
20829
|
-
links:
|
|
20999
|
+
nodes: currentQuestNodes,
|
|
21000
|
+
links: currentQuestLinks
|
|
20830
21001
|
};
|
|
20831
21002
|
}
|
|
20832
21003
|
const allNodes = Object.values(parentData).flatMap((db) => db.nodes || []);
|
|
@@ -20858,7 +21029,12 @@ async function get_scene_view_data_logic(db_services, scene_config, owner_id, ty
|
|
|
20858
21029
|
const validatedSceneData = {
|
|
20859
21030
|
...sceneData,
|
|
20860
21031
|
nodes: validatedNodes,
|
|
20861
|
-
links: validatedLinks
|
|
21032
|
+
links: validatedLinks,
|
|
21033
|
+
// Re-injetando no validated para que o restante do sistema (e.g. XViewScene local state)
|
|
21034
|
+
// continue acessando as quests sem perceber a separação física
|
|
21035
|
+
quest_nodes: currentQuestNodes,
|
|
21036
|
+
quest_links: currentQuestLinks,
|
|
21037
|
+
milestones: currentMilestones
|
|
20862
21038
|
};
|
|
20863
21039
|
const ancestryFilePaths = [];
|
|
20864
21040
|
ancestryFilePaths.push({
|