Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
76 commits
Select commit Hold shift + click to select a range
f802650
paginate substation images
nbeatty-gpa May 11, 2026
540dcb1
reset to first page on sort
nbeatty-gpa May 19, 2026
87fba2f
reset to first page on sort
nbeatty-gpa May 19, 2026
85c58cb
reset to first page on sort
nbeatty-gpa May 19, 2026
37e2846
reset to first page on sort
nbeatty-gpa May 19, 2026
d27bd15
reset to first page on sort
nbeatty-gpa May 19, 2026
6f3e5c5
fix styling for paging
nbeatty-gpa May 22, 2026
0a1bf24
paginate value list group item
nbeatty-gpa May 26, 2026
b4efcc9
page asset ConnectedChannels endpoint
nbeatty-gpa May 27, 2026
854e0d9
page Asset Channels table
nbeatty-gpa May 27, 2026
4ae5e72
paginate tables tab of external db
nbeatty-gpa May 28, 2026
1e9a829
Fix error filtering users by additional fields
nbeatty-gpa Jun 5, 2026
cb13c06
Refactor byUser page from slices to local state with Generic Controller
nbeatty-gpa Jun 5, 2026
9d87da8
clean up byUser
nbeatty-gpa Jun 5, 2026
c4eba4d
move ByUserGroup from GenericSlice to GenericController
nbeatty-gpa Jun 5, 2026
d3d42ba
paginate GroupUsers
nbeatty-gpa Jun 8, 2026
3024f63
paginate ExternalDBTableFields
nbeatty-gpa Jun 8, 2026
32fec19
paginate byAssetGroup
nbeatty-gpa Jun 9, 2026
44fbf34
paginate assetGroupSubGroups
nbeatty-gpa Jun 9, 2026
d7fe2a6
paginate assetGroupsAssets
nbeatty-gpa Jun 9, 2026
e221065
paginate assetGroupMeters
nbeatty-gpa Jun 9, 2026
fd5f157
paginate assetSubstations
nbeatty-gpa Jun 9, 2026
9a3c974
paginate assetMeters
nbeatty-gpa Jun 9, 2026
4ff0cdf
paginate assetConnections
nbeatty-gpa Jun 9, 2026
8044470
paginate customerMeter
nbeatty-gpa Jun 9, 2026
58dc1a3
paginate customerAsset
nbeatty-gpa Jun 9, 2026
8d6887d
paginate MeterTrendChannel
nbeatty-gpa Jun 9, 2026
c415aa3
remove accidental comment
nbeatty-gpa Jun 9, 2026
997971e
paginate meterChannelScaling table
nbeatty-gpa Jun 9, 2026
b10e624
paginate meterEventChannels
nbeatty-gpa Jun 10, 2026
69c7c06
Paginate remoteXDA assets
nbeatty-gpa Jun 10, 2026
161bd4b
Paginate remoteXDA meters
nbeatty-gpa Jun 10, 2026
d228bd4
simplify settings sort
nbeatty-gpa Jun 10, 2026
074c3f0
clean up user and userGroup
nbeatty-gpa Jun 10, 2026
f5c0f50
fix generic controller typing
nbeatty-gpa Jun 10, 2026
b927cff
fix dependency array
nbeatty-gpa Jun 10, 2026
509c94a
use stricter typing in EventChannelSlice
nbeatty-gpa Jun 10, 2026
c275f03
changes to store typing
nbeatty-gpa Jun 10, 2026
e57fff3
cleanup import
nbeatty-gpa Jun 10, 2026
12be17c
fix typing
nbeatty-gpa Jun 10, 2026
999bb99
refresh on changed
nbeatty-gpa Jun 10, 2026
8b51703
fix broken Additional Field selector in ExternalDBTable
nbeatty-gpa Jun 11, 2026
1693e4b
fix decimal page
nbeatty-gpa Jun 15, 2026
afa3bf3
fix grammar mistakes in ExternalDBUpdate
nbeatty-gpa Jun 15, 2026
337e4f1
do not error out completely on uncompleted search
nbeatty-gpa Jun 15, 2026
bc23998
fix utf-A typo
nbeatty-gpa Jun 19, 2026
990a20c
remove companySlice from merged store
nbeatty-gpa Jun 19, 2026
151daa0
abort correct handle
nbeatty-gpa Jun 19, 2026
79d654b
return empty PagedResults if no images found for substation
nbeatty-gpa Jun 19, 2026
603c26a
include 'loading' status during paged search
nbeatty-gpa Jun 19, 2026
ac299bc
filter customer assets on customer ID
nbeatty-gpa Jun 19, 2026
cf42ee2
add filters to value list
nbeatty-gpa Jun 19, 2026
bedf1f3
fix effect cleanup logic
nbeatty-gpa Jun 22, 2026
dfce438
check OrderBy values
nbeatty-gpa Jun 22, 2026
9d677a5
correct use of hasPermissions
nbeatty-gpa Jun 23, 2026
7d91e57
clean up substation images
nbeatty-gpa Jun 23, 2026
3842579
move valuelistitem away from slices
nbeatty-gpa Jun 23, 2026
756453e
remove unused imports
nbeatty-gpa Jun 26, 2026
e0fc35f
fix use effect returns
nbeatty-gpa Jun 26, 2026
bef2690
cleanup valuelistitem
nbeatty-gpa Jun 26, 2026
258f604
changes to store typing
nbeatty-gpa Jun 10, 2026
918bac7
fix cleanup function
nbeatty-gpa Jun 29, 2026
e151161
move usergroups away from slices
nbeatty-gpa Jun 29, 2026
197c8c5
update gemstone
nbeatty-gpa Jun 29, 2026
c97d41a
remove DataFileSlice
nbeatty-gpa Jun 29, 2026
e0ded17
clean up value list items table
nbeatty-gpa Jul 2, 2026
c68defc
fix refresh on change
nbeatty-gpa Jul 2, 2026
ac9db13
cleanup
nbeatty-gpa Jul 2, 2026
113e197
move CustomerAsset away from slices
nbeatty-gpa Jul 2, 2026
392be9e
move CustomerMeter away from slices
nbeatty-gpa Jul 2, 2026
bb15609
move ExternalDBTableFields away from slices
nbeatty-gpa Jul 6, 2026
d0af07c
revert callback pattern
nbeatty-gpa Jul 6, 2026
d2ff630
cleanup user
nbeatty-gpa Jul 6, 2026
a1b0e49
cleanup extdb tables
nbeatty-gpa Jul 6, 2026
59a1c23
remove dead callback
nbeatty-gpa Jul 6, 2026
890d09d
remove dead callback
nbeatty-gpa Jul 6, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,14 @@
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Net.Http;
using System.Transactions;
using System.Reflection;
using System.Web.Http;
using GSF.Data;
using GSF.Data.Model;
using GSF.Web.Model;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using openXDA.Model;
using SystemCenter.Model;

