Skip to content

Commit 0874e58

Browse files
Copilotdwarwick
andcommitted
Implement proper Syncfusion Container nodes with Children collection
Co-authored-by: dwarwick <15970276+dwarwick@users.noreply.github.com>
1 parent a0957e3 commit 0874e58

File tree

1 file changed

+111
-68
lines changed

1 file changed

+111
-68
lines changed

JwtIdentity.Client/Pages/Survey/BranchingSurveyEdit.razor.cs

Lines changed: 111 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -459,9 +459,7 @@ private void BuildSyncfusionDiagram()
459459
if (Survey == null || QuestionGroups == null || !QuestionGroups.Any())
460460
return;
461461

462-
double xPosition = 50; // Starting X position for layout
463-
464-
// Create container-style groupings for each group with option nodes inside
462+
// Create Container nodes for each group with option nodes as children
465463
foreach (var group in QuestionGroups.OrderBy(g => g.GroupNumber))
466464
{
467465
var questionCount = Survey.Questions.Count(q => q.GroupId == group.GroupNumber);
@@ -476,47 +474,50 @@ private void BuildSyncfusionDiagram()
476474
.OrderBy(q => q.QuestionNumber)
477475
.ToList();
478476

479-
// Calculate container dimensions based on children
480-
var childCount = 0;
481-
foreach (var question in groupQuestions)
482-
{
483-
childCount += GetOptionCount(question);
484-
}
485-
486-
var containerHeight = Math.Max(200, 120 + (childCount * 75));
477+
// Calculate container dimensions
478+
var childCount = GetOptionCount(groupQuestions);
479+
var containerHeight = Math.Max(200, 100 + (childCount * 75));
487480
var containerWidth = 360.0;
488481

489-
// Create background container node for the group
490-
var containerNode = new Node()
482+
// Create Container node
483+
var container = new Container()
491484
{
492485
ID = $"Container{group.GroupNumber}",
493486
Width = containerWidth,
494487
Height = containerHeight,
495-
OffsetX = xPosition + (containerWidth / 2),
496-
OffsetY = 50 + (containerHeight / 2),
497-
Annotations = new DiagramObjectCollection<ShapeAnnotation>()
488+
Header = new ContainerHeader()
498489
{
499-
new ShapeAnnotation()
490+
ID = $"Header{group.GroupNumber}",
491+
Height = 50,
492+
Annotation = new ShapeAnnotation()
500493
{
501494
Content = $"{groupName}\n({questionCount} question{(questionCount != 1 ? "s" : "")})",
502-
Style = new TextStyle() { Color = "white", Bold = true, FontSize = 14 },
503-
VerticalAlignment = VerticalAlignment.Top,
504-
Margin = new DiagramThickness() { Top = 10 }
495+
Style = new TextStyle()
496+
{
497+
Color = "white",
498+
Bold = true,
499+
FontSize = 14
500+
}
501+
},
502+
Style = new TextStyle()
503+
{
504+
Fill = GetGroupColor(group.GroupNumber),
505+
StrokeColor = "Black",
505506
}
506507
},
507508
Style = new ShapeStyle()
508509
{
509510
Fill = GetGroupColor(group.GroupNumber),
510511
StrokeWidth = 3,
511512
StrokeColor = "Black"
512-
},
513-
Constraints = NodeConstraints.Default & ~NodeConstraints.Select // Make it non-selectable like a background
513+
}
514514
};
515515

516-
Nodes.Add(containerNode);
516+
// Create children array for the container
517+
var childrenIds = new List<string>();
517518

