diff --git a/DataCenter_Windows/WindowsDataCenter/Interfaces/IRepository.cs b/DataCenter_Windows/WindowsDataCenter/Interfaces/IRepository.cs index 8cf0ea0..2a8c720 100644 --- a/DataCenter_Windows/WindowsDataCenter/Interfaces/IRepository.cs +++ b/DataCenter_Windows/WindowsDataCenter/Interfaces/IRepository.cs @@ -11,6 +11,15 @@ /// UserList GetUsers(); /// + /// Search the user list for the following string + /// + /// string to search the user store for. + /// + /// Returns with full list of users, + /// plus a total user count. Pagination options are supported. + /// + UserList Search(string searchParam); + /// /// Get details about a single user in the system base on their Id /// /// diff --git a/DataCenter_Windows/WindowsDataCenter/Interfaces/UserList.cs b/DataCenter_Windows/WindowsDataCenter/Interfaces/UserList.cs index 303d7d3..701dfe7 100644 --- a/DataCenter_Windows/WindowsDataCenter/Interfaces/UserList.cs +++ b/DataCenter_Windows/WindowsDataCenter/Interfaces/UserList.cs @@ -8,6 +8,7 @@ namespace Interfaces { Users = new List(); } + public string Query { get; set; } public int UserCount { get { return Users.Count; } } public List Users { get; set; } public int PageSize { get; set; } diff --git a/DataCenter_Windows/WindowsDataCenter/SQLiteRepository/SQLiteProcedures.cs b/DataCenter_Windows/WindowsDataCenter/SQLiteRepository/SQLiteProcedures.cs index 959b755..1ed3431 100644 --- a/DataCenter_Windows/WindowsDataCenter/SQLiteRepository/SQLiteProcedures.cs +++ b/DataCenter_Windows/WindowsDataCenter/SQLiteRepository/SQLiteProcedures.cs @@ -14,5 +14,6 @@ namespace SQLiteRepository public const string UPDATE_CARD_USER_ID = "update CardUniqueId set UserId_FK=? where Id=?"; + public const string SEARCH_USER_LIST = "SELECT * FROM[UserIdentity] where(FirstName Like ? OR LastName Like ?)"; } } \ No newline at end of file diff --git a/DataCenter_Windows/WindowsDataCenter/SQLiteRepository/SQLiteRepository.cs b/DataCenter_Windows/WindowsDataCenter/SQLiteRepository/SQLiteRepository.cs index 4afd5f6..8dd9c76 100644 --- a/DataCenter_Windows/WindowsDataCenter/SQLiteRepository/SQLiteRepository.cs +++ b/DataCenter_Windows/WindowsDataCenter/SQLiteRepository/SQLiteRepository.cs @@ -58,6 +58,45 @@ namespace SQLiteRepository return ret; } + public UserList Search(string searchParam) + { + var ret = new UserList(); + searchParam = string.Format("%{0}%", searchParam); + var users = _connection.Query( + SQLiteProcedures.SEARCH_USER_LIST, + searchParam, searchParam); + + if (!users.Any()) + { + ret.PageNumber = 1; + ret.PageSize = 20; + return ret; + } + + foreach (var user in users) + { + var userObj = ChangeToUserObject(user); + var cards = _connection.Query( + SQLiteProcedures.GET_CARDS_BY_USER_ID, + user.Id); + + foreach (var card in cards) + { + userObj.AssociatedIdentifiers.Add(new Identifier() + { + UniqueId = card.CardUId, + IsAssociatedToUser = true, + Id = card.Id + }); + } + ret.Users.Add(userObj); + } + ret.PageSize = 20; + ret.PageNumber = 1; + + return ret; + } + public User GetUser(int id) { var ret = new User(); diff --git a/DataCenter_Windows/WindowsDataCenter/WindowsDataCenter/Controllers/UsersController.cs b/DataCenter_Windows/WindowsDataCenter/WindowsDataCenter/Controllers/UsersController.cs index 0322f2d..2ed6dd7 100644 --- a/DataCenter_Windows/WindowsDataCenter/WindowsDataCenter/Controllers/UsersController.cs +++ b/DataCenter_Windows/WindowsDataCenter/WindowsDataCenter/Controllers/UsersController.cs @@ -19,9 +19,10 @@ namespace WindowsDataCenter [HttpGet] [Route("")] - public IHttpActionResult GetUsers([FromUri] int pageSize = -1, [FromUri] int pageNumber =-1) + public IHttpActionResult GetUsers([FromUri] string query = "",[FromUri] int pageSize = -1, [FromUri] int pageNumber =-1) { - var userList = _repo.GetUsers(); + var userList = query == string.Empty ? _repo.GetUsers() : _repo.Search(query); + userList.Query = query == string.Empty ? null : query; var msg = Request.CreateResponse(HttpStatusCode.OK, userList); diff --git a/DataCenter_Windows/WindowsDataCenter/WindowsDataCenter/www/index.html b/DataCenter_Windows/WindowsDataCenter/WindowsDataCenter/www/index.html index ba936f5..4c38957 100644 --- a/DataCenter_Windows/WindowsDataCenter/WindowsDataCenter/www/index.html +++ b/DataCenter_Windows/WindowsDataCenter/WindowsDataCenter/www/index.html @@ -2,9 +2,19 @@ Flexi Time Data Viewer - - - + + + + + + + + + + + + -
+
-
+
- + - -
-
+ + +

