From c6a2ed38b1114aab97211ad68f7a263f5b5fc7dc Mon Sep 17 00:00:00 2001 From: Jan Tuomi Date: Thu, 19 Jan 2017 01:43:12 +0200 Subject: [PATCH] Add search bar and filter options to member table In addition to new functionality, the styles of the page were refined. Resolves #19. Resolves #20. --- members/static/css/jasenlista.css | 46 +++++ members/static/html/jasenlista.html | 78 ++++--- members/static/js/members_controllers.js | 250 ++++++++++++++++------- 3 files changed, 272 insertions(+), 102 deletions(-) create mode 100644 members/static/css/jasenlista.css diff --git a/members/static/css/jasenlista.css b/members/static/css/jasenlista.css new file mode 100644 index 0000000..0b6068d --- /dev/null +++ b/members/static/css/jasenlista.css @@ -0,0 +1,46 @@ +#download-csv { + margin-left: 20px; +} + +.content-area { + padding-left: 15px; + padding-right: 15px; +} + +.content-area-title { + text-align: left; + float: left; +} + +.filter-field { + margin-left: 5px; + margin-right: 5px; +} + +.table-button { + margin-left: 5px; + margin-right: 5px; + margin-bottom: 5px; +} + +.table-button-column { + text-align: right; +} + +.filters { + text-align: right; + float: right; + margin-bottom: 5px; +} + +.first-filter { + margin-top: 20px; +} + +.last-filter { + margin-bottom: 30px; +} + +.inline-title { + display: inline; +} diff --git a/members/static/html/jasenlista.html b/members/static/html/jasenlista.html index 091ad93..b600d5d 100644 --- a/members/static/html/jasenlista.html +++ b/members/static/html/jasenlista.html @@ -1,17 +1,33 @@ +
-
-

Jäsenlista (jäseniä {{members.length}})

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

Jäsenlista (jäseniä: {{members.length}})

