Added sorting to user list, ASCending and DESCending on first and last name

fixed pagination where it wasnt rounding up so <x.5 would show not 1 page less than required.
fix issue introduced in last branch where group drop down/filter wouldnt work.
#51
This commit is contained in:
chris.watts90@outlook.com 2020-02-25 14:48:49 +00:00
parent 1e633e97c7
commit 20bf968675
9 changed files with 227 additions and 101 deletions

View File

@ -12,7 +12,7 @@ namespace Interfaces
/// Returns <see cref="UserList"/> with full list of users,
/// plus a total user count. Pagination options are supported.
/// </returns>
UserList GetUsers(int pageNumber = -1, int pageSize = -1, int groupId = -1);
UserList GetUsers(int pageNumber = -1, int pageSize = -1, int groupId = -1, SortOptions sort = SortOptions.None);
/// <summary>
/// Search the user list for the following string
/// </summary>

View File

@ -72,6 +72,7 @@
<Compile Include="OperationResponse.cs" />
<Compile Include="Policy.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="SortOptions.cs" />
<Compile Include="TimeLog.cs" />
<Compile Include="TimeLogList.cs" />
<Compile Include="User.cs" />

View File

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Interfaces
{
public enum SortOptions
{
None,
FirstNameAscending,
FirstNameDescending,
LastNameAscending,
LastNameDescending,
}
}

View File