-
- +
+
@@ -76,37 +86,45 @@ -
+

- +
- - + +
- +
- + +
+
+
+ + + + +

- +
- + - +
@@ -122,21 +140,21 @@
- + - +

- +
-
+
@@ -150,12 +168,9 @@
-
-

Content

ID
@@ -230,13 +245,11 @@ - - - - - - + + \ No newline at end of file diff --git a/DataCenter_Windows/WindowsDataCenter/WindowsDataCenter/www/spa.js b/DataCenter_Windows/WindowsDataCenter/WindowsDataCenter/www/spa.js index 37fff59..b969143 100644 --- a/DataCenter_Windows/WindowsDataCenter/WindowsDataCenter/www/spa.js +++ b/DataCenter_Windows/WindowsDataCenter/WindowsDataCenter/www/spa.js @@ -1,18 +1,4 @@ -//(function ($) { -// "use strict"; -// $.fn.clickToggle = function (func1, func2) { -// var funcs = [func1, func2]; -// this.data("toggleclicked", 0); -// this.click(function () { -// var data = $(this).data(); -// var tc = data.toggleclicked; -// $.proxy(funcs[tc], this)(); -// data.toggleclicked = (tc + 1) % 2; -// }); -// return this; -// }; -//}(jQuery)); -function DataVM() { +function DataVM() { "use strict"; var self = this; self.menuOptions = ["Users", "Data", "Stats", "Other"]; @@ -34,14 +20,29 @@ function DataVM() { users: "users", userDetails: "userData", timeLogs: "timelogs", - home: this.users + home: function () { return this.users; } }; self.goToMenuOption = function (menu) { location.hash = menu; console.log("goToMenuOption: " + menu); }; - self.goToUserDetails = function (user) { location.hash = self.uiPages.userDetails + "/" + user.Id; }; - self.goToTimeLogs = function (user) { location.hash= "timelogs" + "/" + user.Id; }; - self.createRequestUrl = function (routePath, params, requiresCallback) { + self.goToUserDetails = function (user) { location.hash = self.uiPages.userDetails + "/" + user.UserId; }; + self.goToTimeLogs = function (user) { location.hash = "timelogs" + "/" + user.UserId; }; + /** + * Create a request URL - references apiEndpoints object to construct url with args, and optional callback url. + * @param {string} routePath + * @param {Array} params - Key, Value object detailing the param name (key) and value (value). + * @param {boolean} requiresCallback - True - add callback function for JSONP/CORS. + * @param {boolean} isRelativePath - True, create a relative URL (without root). + * @returns {string} the url generated + * @example + * createRequestUrl("/api/endpoint", [{key:"param", value:"value"}], true, false); + * returns: "http://192.168.2.2/api/endpoint?param=value&callback=?" + */ + self.createRequestUrl = function (routePath, params, requiresCallback, isRelativePath) { var appender = "?"; - var url = self.apiEndpoints.root + routePath; + var url = ""; + if (isRelativePath) { + url = self.apiEndpoints.root; + } + url = url + routePath; if (params !== undefined && params !== null) { if (params.length > 0) { @@ -56,8 +57,13 @@ function DataVM() { } return url; }; - //this function looks for a custom attribute called "pagedestination". - //if this is used as a clickhandler, the pagedestination attribute should name the page you want. + /** + * Function to redirect to a page in the sammy.js eco system. + * Relies on "pagedestination" tag in the html. This is a button click handler. + * @param {Object} data - dunno? + * @param {Object} event - handle to the button that was clicked. + * @returns {nothing} - redirects to the url referenced by the pageDestination tag. + */ self.returnButtonClick = function (data, event) { var target = null; if (event.target) target = event.target; @@ -70,102 +76,145 @@ function DataVM() { break; } } - console.log(destination); - self.goToMenuOption(destination); //redirect to whereever the button is telling us to go.. + if (destination !== "") { + console.log(destination); + self.goToMenuOption(destination); //redirect to whereever the button is telling us to go.. + } } else { console.log("target is null, going nowhere"); } }; + self.initDatePicker = function () { + $("#weeklyDatePicker").datepicker({ + weekStart: 1, + maxViewMode: 2, + endDate: "+0d", + todayBtn: true, + format: "yyyy-mm-dd", + todayHighlight: true, + calendarWeeks: true + }); + $("#weeklyDatePicker").datepicker("setDate", new Date().toDateString("yyyy-mm-dd")); + console.log("finished init"); + }; + self.assignHandler = function () { + //console.log('shall I assign?'); + var elem = $("#weeklyDatePicker")[0]; + var data = jQuery.hasData(elem) && jQuery._data(elem); + if (!data.events.changeDate) { + //console.log("assigning.."); + $("#weeklyDatePicker").on("changeDate", function (e) { + var kk = e.date; + //console.log(kk); + //console.log( + // "1: Iso Week Number: " + moment(kk).isoWeek() + " of " + + // moment(kk).weeksInYear() + //); + //console.log("before: " + self.selectedCalendarWeek()); + self.selectedCalendarWeek(moment(kk).isoWeek()); + //console.log("after: " + self.selectedCalendarWeek()); + }); + } + } self.getUserList = function () { - console.log("beginGetUserData"); - var url = self.createRequestUrl(self.apiEndpoints.getUserList, null, true); + //console.log("beginGetUserData"); + var url = self.createRequestUrl(self.apiEndpoints.getUserList, null, false); console.log(url); $.getJSON(url, function (res) { - console.log("getting user data"); - console.log(res); + //console.log("getting user data"); + //console.log(res); self.userList(res); }).fail(function () { console.log("error - getusers"); }); }; + self.searchUsers = function(query) { + var url = self.createRequestUrl(self.apiEndpoints.getUserList, + [{ key: "query", value: query }], false, false); + $.getJSON(url, + function(res) { + self.userList(res); + }).fail(function(res) { + self.goToMenuOption(self.uiPages.home()); + } + ); + }; self.getUserDetails = function (userId) { - console.log("beginGetUserDetailsData"); - //var url = self.apiEndpoints.root + self.apiEndpoints.getUserDetails + "/" + userId; - var url = self.createRequestUrl(self.apiEndpoints.getUserDetails + "/" + userId, null, true); - console.log(url); + //console.log("beginGetUserDetailsData"); + var url = self.createRequestUrl(self.apiEndpoints.getUserDetails + "/" + userId, null, false); $.getJSON(url, function (res) { - console.log("got user data"); - //console.log(res); + //console.log("got user data"); self.chosenUserDetails(res); - //console.log(self.chosenUserDetails()); }).fail(function () { console.log("error - getuserdetails"); + self.goToMenuOption(self.uiPages.home()); }); }; - self.handleEditedUser = function (user) { - console.log("Post Edited User: " + user.Id); - //var url = self.apiEndpoints.root + self.apiEndpoints.editUser; - var url = self.createRequestUrl(self.apiEndpoints.editUser, null, false); + self.submitChangedUser = function (user) { + //console.log("Post Edited User: " + user.UserId); var url = self.apiEndpoints.editUser; console.log("posting to.." + url); $.post(url, user, function () { - console.log("finished posting.."); }, "json") - //.done(function () { - // //self.goToMenuOption("users"); - // //self.chosenUserDetails(null); - // //self.goToMenuOption(self.menuOptions.home); - // }) - .fail(function (response) { - //due to unique way a 201 is a fail... - if (response.status === 201) { - self.goToMenuOption("users"); - self.chosenUserDetails(null); - } else { - console.log("error - post edited user"); - console.log(self.chosenUserDetails().UserId); - self.goToMenuOption(self.menuOptions.home); - } - }); + .done(function () { + self.goToMenuOption("users"); + self.chosenUserDetails(null); + }) + .fail(function (response) { + if (response.status === 201) { + self.goToMenuOption("users"); + self.chosenUserDetails(null); + } else { + console.log("error - post edited user"); + self.goToMenuOption(self.uiPages.home()); + } + }); }; self.getTimeLogData = function (userId, calendarWeek) { - console.log("begin get TimeLog Data"); + //console.log("begin get TimeLog Data"); var url = self.createRequestUrl(self.apiEndpoints.getTimeLogs, [{ key: "userId", value: userId }, { key: "calendarWeek", value: calendarWeek }], - true); + false); $.getJSON(url, function (res) { - console.log("got user timelog data"); - //console.log(res); + //console.log("got user timelog data"); self.userTimeLogData(res); - }).fail(function () { - console.log("error - getuserdetails"); - self.goToMenuOption(self.uiPages.home); //go home. + self.initDatePicker(); + self.assignHandler(); + }).fail(function (resp) { + if (resp.status === 200) { + self.userTimeLogData(resp.content); + //console.log(resp.content); + } else { + console.log("error - getuserdetails"); + self.goToMenuOption(self.uiPages.home()); //go home. + } }); }; self.getUnassignedCardData = function () { - console.log("begin get unassigned cards"); - var url = self.createRequestUrl(self.apiEndpoints.getUnassignedCards, null, true); + //console.log("begin get unassigned cards"); + var url = self.createRequestUrl(self.apiEndpoints.getUnassignedCards, null, false); $.getJSON(url, function (res) { - console.log("got unassigned card data"); //console.log(res); self.unassignedCardData(res); }).fail(function () { console.log("error - getuserdetails"); - //self.goToMenuOption(self.uiPages.home); //go home. // no, dont want to go home here, cos just means we dont have any details? }); }; Sammy(function () { this.get("#users", function () { - console.log(this.params.menuOption); + var query = this.params.query; + console.log(this.params.query); self.chosenMenuItemId("Users"); self.chosenUserDetails(null); self.userList(null); self.userTimeLogData(null); - self.getUserList(); + if (query) + self.searchUsers(query); + else + self.getUserList(); //$.get("http://localhost:3000", { menu: this.params.menu }, self.chosenMenuData); }); this.get("#userData/:userId", function () { - console.log("userData userId: " + this.params.userId); console.log("getting details for user: " + this.params.userId); self.chosenMenuItemId("Data"); //todo: change this! (replace with actual get timelogs call) self.userList(null); @@ -176,82 +225,57 @@ function DataVM() { }); this.get("#timelogs/:userId", function () { console.log("get user time logs, userID: " + this.params.userId); - self.chosenMenuItemId('Other'); + self.chosenMenuItemId("Other"); self.userList(null); self.chosenUserDetails(null); - //self.selectedCalendarWeek = 0; self.getTimeLogData(this.params.userId, self.selectedCalendarWeek()); - self.userTimeLogData({ "test": 0 }); - self.initDatePicker(); - //$( "#datepicker" ).datepicker(); }); this.get("#newUser", function () { console.log("creating new user"); - self.chosenMenuItemId('newUser'); + self.chosenMenuItemId("newUser"); self.userList(null); self.userTimeLogData(null); self.chosenUserDetails({ - "Id": -1, "UserId": -1, "FirstName": null, "LastName": null, "HoursPerWeek": null, - "AssociatedCards": null + "AssociatedIdentifiers": [], + "IsContractor": false }); self.getUnassignedCardData(); }); - this.get("#stats", function() { + this.get("#stats", function () { self.goToMenuOption("users"); }); - this.post("#edituser", function (context) { - $.each(self.chosenUserDetails().AssociatedCards, function (k, v) { - if (v.IsSelected !== true) { - console.log("removing.."); - self.chosenUserDetails().AssociatedCards.splice(k, 1); - console.log(v.CardUId); - } - }); + this.post("#edituser", function () { + $.each(self.chosenUserDetails().AssociatedIdentifiers, + function (k, v) { + if (v.IsAssociatedToUser !== true) { + console.log("removing.."); + self.chosenUserDetails().AssociatedIdentifiers.splice(k, 1); + console.log(v.UniqueId); + } + }); $.each(self.unassignedCardData().data, function (k, v) { - if (v.IsSelected == true) { - self.chosenUserDetails().AssociatedCards.push(v); - console.log(v.CardUId); + if (v.IsAssociatedToUser === true) { + self.chosenUserDetails().AssociatedIdentifiers.push(v); + console.log(v.UniqueId); } }); - console.log(self.chosenUserDetails()); - self.handleEditedUser(self.chosenUserDetails()); - //self.goToMenuOption(self.menuOptions.home); + //console.log(self.chosenUserDetails()); + self.submitChangedUser(self.chosenUserDetails()); return false; }); //default route (home page) this.get("", function () { this.app.runRoute("get", "#" + self.uiPages.users) }); }).run(); - self.initDatePicker = function () { - "use strict"; - //Initialize the datePicker(I have taken format as mm-dd-yyyy, you can - //have your owh) - $("#weeklyDatePicker").datepicker({ - weekStart: 1, - maxViewMode: 2, - endDate: "+0d", - todayBtn: true, - format: "yyyy-mm-dd", - todayHighlight: true, - calendarWeeks: true - }); - $("#weeklyDatePicker").on("changeDate", function (e) { - "use strict"; - console.log("in here2"); - var kk = e.date; - console.log(kk); - console.log( - "1: Iso Week Number: " + moment(kk).isoWeek() + " of " + - moment(kk).weeksInYear() - ); - console.log("before: " + self.selectedCalendarWeek()); - self.selectedCalendarWeek(moment(kk).isoWeek()); - console.log("after: " + self.selectedCalendarWeek()); - }); - //console.log("finished init"); - }; }; -ko.applyBindings(new DataVM()); \ No newline at end of file +ko.applyBindings(new DataVM()); + +$(document).on("mouseenter", ".datepicker-days tbody tr", function () { + $(this).addClass('highlight'); +}); +$(document).on("mouseleave", ".datepicker-days tbody tr", function () { + $(this).removeClass('highlight'); +}); \ No newline at end of file