Skip to content

Commit b8834d6

Browse files
committed
- Added PersonalDeviceInteractions Obsidian block and removed legacy WebForms version
1 parent d57faa3 commit b8834d6

File tree

8 files changed

+736
-352
lines changed

8 files changed

+736
-352
lines changed
Lines changed: 312 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,312 @@
1+
// <copyright>
2+
// Copyright by the Spark Development Network
3+
//
4+
// Licensed under the Rock Community License (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.rockrms.com/license
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
// </copyright>
16+
//
17+
using System;
18+
using System.ComponentModel;
19+
using System.Data.Entity;
20+
using System.Linq;
21+
22+
using Rock;
23+
using Rock.Attribute;
24+
using Rock.Data;
25+
using Rock.Enums.Controls;
26+
using Rock.Model;
27+
using Rock.Obsidian.UI;
28+
using Rock.Utility;
29+
using Rock.ViewModels.Blocks;
30+
using Rock.ViewModels.Blocks.Crm.PersonalDeviceInteractions;
31+
using Rock.ViewModels.Controls;
32+
using Rock.Web.Cache;
33+
34+
namespace Rock.Blocks.Crm
35+
{
36+
[DisplayName( "Personal Device Interactions" )]
37+
[Category( "CRM" )]
38+
[Description( "Shows a list of all interactions for a personal device." )]
39+
40+
[IntegerField(
41+
"Presence Interval (Minutes)",
42+
Key = AttributeKey.CurrentlyPresentInterval,
43+
Description = "The number of minutes to use when determining if a device is still present. For example, if set to 5, a device is considered present if its last interaction occurred within the past 5 minutes.",
44+
IsRequired = true,
45+
DefaultIntegerValue = 5,
46+
Order = 0 )]
47+
48+
// was [Rock.SystemGuid.BlockTypeGuid( "B734D303-E116-497D-9A03-E641DCF193C3" )]
49+
[Rock.SystemGuid.BlockTypeGuid( "D6224911-2590-427F-9DCE-6D14E79806BA" )]
50+
public class PersonalDeviceInteractions : RockListBlockType<PersonalDeviceInteractions.PersonalDeviceInteractionRow>
51+
{
52+
#region Keys
53+
54+
private static class AttributeKey
55+
{
56+
public const string CurrentlyPresentInterval = "CurrentlyPresentInterval";
57+
}
58+
59+
private static class PageParameterKey
60+
{
61+
public const string PersonalDeviceId = "PersonalDeviceId";
62+
}
63+
64+
private static class PreferenceKey
65+
{
66+
public const string FilterDateRange = "filter-date-range";
67+
public const string FilterShowUnassignedDevices = "filter-show-unassigned-devices";
68+
public const string FilterPresentDevices = "filter-present-devices";
69+
}
70+
71+
#endregion Keys
72+
73+
#region Properties
74+
75+
private PersonPreferenceCollection BlockPersonPreferences => this.GetBlockPersonPreferences();
76+
77+
private SlidingDateRangeBag FilterDateRange => BlockPersonPreferences
78+
.GetValue( PreferenceKey.FilterDateRange )
79+
.ToSlidingDateRangeBagOrNull();
80+
81+
private bool FilterShowUnassignedDevices => BlockPersonPreferences
82+
.GetValue( PreferenceKey.FilterShowUnassignedDevices )
83+
.AsBoolean();
84+
85+
private bool FilterPresentDevices => BlockPersonPreferences
86+
.GetValue( PreferenceKey.FilterPresentDevices )
87+
.AsBoolean();
88+
89+
#endregion Properties
90+
91+
#region Methods
92+
93+
/// <inheritdoc/>
94+
public override object GetObsidianBlockInitialization()
95+
{
96+
var box = new ListBlockBox<PersonalDeviceInteractionsOptionsBag>();
97+
98+
var builder = GetGridBuilder();
99+
100+
box.ExpectedRowCount = null;
101+
box.Options = GetBoxOptions();
102+
box.GridDefinition = builder.BuildDefinition();
103+
104+
return box;
105+
}
106+
107+
/// <summary>
108+
/// Gets the box options required for the component.
109+
/// </summary>
110+
/// <returns>The options that provide additional details to the block.</returns>
111+
private PersonalDeviceInteractionsOptionsBag GetBoxOptions()
112+
{
113+
var options = new PersonalDeviceInteractionsOptionsBag();
114+
115+
var title = "Personal Device Interactions";
116+
var personalDevice = GetPersonalDevice();
117+
if ( personalDevice?.PersonAlias?.Person != null )
118+
{
119+
title = $"{personalDevice.PersonAlias.Person.FullName.ToPossessive()} Device Interactions";
120+
}
121+
options.BlockTitle = title;
122+
123+
// We use this to conditionally render certain columns.
124+
options.IsFilteredByDevice = personalDevice != null;
125+
126+
if ( personalDevice != null )
127+
{
128+
options.Platform = personalDevice.Platform?.Value;
129+
options.Version = personalDevice.DeviceVersion;
130+
131+
if ( personalDevice.PersonalDeviceTypeValueId.HasValue )
132+
{
133+
var deviceTypeValueId = personalDevice.PersonalDeviceTypeValueId.Value;
134+
var dv = DefinedValueCache.Get( deviceTypeValueId );
135+
options.IconCssClass = dv?.GetAttributeValue( "IconCssClass" );
136+
}
137+
}
138+
139+
return options;
140+
}
141+
142+
/// <inheritdoc/>
143+
protected override IQueryable<PersonalDeviceInteractionRow> GetListQueryable( RockContext rockContext )
144+
{
145+
rockContext.SqlLogging( true );
146+
var interactionService = new InteractionService( rockContext );
147+
var baseQuery = interactionService.Queryable()
148+
.AsNoTracking()
149+
.Where( i => i.PersonalDeviceId != null )
150+
.Include( i => i.PersonalDevice.PersonalDeviceType )
151+
.Include( i => i.PersonalDevice.Platform )
152+
.Include( i => i.PersonAlias.Person );
153+
154+
var personalDevice = GetPersonalDevice();
155+
156+
if ( personalDevice != null )
157+
{
158+
var deviceId = personalDevice.Id;
159+
baseQuery = baseQuery.Where( i => i.PersonalDeviceId == deviceId );
160+
}
161+
162+
var queryable = baseQuery.Select( i => new PersonalDeviceInteractionRow
163+
{
164+
Id = i.Id.ToString(),
165+
PersonalDeviceId = i.PersonalDeviceId.Value.ToString(),
166+
InteractionDateTime = i.InteractionDateTime,
167+
InteractionEndDateTime = i.InteractionEndDateTime,
168+
Details = i.InteractionSummary,
169+
AssignedIndividual = i.PersonAlias != null ? i.PersonAlias.Person : null,
170+
DeviceTypeValueId = i.PersonalDevice.PersonalDeviceTypeValueId,
171+
Platform = i.PersonalDevice.Platform != null
172+
? i.PersonalDevice.Platform.Value
173+
: null,
174+
Version = i.PersonalDevice.DeviceVersion
175+
} );
176+
177+
queryable = FilterByDateRange( queryable );
178+
179+
if ( FilterShowUnassignedDevices )
180+
{
181+
queryable = queryable.Where( r => r.AssignedIndividual == null );
182+
}
183+
184+
if ( FilterPresentDevices )
185+
{
186+
var startDateTime = RockDateTime.Now.AddMinutes( -GetAttributeValue( AttributeKey.CurrentlyPresentInterval ).AsInteger() );
187+
queryable = queryable.Where( r => r.InteractionEndDateTime.HasValue && r.InteractionEndDateTime.Value >= startDateTime );
188+
}
189+
190+
rockContext.SqlLogging( false );
191+
192+
return queryable;
193+
}
194+
195+
/// <inheritdoc/>
196+
protected override GridBuilder<PersonalDeviceInteractionRow> GetGridBuilder()
197+
{
198+
return new GridBuilder<PersonalDeviceInteractionRow>()
199+
.WithBlock( this )
200+
.AddTextField( "id", r => r.Id )
201+
.AddDateTimeField( "dateTime", r => r.InteractionDateTime.Date )
202+
.AddPersonField( "assignedIndividual", r => r.AssignedIndividual )
203+
.AddTextField( "details", r => r.Details )
204+
.AddTextField( "deviceType", r =>
205+
{
206+
if ( r.DeviceTypeValueId.HasValue )
207+
{
208+
var dv = DefinedValueCache.Get( r.DeviceTypeValueId.Value );
209+
return dv?.Value ?? string.Empty;
210+
}
211+
212+
return string.Empty;
213+
} )
214+
.AddTextField( "deviceTypeIconCssClass", r =>
215+
{
216+
if ( r.DeviceTypeValueId.HasValue )
217+
{
218+
var dv = DefinedValueCache.Get( r.DeviceTypeValueId.Value );
219+
return dv?.GetAttributeValue( "IconCssClass" ) ?? string.Empty;
220+
}
221+
222+
return string.Empty;
223+
} )
224+
.AddTextField( "platform", r => r.Platform )
225+
.AddTextField( "version", r => r.Version );
226+
}
227+
228+
#endregion Methods
229+
230+
#region Helper Methods
231+
232+
/// <summary>
233+
/// Gets the personal device from the page parameters if exists.
234+
/// </summary>
235+
private PersonalDevice GetPersonalDevice()
236+
{
237+
var key = PageParameter( PageParameterKey.PersonalDeviceId );
238+
239+
if ( key.IsNullOrWhiteSpace() )
240+
{
241+
return null;
242+
}
243+
244+
var personalDeviceService = new PersonalDeviceService( RockContext );
245+
var personalDevice = personalDeviceService
246+
.GetQueryableByKey( key )
247+
.AsNoTracking()
248+
.Include( pd => pd.Platform )
249+
.Include( pd => pd.PersonAlias.Person )
250+
.FirstOrDefault();
251+
252+
return personalDevice;
253+
}
254+
255+
/// <summary>
256+
/// Filters the queryable by the selected date range.
257+
/// </summary>
258+
/// <param name="queryable">The <see cref="PersonalDeviceInteractionRow"/> queryable</param>
259+
/// <returns></returns>
260+
private IQueryable<PersonalDeviceInteractionRow> FilterByDateRange( IQueryable<PersonalDeviceInteractionRow> queryable )
261+
{
262+
// Default to the last 6 months if a null/invalid range was selected.
263+
var defaultSlidingDateRange = new SlidingDateRangeBag
264+
{
265+
RangeType = SlidingDateRangeType.Last,
266+
TimeUnit = TimeUnitType.Month,
267+
TimeValue = 6
268+
};
269+
270+
var dateRange = FilterDateRange.Validate( defaultSlidingDateRange ).ActualDateRange;
271+
var dateTimeStart = dateRange.Start;
272+
var dateTimeEnd = dateRange.End;
273+
274+
queryable = queryable
275+
.Where( i =>
276+
i.InteractionDateTime >= dateTimeStart &&
277+
i.InteractionDateTime <= dateTimeEnd );
278+
279+
return queryable;
280+
}
281+
282+
#endregion Helper Methods
283+
284+
#region Helper Classes
285+
286+
/// <summary>
287+
/// A lightweight class containing only the data needed for the grid to function.
288+
/// </summary>
289+
public class PersonalDeviceInteractionRow
290+
{
291+
public string Id { get; set; }
292+
293+
public string PersonalDeviceId { get; set; }
294+
295+
public DateTime InteractionDateTime { get; set; }
296+
297+
public DateTime? InteractionEndDateTime { get; set; }
298+
299+
public string Details { get; set; }
300+
301+
public Person AssignedIndividual { get; set; }
302+
303+
public int? DeviceTypeValueId { get; set; }
304+
305+
public string Platform { get; set; }
306+
307+
public string Version { get; set; }
308+
}
309+
310+
#endregion Helper Classes
311+
}
312+
}

0 commit comments

Comments
 (0)