Skip to content

Commit c3e4144

Browse files
fix(UI): Added OnDragEndCallback to notify the parent component that the drag has ended and in this case to invoke StateHasChanged CactuseSecurity#3299
1 parent a2d717e commit c3e4144

2 files changed

Lines changed: 156 additions & 136 deletions

File tree

roles/ui/files/FWO.UI/Pages/NetworkModelling/EditConnLeftSide.razor

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
<div class="form-group row">
2121
<div class="@ColWidthClass()">
2222
<DraggableList AllElements="AvailableNwElements" @bind-SelectedElements="selectedNwElems"
23-
HandleDragStart="HandleNwDragStart" Display="@DisplayNwObject" MaxHeight="25"/>
23+
HandleDragStart="HandleNwDragStart" Display="@DisplayNwObject" MaxHeight="25" OnDragEndCallback="StateHasChanged" />
2424
</div>
2525
@if(!OverviewMode)
2626
{
@@ -91,7 +91,7 @@
9191
<div class="form-group row">
9292
<div class="@ColWidthClass()">
9393
<DraggableList AllElements="ConnHandler.AvailableSvcElems" @bind-SelectedElements="selectedSvcElems"
94-
HandleDragStart="HandleSvcDragStart" Display="@DisplaySvcObject" MaxHeight="25"/>
94+
HandleDragStart="HandleSvcDragStart" Display="@DisplaySvcObject" MaxHeight="25" OnDragEndCallback="StateHasChanged" />
9595
</div>
9696
@if(!OverviewMode)
9797
{
@@ -470,7 +470,7 @@
470470
}
471471

472472
private bool HandleNwDragStart(DragEventArgs e, KeyValuePair<int, long> selectedNwElem)
473-
{
473+
{
474474
if(!selectedNwElems.Contains(selectedNwElem))
475475
{
476476
selectedNwElems.Add(selectedNwElem);

roles/ui/files/FWO.UI/Shared/DraggableList.razor

Lines changed: 153 additions & 133 deletions
Original file line numberDiff line numberDiff line change
@@ -3,156 +3,176 @@
33
@inject KeyboardInputService keyboardInputService
44

55
<div class="bg-secondary col-sm-12 border @CssClass" style="max-height: calc( @(MaxHeight) * 1vh);"
6-
tabindex="0">
7-
@for (int i = 0; i < AllElements.Count; i++)
8-
{
9-
int j = i;
10-
<div class="draggable draggable-item @(SelectedElements.Contains(AllElements[j]) ? "draggable-selected" : "")" draggable="true"
11-
@ondragstart="@((e) => { HandleDragStart(e, AllElements[j]); lastSelected = null; })"
12-
@onclick="() => ToggleSelect(j)" >
13-
<nobr>@((MarkupString)Display(AllElements[j]))</nobr>
14-
</div>
15-
}
6+
tabindex="0">
7+
@for (int i = 0; i < AllElements.Count; i++)
8+
{
9+
int j = i;
10+
<div class="draggable draggable-item @(SelectedElements.Contains(AllElements[j]) ? "draggable-selected" : "")" draggable="true"
11+
@ondragstart="@((e) => { HandleDragStart(e, AllElements[j]); lastSelected = null; })"
12+
@onclick="() => ToggleSelect(j)"
13+
@ondragend="OnDragEnd">
14+
<nobr>@((MarkupString)Display(AllElements[j]))</nobr>
15+
</div>
16+
}
1617
</div>
1718

1819
@code
1920
{
20-
[Parameter]
21-
public List<ElementType> AllElements { get; set; } = new List<ElementType>();
21+
[Parameter]
22+
public List<ElementType> AllElements { get; set; } = new List<ElementType>();
2223

23-
[Parameter]
24-
public List<ElementType> SelectedElements { get; set; } = new List<ElementType>();
24+
[Parameter]
25+
public List<ElementType> SelectedElements { get; set; } = new List<ElementType>();
2526

2627
[Parameter]
2728
public EventCallback<List<ElementType>> SelectedElementsChanged { get; set; }
2829

2930
[Parameter]
3031
public Func<DragEventArgs, ElementType, bool> HandleDragStart { get; set; } = DoNothingSync;
3132

32-
[Parameter]
33-
public Func<ElementType, string> Display { get; set; } = DoNothingSync;
33+
[Parameter]
34+
public Func<ElementType, string> Display { get; set; } = DoNothingSync;
3435

35-
[Parameter]
36-
public int MaxHeight { get; set; } = 50;
36+
[Parameter]
37+
public int MaxHeight { get; set; } = 50;
3738

38-
[Parameter]
39+
[Parameter]
3940
public bool Multiselect { get; set; } = true;
4041

4142
[Parameter]
4243
public string CssClass { get; set; } = "overflow-x-clip overflow-y-auto";
4344

44-
private int? lastSelected;
45-
private List<int> lastSelectedRange = new();
46-
47-
private void ToggleSelect(int index)
48-
{
49-
bool shiftPressed = keyboardInputService.ShiftPressed;
50-
bool ctrlPressed = keyboardInputService.ControlPressed;
51-
52-
// if no multiselect treat as if no multiselect key is pressed
53-
if (!Multiselect || (!shiftPressed && !ctrlPressed))
54-
{
55-
// if only one is selected deselect on click
56-
if (SelectedElements.Contains(AllElements[index]) && SelectedElements.Count() == 1)
57-
{
58-
Deselect(index);
59-
}
60-
else
61-
{
62-
Select(index);
63-
}
64-
}
65-
66-
if (shiftPressed)
67-
{
68-
if (!SelectedElements.Any())
69-
{
70-
Select(index);
71-
}
72-
else
73-
{
74-
if (SelectedElements.Contains(AllElements[index]) && SelectedElements.Count() == 1)
75-
{
76-
Deselect(index);
77-
}
78-
else
79-
{
80-
SelectRange(index);
81-
}
82-
}
83-
}
84-
85-
if (ctrlPressed)
86-
{
87-
// if only one is selected deselect on click
88-
if (SelectedElements.Contains(AllElements[index]))
89-
{
90-
Deselect(index);
91-
}
92-
else
93-
{
94-
Select(index, true);
95-
}
96-
}
97-
98-
SelectedElementsChanged.InvokeAsync(SelectedElements);
99-
}
100-
101-
private void Select(int index, bool multiSelect = false)
102-
{
103-
if (!multiSelect)
104-
{
105-
SelectedElements.Clear();
106-
}
107-
108-
SelectedElements.Add(AllElements[index]);
109-
lastSelected = index;
110-
lastSelectedRange.Clear();
111-
}
112-
113-
private void SelectRange(int index)
114-
{
115-
foreach (ElementType element in AllElements.Where((item, index) => lastSelectedRange.Contains(index)).ToList())
116-
{
117-
if(SelectedElements.Contains(element))
118-
{
119-
SelectedElements.Remove(element);
120-
}
121-
}
122-
123-
lastSelectedRange.Clear();
124-
125-
if(index > lastSelected)
126-
{
127-
for(int idx = (int)lastSelected; idx <= index; ++idx)
128-
{
129-
SelectedElements.Add(AllElements[idx]);
130-
lastSelectedRange.Add(idx);
131-
}
132-
}
133-
134-
if(index < lastSelected)
135-
{
136-
for(int idx = (int)lastSelected; idx >= index; --idx)
137-
{
138-
SelectedElements.Add(AllElements[idx]);
139-
lastSelectedRange.Add(idx);
140-
}
141-
}
142-
}
143-
144-
private void Deselect(int index)
145-
{
146-
SelectedElements.Remove(AllElements[index]);
147-
lastSelected = null;
148-
}
149-
150-
private void DeselectRange()
151-
{
152-
SelectedElements.Clear();
153-
lastSelected = null;
154-
}
155-
156-
private static bool DoNothingSync(DragEventArgs e, ElementType elem) { return false; }
157-
private static string DoNothingSync(ElementType e) { return ""; }
45+
[Parameter]
46+
public EventCallback OnDragEndCallback { get; set; }
47+
48+
private int? lastSelected;
49+
private List<int> lastSelectedRange = new();
50+
51+
private void ToggleSelect(int index)
52+
{
53+
bool shiftPressed = keyboardInputService.ShiftPressed;
54+
bool ctrlPressed = keyboardInputService.ControlPressed;
55+
56+
// if no multiselect treat as if no multiselect key is pressed
57+
if (!Multiselect || (!shiftPressed && !ctrlPressed))
58+
{
59+
// if only one is selected deselect on click
60+
if (SelectedElements.Contains(AllElements[index]) && SelectedElements.Count() == 1)
61+
{
62+
Deselect(index);
63+
}
64+
else
65+
{
66+
Select(index);
67+
}
68+
}
69+
70+
if (shiftPressed)
71+
{
72+
if (!SelectedElements.Any())
73+
{
74+
Select(index);
75+
}
76+
else
77+
{
78+
if (SelectedElements.Contains(AllElements[index]) && SelectedElements.Count() == 1)
79+
{
80+
Deselect(index);
81+
}
82+
else
83+
{
84+
SelectRange(index);
85+
}
86+
}
87+
}
88+
89+
if (ctrlPressed)
90+
{
91+
// if only one is selected deselect on click
92+
if (SelectedElements.Contains(AllElements[index]))
93+
{
94+
Deselect(index);
95+
}
96+
else
97+
{
98+
Select(index, true);
99+
}
100+
}
101+
102+
SelectedElementsChanged.InvokeAsync(SelectedElements);
103+
}
104+
105+
private void Select(int index, bool multiSelect = false)
106+
{
107+
if (!multiSelect)
108+
{
109+
SelectedElements.Clear();
110+
}
111+
112+
SelectedElements.Add(AllElements[index]);
113+
lastSelected = index;
114+
lastSelectedRange.Clear();
115+
}
116+
117+
private void SelectRange(int index)
118+
{
119+
foreach (ElementType element in AllElements.Where((item, index) => lastSelectedRange.Contains(index)).ToList())
120+
{
121+
if (SelectedElements.Contains(element))
122+
{
123+
SelectedElements.Remove(element);
124+
}
125+
}
126+
127+
lastSelectedRange.Clear();
128+
129+
if (index > lastSelected)
130+
{
131+
for (int idx = (int)lastSelected; idx <= index; ++idx)
132+
{
133+
SelectedElements.Add(AllElements[idx]);
134+
lastSelectedRange.Add(idx);
135+
}
136+
}
137+
138+
if (index < lastSelected)
139+
{
140+
for (int idx = (int)lastSelected; idx >= index; --idx)
141+
{
142+
SelectedElements.Add(AllElements[idx]);
143+
lastSelectedRange.Add(idx);
144+
}
145+
}
146+
}
147+
148+
private void Deselect(int index)
149+
{
150+
SelectedElements.Remove(AllElements[index]);
151+
lastSelected = null;
152+
}
153+
154+
private void DeselectRange()
155+
{
156+
SelectedElements.Clear();
157+
lastSelected = null;
158+
}
159+
160+
/// <summary>
161+
/// Invokes OnDragEnd EventCallback (only if it has a delegate)
162+
/// </summary>
163+
/// <returns></returns>
164+
private async Task OnDragEnd()
165+
{
166+
if (OnDragEndCallback.HasDelegate)
167+
{
168+
try
169+
{
170+
await OnDragEndCallback.InvokeAsync();
171+
}
172+
catch (Exception){ }
173+
}
174+
}
175+
176+
private static bool DoNothingSync(DragEventArgs e, ElementType elem) { return false; }
177+
private static string DoNothingSync(ElementType e) { return ""; }
158178
}

0 commit comments

Comments
 (0)