Skip to content

Commit 926c45a

Browse files
committed
Merge branch 'hotfix-19.1' into develop
2 parents b3e933f + 29d2982 commit 926c45a

7 files changed

Lines changed: 859 additions & 606 deletions

File tree

Rock.Blocks/Core/McpServerList.cs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,12 @@
2929
using Rock.Web.Cache;
3030
using Rock.Web.Cache.Entities;
3131

32+
#if WEBFORMS
33+
using System.Web.UI;
34+
35+
using Rock.Web;
36+
#endif
37+
3238
namespace Rock.Blocks.Core
3339
{
3440
/// <summary>
@@ -128,5 +134,61 @@ private List<McpServerListItemBag> GetMcpServers( bool appendApiKeyToUrl )
128134
}
129135

130136
#endregion
137+
138+
#if WEBFORMS
139+
#region Custom Settings
140+
141+
/// <summary>
142+
/// Widens Bootstrap tooltips inside the BlockProperties iframe so the verbose
143+
/// "Append API Key to URL" help text wraps to fewer lines and fits within the
144+
/// iframe's vertical space (the default 200px tooltip width forces the long
145+
/// description to wrap into a tall tooltip that gets clipped at the iframe edge).
146+
/// </summary>
147+
/*
148+
5/1/26 - JMH
149+
150+
This provider only loads when the McpServerList block is being edited, so the
151+
injected CSS is naturally scoped to this block's settings dialog and doesn't
152+
affect tooltips elsewhere in Rock.
153+
154+
Reason: Tooltips can't extend past an iframe's boundary; widening them keeps
155+
the rendered tooltip short enough to fit.
156+
*/
157+
[CustomSettingsBlockType( typeof( McpServerList ), Model.SiteType.Web )]
158+
public class McpServerListCustomSettingsProvider : RockCustomSettingsProvider
159+
{
160+
private const string TooltipWidthScript = @"
161+
<script>
162+
(function() {
163+
var style = document.createElement( 'style' );
164+
style.textContent = '.tooltip-inner { max-width: 500px; }';
165+
document.head.appendChild( style );
166+
})();
167+
</script>";
168+
169+
/// <inheritdoc />
170+
public override string CustomSettingsTitle => "Basic Settings";
171+
172+
/// <inheritdoc />
173+
public override Control GetCustomSettingsControl( IHasAttributes attributeEntity, Control parent )
174+
{
175+
return new LiteralControl( TooltipWidthScript );
176+
}
177+
178+
/// <inheritdoc />
179+
public override void ReadSettingsFromEntity( IHasAttributes attributeEntity, Control control )
180+
{
181+
// No persisted state — this provider only injects styling for tooltips.
182+
}
183+
184+
/// <inheritdoc />
185+
public override void WriteSettingsToEntity( IHasAttributes attributeEntity, Control control, RockContext rockContext )
186+
{
187+
// No persisted state — this provider only injects styling for tooltips.
188+
}
189+
}
190+
191+
#endregion
192+
#endif
131193
}
132194
}