namespace SystemCenter.Controllers.OpenXDA
{
Expand Down Expand Up @@ -105,6 +104,78 @@ GROUP BY
return Unauthorized();
}

[HttpPost, Route("{assetGroupID:int}/Assets/{page:int}")]
public IHttpActionResult GetAssetsPaged([FromBody] PostData postData, [FromUri] int assetGroupID, [FromUri] int page)
{

if (!GetAuthCheck())
return Unauthorized();

int recordsPerPage = Take ?? 50;

PagedResults results = new PagedResults();
results.RecordsPerPage = recordsPerPage;

string orderBy = "ID";

if (typeof(Asset).GetProperties().Select(prop => prop.Name).Contains(postData.OrderBy) || postData.OrderBy == "AssetType")
{
orderBy = postData.OrderBy;
}

using (AdoDataConnection connection = new AdoDataConnection(Connection))
{
string sql = $@"SELECT
DISTINCT
Asset.ID,
AssetAssetGroup.AssetGroupID,
Asset.AssetKey,
Asset.AssetName,
Asset.VoltageKV,
AssetType.Name as AssetType,
COUNT(DISTINCT Meter.ID) as Meters,
COUNT(DISTINCT Location.ID) as Locations
FROM
Asset Join
AssetType ON Asset.AssetTypeID = AssetType.ID LEFT JOIN
MeterAsset ON MeterAsset.AssetID = Asset.ID LEFT JOIN
Meter ON MeterAsset.MeterID = Meter.ID LEFT JOIN
AssetLocation ON AssetLocation.AssetID = Asset.ID LEFT JOIN
Location ON AssetLocation.LocationID = Location.ID LEFT JOIN
AssetAssetGroup ON Asset.ID = AssetAssetGroup.AssetID
GROUP BY
Asset.ID,
Asset.AssetKey,
Asset.AssetName,
Asset.VoltageKV,
AssetType.Name,
AssetAssetGroup.AssetGroupID
HAVING AssetAssetGroup.AssetGroupID = {{0}}
ORDER BY {orderBy} {(postData.Ascending ? "ASC" : "DESC")}
";
Comment thread
nbeatty-gpa marked this conversation as resolved.

DataTable records = connection.RetrieveData(sql, assetGroupID);

int totalRecords = records.Rows.Count;

DataRow[] rows = records.AsEnumerable()
.Skip((page) * recordsPerPage)
.Take(recordsPerPage)
.ToArray();

DataTable pagedTable = records.Clone();

foreach (DataRow row in rows)
pagedTable.ImportRow(row);

results.TotalRecords = totalRecords;
results.NumberOfPages = (totalRecords + recordsPerPage - 1) / recordsPerPage;
results.Data = JsonConvert.SerializeObject(pagedTable);
}

return Ok(results);
}