+ +
+
+
@@ -24,27 +40,23 @@ - - - - - - - - - - - - - - - + + + + + + + + + + + + +
SukunimiMaksanut
{{ x.last_name }}{{ x.first_name }}{{ x.email }}{{ x.AYY }}{{ x.jas }}{{ x.POR }}{{ x.created }}{{ x.paid }} - - - Muokkaa - - -
{{ x.last_name }}{{ x.first_name }}{{ x.email }}{{ x.AYY }}{{ x.jas }}{{ x.POR }}{{ x.created }}{{ x.paid }} + + Muokkaa + +
diff --git a/members/static/js/members_controllers.js b/members/static/js/members_controllers.js index 46c5a82..d1cd262 100644 --- a/members/static/js/members_controllers.js +++ b/members/static/js/members_controllers.js @@ -16,12 +16,12 @@ var notySuccess = notyfication('success',2500); function editor(returnpath){ return function($scope, $http, $route, $routeParams, $window, $location) { $scope.member = {"id": $routeParams.id}; - $http.get("/members/api/member/"+$scope.member.id).then(function(response){ + $http.get("/members/api/member/" + $scope.member.id).then(function(response) { $scope.member = response.data; }); $scope.send = function() { - $http.put("/members/api/member/"+$scope.member.id, $scope.member).then(function(data){ + $http.put("/members/api/member/" + $scope.member.id, $scope.member).then( function(data){ notySuccess("Jäsentiedot tallennettu"); $location.path(returnpath); }); @@ -31,101 +31,213 @@ function editor(returnpath){ } } } -app.directive('ngConfirmClick', -[ -function() -{ return { - link: function (scope, element, attr) - { +app.directive('ngConfirmClick', [ function() { return { + link: function (scope, element, attr) { var clickAction = attr.confirmedClick; - element.bind('click',function (event) - { - noty({ + element.bind('click',function (event) { + noty( { text: 'Oletko aivan varma? T. Lasse Lehtinen', layout: 'bottomRight', - buttons: [ - { - addClass: 'btn btn-danger', text: 'Kyllä', onClick: function($noty) { - // this = button element - // $noty = $noty element - $noty.close(); - scope.$eval(clickAction) - } - }, - { - addClass: 'btn btn-primary', text: 'Ei', onClick: function($noty) { - $noty.close(); - } - } - ] - }); + buttons: [ { + addClass: 'btn btn-danger', text: 'Kyllä', onClick: function($noty) { + // this = button element + // $noty = $noty element + $noty.close(); + scope.$eval(clickAction) + } + }, + { + addClass: 'btn btn-primary', text: 'Ei', onClick: function($noty) { + $noty.close(); + } + } ] + } ); }); } }}]); // controllers -app.controller("getController", function($scope, $http, $window, $location){ +app.controller("getController", function($scope, $document, $http, $window, $location){ + /* List of all members that are fetched from the database */ $scope.members = []; - $scope.getFunction = function() { - $http.get("/members/api/members").then(function(response){ - $scope.members = response.data; - // map trues and falses to more user-friendly format - _.each($scope.members, function(m){ - m.jas = m.jas ? "Kyllä" : "Ei"; - m.AYY = m.AYY ? "Kyllä" : "Ei"; - }); - $scope.shown_members = $scope.members; - }); - }; - $scope.getFunction(); - $scope.updatePayment= function(id){ - $http.put("/members/api/member/"+id,{paid:moment().format("YYYY-MM-DD kk:mm:ss") }).then(function(resp){ - $scope.getFunction(); + + /* Fetch all members from the database and show all members in the table */ + $scope.updateMembers = function() { + $http.get("/members/api/members").then(function(response){ + $scope.members = response.data; + // map trues and falses to more user-friendly format + _.each($scope.members, function(m){ + m.jas = m.jas ? "Kyllä" : "Ei"; + m.AYY = m.AYY ? "Kyllä" : "Ei"; + }); + $scope.shown_members = $scope.members; }); }; + + /* Fetch a single member from the database by id and update its row */ + $scope.updateMember = function(id) { + $http.get("/members/api/member/" + id).then(function(response) { + for (var i = 0; i < $scope.shown_members.length; i++) { + var member = $scope.shown_members[i]; + if (String(member.id) == String(id)) { + member = response.data; + member.jas = member.jas ? "Kyllä" : "Ei"; + member.AYY = member.AYY ? "Kyllä" : "Ei"; + + $scope.shown_members[i] = member; + } + } + }); + }; + + /* Update the payment date of a single member to the current time and send + * the member to the database */ + $scope.updatePayment= function(id){ + $http.put("/members/api/member/"+id, { paid: moment().format("YYYY-MM-DD kk:mm:ss") }).then(function(resp) { + $scope.updateMember(id); + + notySuccess("Maksupäivämäärä päivitetty."); + }); + }; + + /* Redirect the browser to the CSV dump download endpoint */ $scope.loadCSV = function() { window.location = "/members/api/getCSV"; }; - $scope.delete_member = function(id) { + + /* Delete a single member by id */ + $scope.deleteMember = function(id) { $http.delete("/members/api/member/" + id).then( function(response) { notySuccess("Poistaminen onnistui") - $scope.getFunction(); + $scope.updateMembers(); }, function(response) { notyError("Epäonnistui. Yritä uudelleen."); - $scope.getFunction(); + $scope.updateMembers(); } ); }; - $scope.datePicker = null; - $scope.filter_by_date = function() { - if ($scope.datePicker == null) - { - $scope.shown_members = $scope.members; - } - else - { - $scope.shown_members = []; - for (var i = 0; i < $scope.members.length; i++) - { - if (moment($scope.members[i].paid) < $scope.datePicker) - { - $scope.shown_members.push($scope.members[i]); + /* Filter in only those members whose 'created' field comes + * before the specified date */ + $scope.filterByAddedBeforeDate = function(members) { + if ($scope.addedBeforeDatePicker == null) { + return members; } - } - } - }; - $scope.clear_filter = function() { - $scope.datePicker = null; - $scope.getFunction(); + + var result = []; + for (var i = 0; i < members.length; i++) { + if (moment(members[i].created) <= $scope.addedBeforeDatePicker) { + result.push(members[i]); + } + } + return result; + }; + + /* Filter in only those members whose 'created' field comes + * after the specified date */ + $scope.filterByAddedAfterDate = function(members) { + if ($scope.addedAfterDatePicker == null) { + return members; + } + + var result = []; + for (var i = 0; i < members.length; i++) { + if (moment(members[i].created) > $scope.addedAfterDatePicker) { + result.push(members[i]); + } + } + return result; + }; + + /* Filter in only those members whose 'paid' field comes + * before the specified date */ + $scope.filterByPaidBeforeDate = function(members) { + if ($scope.paidBeforeDatePicker == null) { + return members; + } + + var result = []; + for (var i = 0; i < members.length; i++) { + if (moment(members[i].paid) <= $scope.paidBeforeDatePicker) { + result.push(members[i]); + } + } + return result; + }; + + /* Filter in only those members whose 'paid' field comes + * after the specified date */ + $scope.filterByPaidAfterDate = function(members) { + if ($scope.paidAfterDatePicker == null) { + return members; + } + + var result = []; + for (var i = 0; i < members.length; i++) { + if (moment(members[i].paid) > $scope.paidAfterDatePicker) { + result.push(members[i]); + } + } + return result; + }; + + /* Do a lazy search on the first name, last name and email fields + * If at least one of the aforementioned fields contains any of the search terms + * the search will be positive */ + $scope.filterBySearch = function(members) { + if ($scope.searchFilter == null) { + return members; + } + + var filterSearch = $scope.searchFilter.trim(); + if (filterSearch.length == 0) { + return members; + } + + var names = filterSearch.split(" "); + var result = []; + for (var i = 0; i < members.length; i++) { + var member = members[i]; + for (var j = 0; j < names.length; j++) { + var name = names[j].trim(); + if (name.length == 0) continue; + + if (member.first_name.includes(name) || member.last_name.includes(name) || member.email.includes(name)) { + result.push(member); + break; + } + } + } + return result; + } + + /* Run all filters on the members list */ + $scope.doFilter = function() { + var result = $scope.members; + result = $scope.filterByAddedBeforeDate(result); + result = $scope.filterByAddedAfterDate(result); + result = $scope.filterByPaidBeforeDate(result); + result = $scope.filterByPaidAfterDate(result); + result = $scope.filterBySearch(result); + + $scope.shown_members = result; + } + + /* Clear all filter fields and reset the table view */ + $scope.clearFilter = function() { + $scope.paidBeforeDatePicker = null; + $scope.paidAfterDatePicker = null; + $scope.addedBeforeDatePicker = null; + $scope.addedAfterDatePicker = null; + $scope.searchFilter = null; + $scope.updateMembers(); }; - $scope.$watch('datePicker', function(newValue, oldValue) { - $scope.filter_by_date(); - }); + /* Start by resetting the whole thing */ + $scope.clearFilter(); }); app.controller("postController", function($scope, $http, $location) {