Rock.Blocks/Engagement/ConnectionsHub.cs

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1003,6 +1003,67 @@ private void LaunchWorkflowsInBackground( List<ConnectionRequest> eligibleReques
10031003

10041004
#region Placement Group Methods
10051005

1006+
/// <summary>
1007+
/// Applies a default group member role and/or status to the Connection Request
1008+
/// when the assigned placement group's opportunity offers only a single option.
1009+
/// The Edit and Add UIs hide the role/status dropdown when there is only one
1010+
/// configured value, so the bag arrives without a selection. This fills the
1011+
/// gap so the request can still be fully placed.
1012+
/// </summary>
1013+
/// <param name="entity">The Connection Request whose role/status may need defaulting.</param>
1014+
private void ApplyDefaultGroupMemberRoleAndStatus( ConnectionRequest entity )
1015+
{
1016+
if ( !entity.AssignedGroupId.HasValue )
1017+
{
1018+
return;
1019+
}
1020+
1021+
if ( entity.AssignedGroupMemberRoleId.HasValue && entity.AssignedGroupMemberStatus.HasValue )
1022+
{
1023+
return;
1024+
}
1025+
1026+
var placementGroup = new GroupService( RockContext ).Get( entity.AssignedGroupId.Value );
1027+
if ( placementGroup == null )
1028+
{
1029+
return;
1030+
}
1031+
1032+
var configs = new ConnectionOpportunityGroupConfigService( RockContext ).Queryable()
1033+
.AsNoTracking()
1034+
.Where( c =>
1035+
c.ConnectionOpportunityId == entity.ConnectionOpportunityId &&
1036+
c.GroupTypeId == placementGroup.GroupTypeId )
1037+
.Select( c => new
1038+
{
1039+
c.GroupMemberRoleId,
1040+
c.GroupMemberStatus
1041+
} )
1042+
.ToList();
1043+
1044+
if ( !entity.AssignedGroupMemberRoleId.HasValue )
1045+
{
1046+
var distinctRoleIds = configs.Select( c => c.GroupMemberRoleId ).Distinct().ToList();
1047+
if ( distinctRoleIds.Count == 1 )
1048+
{
1049+
entity.AssignedGroupMemberRoleId = distinctRoleIds[0];
1050+
}
1051+
}
1052+
1053+
if ( !entity.AssignedGroupMemberStatus.HasValue && entity.AssignedGroupMemberRoleId.HasValue )
1054+
{
1055+
var distinctStatuses = configs
1056+
.Where( c => c.GroupMemberRoleId == entity.AssignedGroupMemberRoleId.Value )
1057+
.Select( c => c.GroupMemberStatus )
1058+
.Distinct()
1059+
.ToList();
1060+
if ( distinctStatuses.Count == 1 )
1061+
{
1062+
entity.AssignedGroupMemberStatus = distinctStatuses[0];
1063+
}
1064+
}
1065+
}
1066+
10061067
/// <summary>
10071068
/// Serializes the Placement Group Member Attribute values into a JSON string and returns it
10081069
/// </summary>
@@ -1706,6 +1767,10 @@ private bool UpdateEntityFromBox( ConnectionRequest entity, ValidPropertiesBox<C
17061767
box.IfValidProperty( nameof( box.Bag.GroupMemberStatus ),
17071768
() => entity.AssignedGroupMemberStatus = box.Bag.GroupMemberStatus );
17081769

1770+
// If the opportunity only offers a single role or status, the UI hides the dropdown,
1771+
// so the bag arrives empty. Default it before serializing attribute values.
1772+
ApplyDefaultGroupMemberRoleAndStatus( entity );
1773+
17091774
box.IfValidProperty( nameof( box.Bag.PlacementGroupMemberAttributeValues ),
17101775
() => entity.AssignedGroupMemberAttributeValues = GetGroupMemberAttributeValuesFromBag( box.Bag.PlacementGroupMemberAttributeValues, entity.AssignedGroupId, entity.AssignedGroupMemberRoleId, entity.AssignedGroupMemberStatus ) );
17111776
}

Rock.JavaScript.Obsidian.Blocks/src/Engagement/ConnectionsHub/addConnectionRequestModal.partial.obs

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -509,24 +509,6 @@
509509
pruneAndSeedPlacementGroupMemberAttributeValues();
510510
});
511511

512-
/**
513-
* If there is only one group member role then we will hide the dropdown and set the value to that role by default.
514-
*/
515-
watch(() => props.placementGroupDetails?.groupMemberRoles, () => {
516-
if (props.placementGroupDetails?.groupMemberRoles && props.placementGroupDetails.groupMemberRoles.length === 1) {
517-
groupMemberRoleGuid.value = props.placementGroupDetails.groupMemberRoles[0].value ?? "";
518-
}
519-
});
520-
521-
/**
522-
* If there is only one group member status for the selected role then we will hide the dropdown and set the value to that status by default.
523-
*/
524-
watch(groupMemberStatusItems, () => {
525-
if (groupMemberStatusItems.value.length === 1) {
526-
groupMemberStatus.value = groupMemberStatusItems.value[0].value ?? "";
527-
}
528-
});
529-
530512
watch(() => props.modelValue.bag, () => {
531513
updateRefValue(comments, props.modelValue.bag?.comments ?? "");
532514
updateRefValue(connectionOpportunityGuid, props.modelValue.bag?.connectionOpportunityGuid ?? "");

0 commit comments

Comments
 (0)