[HttpPost, Route("{assetGroupID:int}/AddAssets")]
public IHttpActionResult AddAssets(int assetGroupID, [FromBody] IEnumerable<int> assets)
{
Expand Down Expand Up @@ -205,6 +276,73 @@ GROUP BY
return Unauthorized();
}

[HttpPost, Route("{assetGroupID:int}/Meters/{page:int}")]
public IHttpActionResult GetMetersPaged([FromBody] PostData postData, [FromUri] int assetGroupID, [FromUri] int page)
{
if (!GetAuthCheck())
return Unauthorized();

int recordsPerPage = Take ?? 50;

PagedResults results = new PagedResults();
results.RecordsPerPage = recordsPerPage;

string orderBy = "ID";

if (typeof(Meter).GetProperties().Select(prop => prop.Name).Contains(postData.OrderBy))
orderBy = postData.OrderBy;

using (AdoDataConnection connection = new AdoDataConnection(Connection))
{
string sql = $@"SELECT DISTINCT
Meter.ID,
MeterAssetGroup.AssetGroupID,
Meter.AssetKey,
Meter.Name,
Meter.Make,
Meter.Model,
Location.Name as Location,
COUNT(DISTINCT MeterAsset.AssetID) as MappedAssets
FROM
Meter LEFT JOIN
Location ON Meter.LocationID = Location.ID LEFT JOIN
MeterAsset ON Meter.ID = MeterAsset.MeterID LEFT JOIN
Asset ON MeterAsset.AssetID = Asset.ID LEFT JOIN
MeterAssetGroup ON Meter.ID = MeterAssetGroup.MeterID
GROUP BY
Meter.ID,
Meter.AssetKey,
Meter.Name,
Meter.Make,
Meter.Model,
Location.Name,
MeterAssetGroup.AssetGroupID
HAVING MeterAssetGroup.AssetGroupID = {{0}}
ORDER BY {orderBy} {(postData.Ascending ? "ASC" : "DESC")}
";
Comment thread
nbeatty-gpa marked this conversation as resolved.

DataTable records = connection.RetrieveData(sql, assetGroupID);

int totalRecords = records.Rows.Count;

DataRow[] rows = records.AsEnumerable()
.Skip((page) * recordsPerPage)
.Take(recordsPerPage)
.ToArray();

DataTable pagedTable = records.Clone();

foreach (DataRow row in rows)
pagedTable.ImportRow(row);

results.TotalRecords = totalRecords;
results.NumberOfPages = (totalRecords + recordsPerPage - 1) / recordsPerPage;
results.Data = JsonConvert.SerializeObject(pagedTable);
}

return Ok(results);
}

[HttpPost, Route("{assetGroupID:int}/AddMeters")]
public IHttpActionResult AddMeters(int assetGroupID, [FromBody] IEnumerable<int> meters)
{
Expand Down Expand Up @@ -293,7 +431,6 @@ public IHttpActionResult GetSubGroups(int assetGroupID)
try
{
IEnumerable<AssetGroupView> records = new TableOperations<AssetGroupView>(connection).QueryRecordsWhere("ID in (SELECT ChildAssetGroupID FROM AssetGroupAssetGroupView WHERE ParentAssetGroupID = {0})", assetGroupID);

return Ok(records);
}
catch (Exception ex)
Expand All @@ -306,6 +443,33 @@ public IHttpActionResult GetSubGroups(int assetGroupID)
return Unauthorized();
}

[HttpPost, Route("{assetGroupID:int}/AssetGroups/{page:int}")]
public IHttpActionResult GetSubGroupsPaged([FromBody] PostData postData, [FromUri] int assetGroupID, [FromUri] int page)
{
if (!GetAuthCheck())
return Unauthorized();

int recordsPerPage = Take ?? 50;

PagedResults results = new PagedResults();
results.RecordsPerPage = recordsPerPage;

using (AdoDataConnection connection = new AdoDataConnection(Connection))
{
IEnumerable<AssetGroupView> records = new TableOperations<AssetGroupView>(connection).QueryRecordsWhere("ID in (SELECT ChildAssetGroupID FROM AssetGroupAssetGroupView WHERE ParentAssetGroupID = {0})", assetGroupID);
if (postData.Ascending)
records = records.OrderBy(record => record.GetType().GetProperty(postData.OrderBy).GetValue(record) ?? record.ID);
else
records = records.OrderByDescending(record => record.GetType().GetProperty(postData.OrderBy).GetValue(record) ?? record.ID);

results.TotalRecords = records.Count();
results.NumberOfPages = (records.Count() + recordsPerPage - 1) / recordsPerPage;
results.Data = JsonConvert.SerializeObject(records.Skip(page * recordsPerPage).Take(recordsPerPage));
}

return Ok(results);
}

[HttpPost, Route("{assetGroupID:int}/AddAssetGroups")]
public IHttpActionResult AddSubgroups(int assetGroupID, [FromBody] IEnumerable<int> subGroups)
{
Expand Down
Loading