@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
namespace Interfaces
{
@ -14,13 +15,15 @@ namespace Interfaces
public int TotalUserCount { get; set; }
public List<User> Users { get; set; }
public SortOptions SelectedSortOption { get; set; }
public int PageCount
{
get
{
if (TotalUserCount < PageSize)
return 1;
return (TotalUserCount / PageSize);
return (int)Math.Ceiling(Convert.ToDouble(TotalUserCount) / Convert.ToDouble(PageSize));
}
}
public Group GroupFilter { get; set; }

View File

@ -27,9 +27,7 @@ namespace SQLiteRepository
+ "select " + nameof(GroupDb.GroupId)
+ " from " + nameof(GroupDb)
+ " where " + nameof(GroupDb.GroupName) + " = 'Archived') )"
+ "order by "
+ nameof(UserIdentity.LastName) + " collate nocase, "
+ nameof(UserIdentity.FirstName) + " collate nocase";
+ "order by ? collate nocase ?, ? collate nocase ?";
public const string GET_ALL_USERS_PAGINATE =
"select * from " + nameof(UserIdentity) + " ut "
@ -44,17 +42,17 @@ namespace SQLiteRepository
+ " from " + nameof(GroupDb)
+ " where " + nameof(GroupDb.GroupName) + " = 'Archived') )"
+ " order by "
+ nameof(UserIdentity.LastName) + " collate nocase, "
+ nameof(UserIdentity.FirstName) + " collate nocase "
+ "limit ? offset ?";
+ "{0} collate nocase {1}, "
+ "{2} collate nocase {3} "
+ "limit {4} offset {5}";
public const string GET_ALL_USERS_BY_GROUP =
"select u." + nameof(UserIdentity.Id) + ", u." + nameof(UserIdentity.FirstName) + ", u." +
nameof(UserIdentity.LastName) + ", u." + nameof(UserIdentity.HoursPerWeek) + ", u." +
nameof(UserIdentity.IsContractor) + " from " + nameof(UserIdentity) + " u left join " +
nameof(UserGroupJoinDb) + " ugj on ugj." + nameof(UserGroupJoinDb.UserId_FK) + " = u." +
nameof(UserIdentity.Id) + " where ugj." + nameof(UserGroupJoinDb.GroupId_FK) + "=? order by u." +
nameof(UserIdentity.LastName) + " collate nocase, u." + nameof(UserIdentity.LastName) + " collate nocase";
nameof(UserIdentity.Id) + " where ugj." + nameof(UserGroupJoinDb.GroupId_FK) + "= {0} " +
"order by u.{1} collate nocase {2}, u.{3} collate nocase {4}";
public const string GET_USER_BY_ID =
"select * from " + nameof(UserIdentity) + " where " + nameof(UserIdentity.Id) + "=?";
@ -96,7 +94,18 @@ namespace SQLiteRepository
nameof(TimeLogDb.SwipeEventDateTime) + " desc LIMIT 1";
public const string GET_TOTAL_USER_COUNT =
"select Max(" + nameof(UserIdentity.Id) + ") from " + nameof(UserIdentity);
"select count(1) from " + nameof(UserIdentity) + " ut "
+ "where "
+ "EXISTS( select " + nameof(GroupDb.GroupId)
+ " from " + nameof(GroupDb)
+ " where " + nameof(GroupDb.GroupName) + " = 'Archived') "
+ "AND NOT EXISTS( select * from " + nameof(UserGroupJoinDb) + " ugp where "
+ nameof(UserGroupJoinDb.UserId_FK) + " = ut.Id"
+ " and " + nameof(UserGroupJoinDb.GroupId_FK) + " = ( "
+ "select " + nameof(GroupDb.GroupId)
+ " from " + nameof(GroupDb)
+ " where " + nameof(GroupDb.GroupName) + " = 'Archived') )";
//"select Max(" + nameof(UserIdentity.Id) + ") from " + nameof(UserIdentity);
public const string GET_USER_CONTRACTED_HOURS =
"select " + nameof(UserIdentity.HoursPerWeek) + " From UserIdentity where " + nameof(UserIdentity.Id) + "=?";

View File

@ -45,10 +45,10 @@ namespace SQLiteRepository
CheckForDbUpgrade();
}
public UserList GetUsers(int pageNumber = -1, int pageSize = -1, int groupId = -1)
public UserList GetUsers(int pageNumber = -1, int pageSize = -1, int groupId = -1, SortOptions sort = SortOptions.None)
{
var ret = new UserList();
List<UserIdentity> users = GetUserList(groupId, pageSize, pageNumber);
List<UserIdentity> users = GetUserList(groupId, pageSize, pageNumber, sort);
var userCount = GetUserCount();
@ -555,24 +555,56 @@ namespace SQLiteRepository
return _connection.ExecuteScalar<int>(SQLiteProcedures.GET_TOTAL_USER_COUNT);
}
private List<UserIdentity> GetUserList(int groupId = -1, int pageSize=-1, int pageNumber=-1)
private List<UserIdentity> GetUserList(int groupId = -1, int pageSize = -1, int pageNumber = -1, SortOptions sort = SortOptions.None)
{
List<UserIdentity> users;
var orderByFirst = nameof(UserIdentity.LastName);
var firstOrderDir = "ASC";
var orderBySecond = nameof(UserIdentity.FirstName);
var secondOrderDir = "ASC";
if (sort != SortOptions.None)
{
switch (sort)
{
case SortOptions.FirstNameAscending:
orderByFirst = nameof(UserIdentity.FirstName);
firstOrderDir = "ASC";
orderBySecond = nameof(UserIdentity.LastName);
secondOrderDir = "ASC";
break;
case SortOptions.FirstNameDescending:
orderByFirst = nameof(UserIdentity.FirstName);
firstOrderDir = "DESC";
orderBySecond = nameof(UserIdentity.LastName);
secondOrderDir = "ASC";
break;
case SortOptions.LastNameDescending:
firstOrderDir = "DESC";
break;
}
}
if (pageNumber != -1 && pageSize != -1)
{
users = _connection.Query<UserIdentity>(SQLiteProcedures.GET_ALL_USERS_PAGINATE,
pageSize, (pageNumber - 1) * pageSize);
var qString = string.Format(SQLiteProcedures.GET_ALL_USERS_PAGINATE, orderByFirst, firstOrderDir,
orderBySecond, secondOrderDir, pageSize, (pageNumber - 1) * pageSize);
users = _connection.Query<UserIdentity>(qString);
}
else if (groupId != -1)
{
var qString = string.Format(SQLiteProcedures.GET_ALL_USERS_BY_GROUP, groupId,
orderByFirst, firstOrderDir,
orderBySecond, secondOrderDir);
users =
_connection.Query<UserIdentity>(
SQLiteProcedures.GET_ALL_USERS_BY_GROUP,
groupId);
_connection.Query<UserIdentity>(qString);
}
else
{
users = _connection.Query<UserIdentity>(SQLiteProcedures.GET_ALL_USERS);
users = _connection.Query<UserIdentity>(SQLiteProcedures.GET_ALL_USERS,
orderByFirst, firstOrderDir,
orderBySecond, secondOrderDir);
}
return users;

View File

@ -30,17 +30,18 @@ namespace WindowsDataCenter
public IHttpActionResult GetUsers([FromUri] string query = ""
, [FromUri] int pageSize = -1
, [FromUri] int pageNumber = -1
, [FromUri] int groupId = -1)
, [FromUri] int groupId = -1
, [FromUri] SortOptions sort = SortOptions.None)
{
_logger.Trace("GetUsers called with arguments >> query: {0}, pageSize: {1}, pageNumber: {2}, groupFilter: {3}", query, pageSize, pageNumber, groupId);
_logger.Trace("GetUsers called with arguments >> query: {0}, pageSize: {1}, pageNumber: {2}, groupFilter: {3}, sort: {4}", query, pageSize, pageNumber, groupId, sort);
pageNumber = pageNumber == -1 ? 1 : pageNumber;
pageSize = GetPageSize(pageSize);
var userList = query != string.Empty
? _repo.Search(query)
: groupId != -1
? _repo.GetUsers(groupId: groupId)
: _repo.GetUsers(pageNumber, pageSize);
? _repo.GetUsers(groupId: groupId, sort:sort)
: _repo.GetUsers(pageNumber, pageSize, sort:sort);
_logger.Trace("Got UserList from Repository, UserCount: {0}", userList.UserCount);
if (query != string.Empty)
{
@ -57,6 +58,7 @@ namespace WindowsDataCenter
userList.PageNumber = pageNumber;
userList.PageSize = pageSize;
userList.SelectedSortOption = sort;
_logger.Trace("Returning UserList from GetUsers.");
var msg = Request.CreateResponse(HttpStatusCode.OK, userList);

View File

@ -86,8 +86,23 @@
<thead>
<tr>
<th class="col-md-1"></th>
<th class="col-md-3">First Name</th>
<th class="col-md-3">Last Name</th>
<th class="col-md-3">
<div class="col-md-1">
<a href="#users?sort=firstAsc"><span data-bind="css:{ 'text-success': $root.sortIsActive('firstAsc')}" class="glyphicon glyphicon-chevron-up"></span></a>
</div>
<div class="col-md-1">
<a href="#users?sort=firstDesc"><span data-bind="css:{ 'text-success': $root.sortIsActive('firstDesc')}" class="glyphicon glyphicon-chevron-down"></span></a>
</div>
<span class="col-md-9">First Name</span>
</th>
<th class="col-md-3">
<div class="col-md-1">
<a href="#users?sort=lastAsc"><span data-bind="css:{ 'text-success': $root.sortIsActive('lastAsc')}" class="glyphicon glyphicon-chevron-up"></span></a>
</div>
<div class="col-md-1">
<a href="#users?sort=lastDesc"><span data-bind="css:{ 'text-success': $root.sortIsActive('lastDesc')}"class="glyphicon glyphicon-chevron-down"></span></a>
</div>
<span class="col-md-9">Last Name</span></th>
<th class="col-md-1 text-center">Contractor</th>
<th/>
<th/>

View File

@ -1,4 +1,10 @@
function DataVM() {
const SortOptions = {
LastAsc: "LastNameAscending",
LastDesc: "LastNameDescending",
FirstAsc: "FirstNameAscending",
FirstDesc: "FirstNameDescending"
};
function DataVM() {
"use strict";
var self = this;
self.helpers = new Helpers();
@ -23,6 +29,7 @@
self.policyChangeDate = ko.observable(null);
self.policyChangeAuthor = ko.observable(null);
self.policyVersion = ko.observable(null);
self.selectedSort = ko.observable(null);
self.apiEndpoints = {
root: "http://localhost:8800",
getUserList: "/api/users",
@ -156,7 +163,7 @@
var args = [
{
key: "groupId",
value: datacreateContextMenu
value: data
}
];
var url = self.helpers.createRequestUrl("users", args, false, false);
@ -221,25 +228,32 @@
});
}
};
self.getUserList = function (pageSize, pageNumber, groupId) {
var args = null;
self.getUserList = function (pageSize, pageNumber, groupId, sort) {
var args = [];
if (pageSize && pageNumber) {
args = [
args.push(
{
key: "pageSize",
value: pageSize
},
});
args.push(
{
key: "pageNumber",
value: pageNumber
});
}
];
} else if(groupId) {
args = [
if (groupId) {
args.push(
{
key: "groupId",
value: groupId
}];
});
}
if (sort) {
args.push({
key: "sort",
value: sort
});
}
var url = self.helpers.createRequestUrl(self.apiEndpoints.getUserList, args, false);
$.getJSON(url, function (res) {
@ -261,9 +275,9 @@
self.assignErrorObject(errObj.errorCode, errObj.errorMessage, "getUserList");
});
};
self.searchUsers = function(query) {
self.searchUsers = function(query, sort) {
var url = self.helpers.createRequestUrl(self.apiEndpoints.getUserList,
[{ key: "query", value: query }], false, false);
[{ key: "query", value: query }, {key:"sort",value:sort}], false, false);
$.getJSON(url,
function(res) {
self.userList(res);
@ -426,12 +440,46 @@
maxDate: moment(date).endOf("week")
});
};
function convertSortOption(opt) {
if (!opt) {
return SortOptions.LastAsc;
}
if (opt === "firstAsc") {
return SortOptions.FirstAsc;
}
if (opt === "firstDesc") {
return SortOptions.FirstDesc;
}
if (opt === "lastAsc") {
return SortOptions.LastAsc;
}
if (opt === "lastDesc") {
return SortOptions.LastDesc;
}
};
self.sortIsActive = function (option) {
if (option === "firstAsc" && self.userList().SelectedSortOption === SortOptions.FirstAsc) {
return true;
}
if (option === "firstDesc" && self.selectedSort() === SortOptions.FirstDesc) {
return true;
}
if (option === "lastAsc" && self.selectedSort() === SortOptions.LastAsc) {
return true;
}
if (option === "lastDesc" && self.selectedSort() === SortOptions.LastDesc) {
return true;
}
return false;
};
Sammy(function () {
this.get("#users", function () {
var query = this.params.query;
var pageSize = this.params.pageSize;
var pageNumber = this.params.pageNumber;
var groupId = this.params.groupId;
var sort = convertSortOption(this.params.sort);
console.log(sort);
self.chosenMenuItemId("Home");
self.groupsList(null);
self.chosenUserDetails(null);
@ -444,11 +492,11 @@
}
self.getGroups(function (data) { self.groupsList(data); });
if (query)
self.searchUsers(query);
self.searchUsers(query, sort);
else if (groupId && groupId > 0)
self.getUserList(null, null, groupId);
self.getUserList(null, null, groupId, sort);
else
self.getUserList(pageSize, pageNumber);
self.getUserList(pageSize, pageNumber, null,sort);
});
this.get("#userData/:userId", function () {
self.chosenMenuItemId("Data");
@ -528,7 +576,6 @@
this.post("#manualLog",
function() {
self.createManualLog(self.manualLog());
$('#manualLogDialog').modal("hide");
//self.goToTimeLogs(self.chosenTimeLogUserId, null, [{ key: "selectedDate", value: self.selectedTimeLogDate() }]);
});