518-
// Create child option nodes positioned inside the container
519-
var yOffset = 50 + 70.0; // Start below the header
519+
// Create child option nodes and add them to the container
520+
var yOffset = 20.0; // Offset from header
520521
foreach (var question in groupQuestions)
521522
{
522523
if (question.QuestionType == QuestionType.MultipleChoice)
@@ -527,20 +528,27 @@ private void BuildSyncfusionDiagram()
527528
foreach (var option in mcQuestion.Options.Where(o => o.BranchToGroupId.HasValue))
528529
{
529530
var targetGroupColor = GetGroupColor(option.BranchToGroupId.Value);
531+
var optionNodeId = $"Option_MC_Q{question.Id}_O{option.Id}";
530532

531533
var optionNode = new Node()
532534
{
533-
ID = $"Option_MC_Q{question.Id}_O{option.Id}",
535+
ID = optionNodeId,
534536
Width = 320,
535537
Height = 65,
536-
OffsetX = xPosition + (containerWidth / 2),
538+
OffsetX = containerWidth / 2,
537539
OffsetY = yOffset,
538540
Annotations = new DiagramObjectCollection<ShapeAnnotation>()
539541
{
540542
new ShapeAnnotation()
541543
{
542544
Content = $"Q{question.QuestionNumber}: {question.Text}\n{TruncateText(option.OptionText, 35)}",
543-
Style = new TextStyle() { Color = "black", Bold = false, FontSize = 11, TextWrapping = Syncfusion.Blazor.Diagram.TextWrap.Wrap }
545+
Style = new TextStyle()
546+
{
547+
Color = "black",
548+
Bold = false,
549+
FontSize = 11,
550+
TextWrapping = Syncfusion.Blazor.Diagram.TextWrap.Wrap
551+
}
544552
}
545553
},
546554
Style = new ShapeStyle()
@@ -550,14 +558,16 @@ private void BuildSyncfusionDiagram()
550558
StrokeColor = targetGroupColor
551559
}
552560
};
561+
553562
Nodes.Add(optionNode);
563+
childrenIds.Add(optionNodeId);
554564
yOffset += 75;
555565

556-
// Connect option node to target group container
566+
// Create connector from option to target group
557567
var connector = new Connector()
558568
{
559-
ID = $"Connector_Option_Q{question.Id}_O{option.Id}_To_Container{option.BranchToGroupId}",
560-
SourceID = optionNode.ID,
569+
ID = $"Connector_O{option.Id}_To_Container{option.BranchToGroupId}",
570+
SourceID = optionNodeId,
561571
TargetID = $"Container{option.BranchToGroupId}",
562572
Type = ConnectorSegmentType.Bezier,
563573
Style = new ShapeStyle() { StrokeColor = targetGroupColor, StrokeWidth = 3 },
@@ -579,20 +589,27 @@ private void BuildSyncfusionDiagram()
579589
foreach (var option in saQuestion.Options.Where(o => o.BranchToGroupId.HasValue))
580590
{
581591
var targetGroupColor = GetGroupColor(option.BranchToGroupId.Value);
592+
var optionNodeId = $"Option_SA_Q{question.Id}_O{option.Id}";
582593

583594
var optionNode = new Node()
584595
{
585-
ID = $"Option_SA_Q{question.Id}_O{option.Id}",
596+
ID = optionNodeId,
586597
Width = 320,
587598
Height = 65,
588-
OffsetX = xPosition + (containerWidth / 2),
599+
OffsetX = containerWidth / 2,
589600
OffsetY = yOffset,
590601
Annotations = new DiagramObjectCollection<ShapeAnnotation>()
591602
{
592603
new ShapeAnnotation()
593604
{
594605
Content = $"Q{question.QuestionNumber}: {question.Text}\n{TruncateText(option.OptionText, 35)}",
595-
Style = new TextStyle() { Color = "black", Bold = false, FontSize = 11, TextWrapping = Syncfusion.Blazor.Diagram.TextWrap.Wrap }
606+
Style = new TextStyle()
607+
{
608+
Color = "black",
609+
Bold = false,
610+
FontSize = 11,
611+
TextWrapping = Syncfusion.Blazor.Diagram.TextWrap.Wrap
612+
}
596613
}
597614
},
598615
Style = new ShapeStyle()
@@ -602,14 +619,16 @@ private void BuildSyncfusionDiagram()
602619
StrokeColor = targetGroupColor
603620
}
604621
};
622+
605623
Nodes.Add(optionNode);
624+
childrenIds.Add(optionNodeId);
606625
yOffset += 75;
607626

608-
// Connect option node to target group container
627+
// Create connector from option to target group
609628
var connector = new Connector()
610629
{
611-
ID = $"Connector_Option_Q{question.Id}_O{option.Id}_To_Container{option.BranchToGroupId}",
612-
SourceID = optionNode.ID,
630+
ID = $"Connector_O{option.Id}_To_Container{option.BranchToGroupId}",
631+
SourceID = optionNodeId,
613632
TargetID = $"Container{option.BranchToGroupId}",
614633
Type = ConnectorSegmentType.Bezier,
615634
Style = new ShapeStyle() { StrokeColor = targetGroupColor, StrokeWidth = 3 },
@@ -631,20 +650,27 @@ private void BuildSyncfusionDiagram()
631650
if (tfQuestion.BranchToGroupIdOnTrue.HasValue)
632651
{
633652
var targetGroupColor = GetGroupColor(tfQuestion.BranchToGroupIdOnTrue.Value);
653+
var optionNodeId = $"Option_TF_Q{question.Id}_True";
634654

635655
var optionNode = new Node()
636656
{
637-
ID = $"Option_TF_Q{question.Id}_True",
657+
ID = optionNodeId,
638658
Width = 320,
639659
Height = 65,
640-
OffsetX = xPosition + (containerWidth / 2),
660+
OffsetX = containerWidth / 2,
641661
OffsetY = yOffset,
642662
Annotations = new DiagramObjectCollection<ShapeAnnotation>()
643663
{
644664
new ShapeAnnotation()
645665
{
646666
Content = $"Q{question.QuestionNumber}: {question.Text}\nTrue",
647-
Style = new TextStyle() { Color = "black", Bold = false, FontSize = 11, TextWrapping = Syncfusion.Blazor.Diagram.TextWrap.Wrap }
667+
Style = new TextStyle()
668+
{
669+
Color = "black",
670+
Bold = false,
671+
FontSize = 11,
672+
TextWrapping = Syncfusion.Blazor.Diagram.TextWrap.Wrap
673+
}
648674
}
649675
},
650676
Style = new ShapeStyle()
@@ -654,14 +680,16 @@ private void BuildSyncfusionDiagram()
654680
StrokeColor = targetGroupColor
655681
}
656682
};
683+
657684
Nodes.Add(optionNode);
685+
childrenIds.Add(optionNodeId);
658686
yOffset += 75;
659687

660-
// Connect option node to target group container
688+
// Create connector from option to target group
661689
var connector = new Connector()
662690
{
663-
ID = $"Connector_Option_Q{question.Id}_True_To_Container{tfQuestion.BranchToGroupIdOnTrue}",
664-
SourceID = optionNode.ID,
691+
ID = $"Connector_TF{question.Id}_True_To_Container{tfQuestion.BranchToGroupIdOnTrue}",
692+
SourceID = optionNodeId,
665693
TargetID = $"Container{tfQuestion.BranchToGroupIdOnTrue}",
666694
Type = ConnectorSegmentType.Bezier,
667695
Style = new ShapeStyle() { StrokeColor = targetGroupColor, StrokeWidth = 3 },
@@ -677,20 +705,27 @@ private void BuildSyncfusionDiagram()
677705
if (tfQuestion.BranchToGroupIdOnFalse.HasValue)
678706
{
679707
var targetGroupColor = GetGroupColor(tfQuestion.BranchToGroupIdOnFalse.Value);
708+
var optionNodeId = $"Option_TF_Q{question.Id}_False";
680709

681710
var optionNode = new Node()
682711
{
683-
ID = $"Option_TF_Q{question.Id}_False",
712+
ID = optionNodeId,
684713
Width = 320,
685714
Height = 65,
686-
OffsetX = xPosition + (containerWidth / 2),
715+
OffsetX = containerWidth / 2,
687716
OffsetY = yOffset,
688717
Annotations = new DiagramObjectCollection<ShapeAnnotation>()
689718
{
690719
new ShapeAnnotation()
691720
{
692721
Content = $"Q{question.QuestionNumber}: {question.Text}\nFalse",
693-
Style = new TextStyle() { Color = "black", Bold = false, FontSize = 11, TextWrapping = Syncfusion.Blazor.Diagram.TextWrap.Wrap }
722+
Style = new TextStyle()
723+
{
724+
Color = "black",
725+
Bold = false,
726+
FontSize = 11,
727+
TextWrapping = Syncfusion.Blazor.Diagram.TextWrap.Wrap
728+
}
694729
}
695730
},
696731
Style = new ShapeStyle()
@@ -700,14 +735,16 @@ private void BuildSyncfusionDiagram()
700735
StrokeColor = targetGroupColor
701736
}
702737
};
738+
703739
Nodes.Add(optionNode);
740+
childrenIds.Add(optionNodeId);
704741
yOffset += 75;
705742

706-
// Connect option node to target group container
743+
// Create connector from option to target group
707744
var connector = new Connector()
708745
{
709-
ID = $"Connector_Option_Q{question.Id}_False_To_Container{tfQuestion.BranchToGroupIdOnFalse}",
710-
SourceID = optionNode.ID,
746+
ID = $"Connector_TF{question.Id}_False_To_Container{tfQuestion.BranchToGroupIdOnFalse}",
747+
SourceID = optionNodeId,
711748
TargetID = $"Container{tfQuestion.BranchToGroupIdOnFalse}",
712749
Type = ConnectorSegmentType.Bezier,
713750
Style = new ShapeStyle() { StrokeColor = targetGroupColor, StrokeWidth = 3 },
@@ -723,31 +760,37 @@ private void BuildSyncfusionDiagram()
723760
}
724761
}
725762

726-
xPosition += containerWidth + 100; // Space between containers
763+
// Set the Children property
764+
container.Children = childrenIds.ToArray();
765+
766+
// Add container to nodes
767+
Nodes.Add(container);
727768
}
728769
}
729770

730-
private int GetOptionCount(QuestionViewModel question)
771+
private int GetOptionCount(List<QuestionViewModel> groupQuestions)
731772
{
732-
if (question.QuestionType == QuestionType.MultipleChoice)
733-
{
734-
var mcQuestion = question as MultipleChoiceQuestionViewModel;
735-
return mcQuestion?.Options?.Count(o => o.BranchToGroupId.HasValue) ?? 0;
736-
}
737-
else if (question.QuestionType == QuestionType.SelectAllThatApply)
738-
{
739-
var saQuestion = question as SelectAllThatApplyQuestionViewModel;
740-
return saQuestion?.Options?.Count(o => o.BranchToGroupId.HasValue) ?? 0;
741-
}
742-
else if (question.QuestionType == QuestionType.TrueFalse)
773+
var count = 0;
774+
foreach (var question in groupQuestions)
743775
{
744-
var tfQuestion = question as TrueFalseQuestionViewModel;
745-
var count = 0;
746-
if (tfQuestion?.BranchToGroupIdOnTrue.HasValue == true) count++;
747-
if (tfQuestion?.BranchToGroupIdOnFalse.HasValue == true) count++;
748-
return count;
776+
if (question.QuestionType == QuestionType.MultipleChoice)
777+
{
778+
var mcQuestion = question as MultipleChoiceQuestionViewModel;
779+
count += mcQuestion?.Options?.Count(o => o.BranchToGroupId.HasValue) ?? 0;
780+
}
781+
else if (question.QuestionType == QuestionType.SelectAllThatApply)
782+
{
783+
var saQuestion = question as SelectAllThatApplyQuestionViewModel;
784+
count += saQuestion?.Options?.Count(o => o.BranchToGroupId.HasValue) ?? 0;
785+
}
786+
else if (question.QuestionType == QuestionType.TrueFalse)
787+
{
788+
var tfQuestion = question as TrueFalseQuestionViewModel;
789+
if (tfQuestion?.BranchToGroupIdOnTrue.HasValue == true) count++;
790+
if (tfQuestion?.BranchToGroupIdOnFalse.HasValue == true) count++;
791+
}
749792
}
750-
return 0;
793+
return count;
751794
}
752795

753796
private string GetGroupColor(int groupNumber)

0 commit comments

Comments
 (0)