From ab0b9d321f847ed953a24a64c65d89601e262f39 Mon Sep 17 00:00:00 2001 From: "Eduardo L. Buratti" <elb09@c3sl.ufpr.br> Date: Thu, 14 Nov 2013 14:07:21 -0200 Subject: [PATCH] web: Extend location filter in search ("outros..." option) Signed-off-by: Eduardo L. Buratti <elb09@c3sl.ufpr.br> --- web/app/partials/search.filter.html | 36 +++++++++++++++ web/app/partials/search.html | 6 ++- web/assets/js/attendance.search.js | 68 ++++++++++++++++++++++++++++- web/assets/less/main.less | 27 ++++++++++++ web/queries/get_cities_by_state.sql | 5 +++ web/routes/cities.js | 10 +++++ web/routes/states.js | 31 +++++++++++++ web/server.js | 6 +++ 8 files changed, 186 insertions(+), 3 deletions(-) create mode 100644 web/app/partials/search.filter.html create mode 100644 web/queries/get_cities_by_state.sql create mode 100644 web/routes/cities.js create mode 100644 web/routes/states.js diff --git a/web/app/partials/search.filter.html b/web/app/partials/search.filter.html new file mode 100644 index 0000000..a8ba741 --- /dev/null +++ b/web/app/partials/search.filter.html @@ -0,0 +1,36 @@ +<div class="modal-backdrop fade in"></div> +<div class="modal"> + <div class="modal-dialog"> + <div class="modal-content"> + <form role="form" ng-submit="more.submit()"> + <div class="modal-header"> + <h4 class="modal-title">Mais opções...</h4> + </div> + <div class="modal-body"> + <div class="well well-scrolled"> + <div class="tree-item" ng-repeat="item in more.items" > + <div class="tree-item-title" ng-click="more.expand(item)"> + <small><i class="glyphicon" ng-class="{'glyphicon-plus': !item.expanded, 'glyphicon-minus': item.expanded}"></i></small> + {{ item.title }} + </div> + <ul class="tree-item-subitems"> + <li ng-repeat="subitem in item.subitems" ng-show="item.expanded"> + <div class="checkbox"> + <label> + <input type="checkbox" ng-click="more.select(subitem)"> + {{ subitem.title }} + </label> + </div> + </li> + </ul> + </div> + </div> + </div> + <div class="modal-footer"> + <button class="btn btn-default" ng-click="more.cancel()">Cancelar</button> + <button type="submit" class="btn btn-primary">Adicionar</button> + </div> + </form> + </div> + </div> +</div> \ No newline at end of file diff --git a/web/app/partials/search.html b/web/app/partials/search.html index 504e326..f3ca24a 100644 --- a/web/app/partials/search.html +++ b/web/app/partials/search.html @@ -1,3 +1,5 @@ +<div ng-include="more.includeUrl"></div> + <div class="container"> <div class="search-filters well"> <ul ng-repeat="filter in filters"> @@ -5,7 +7,7 @@ <li class="checkbox" ng-repeat="opt in filter.options"> <label><input type="checkbox" ng-model="opt.value" ng-click="updateFilters(filter, opt)"> {{ opt.title }}</label> </li> - <li class="checkbox" ng-show="filter.more"><a href="">outros...</a></li> + <li class="checkbox" ng-show="filter.more"><a href="" ng-click="more.show()">outros...</a></li> </ul> <div class="clearfix"></div> @@ -32,7 +34,7 @@ <tr ng-repeat="point in points"> <td><a href="">{{ point.name }}</a></td> <td>{{ point.location }}</a></td> - <td>{{ point.project }} </a></td> + <td>{{ point.project }}</a></td> </tr> </tbody> </table> diff --git a/web/assets/js/attendance.search.js b/web/assets/js/attendance.search.js index d88470f..3fa4744 100644 --- a/web/assets/js/attendance.search.js +++ b/web/assets/js/attendance.search.js @@ -66,7 +66,15 @@ angular.module('datasid.attendance.search', []). }); }). - controller('SearchCtrl', function ($scope, $rootScope, PointsFactory) { + factory('CityFactory', function($resource) { + return $resource('/api/cities/:state'); + }). + + factory('StateFactory', function($resource) { + return $resource('/api/states'); + }). + + controller('SearchCtrl', function ($scope, $rootScope, PointsFactory, CityFactory, StateFactory) { $scope.points = []; $scope.sorting = 'name'; @@ -160,6 +168,64 @@ angular.module('datasid.attendance.search', []). }); }; + $scope.more = { + includeUrl: '', + items: [ ], + selectedItems: [], + show: function () { + this.includeUrl = 'partials/search.filter.html'; + + StateFactory.query(function (states) { + angular.forEach(states, function (state) { + $scope.more.items.push({ + key: state.key, + title: state.title, + expanded: false, + subitems: [] + }); + }); + }); + }, + cancel: function () { + this.includeUrl = ''; + $scope.more.items = []; + }, + submit: function () { + for (var i=0; i < this.selectedItems.length; i++) + $scope.filters[1].options.push(this.selectedItems[i]); + + $scope.updateFilters(); + + this.includeUrl = ''; + $scope.more.items = []; + }, + expand: function (item) { + if (item.expanded) { + item.expanded = false; + return; + } + + if (item.subitems.length == 0) + item.subitems = CityFactory.query({state: item.key}); + + item.expanded = true; + }, + select: function (item) { + item.value = !(item.value || false); + + if (item.value) + this.selectedItems.push(item); + else { + for (var i=0; i < this.selectedItems.length; i++) { + if (this.selectedItems[i] == item) { + this.selectedItems.splice(i, 1); + break; + } + } + } + } + }; + $scope.updateFilters = function (filterIn, optionIn) { $scope.compiledFilters = {}; diff --git a/web/assets/less/main.less b/web/assets/less/main.less index 100593d..4a22f76 100644 --- a/web/assets/less/main.less +++ b/web/assets/less/main.less @@ -149,6 +149,7 @@ p.note { .modal { display: block; + overflow: hidden; } .saving { @@ -158,4 +159,30 @@ p.note { margin: 0px -4px -3px 4px; background-image: url("../img/saving.gif"); background-repeat: no-repeat; +} + +.tree-item { + border-bottom: 1px solid #e5e5e5; + + .tree-item-title { + padding: 6px 2px; + cursor: pointer; + font-size: 1.2em; + } + + .tree-item-subitems { + list-style: none; + padding-left: 12px; + + .checkbox { + margin-top: 3px; + margin-bottom: 3px; + } + } +} + +.well-scrolled { + height: 300px; + overflow-x: auto; + padding-top: 6px; } \ No newline at end of file diff --git a/web/queries/get_cities_by_state.sql b/web/queries/get_cities_by_state.sql new file mode 100644 index 0000000..ba6220e --- /dev/null +++ b/web/queries/get_cities_by_state.sql @@ -0,0 +1,5 @@ +SELECT + id AS key, + INITCAP(name) || ', ' || UPPER(state) AS title +FROM city +WHERE state = $1; \ No newline at end of file diff --git a/web/routes/cities.js b/web/routes/cities.js new file mode 100644 index 0000000..cd1d17f --- /dev/null +++ b/web/routes/cities.js @@ -0,0 +1,10 @@ +exports.list = function(req, res) { + var state = req.params.state; + + var query = __dirname + "/../queries/get_cities_by_state.sql"; + + req.db.queryFromFile(query, [state], function(result) { + req.db.done(); + res.json(result.rows); + }); +}; \ No newline at end of file diff --git a/web/routes/states.js b/web/routes/states.js new file mode 100644 index 0000000..8c7edfb --- /dev/null +++ b/web/routes/states.js @@ -0,0 +1,31 @@ +exports.list = function(req, res) { + res.json([ + { key: 'AC', title: 'Acre' }, + { key: 'AL', title: 'Alagoas' }, + { key: 'AP', title: 'Amapá' }, + { key: 'AM', title: 'Amazonas' }, + { key: 'BA', title: 'Bahia' }, + { key: 'CE', title: 'Ceará' }, + { key: 'DF', title: 'Distrito Federal' }, + { key: 'ES', title: 'EspÃrito Santo' }, + { key: 'GO', title: 'Goiás' }, + { key: 'MA', title: 'Maranhão' }, + { key: 'MT', title: 'Mato Grosso' }, + { key: 'MS', title: 'Mato Grosso do Sul' }, + { key: 'MG', title: 'Minas Gerais' }, + { key: 'PA', title: 'Pará' }, + { key: 'PB', title: 'ParaÃba' }, + { key: 'PR', title: 'Paraná' }, + { key: 'PE', title: 'Pernambuco' }, + { key: 'PI', title: 'PiauÃ' }, + { key: 'RJ', title: 'Rio de Janeiro' }, + { key: 'RN', title: 'Rio Grande do Norte' }, + { key: 'RS', title: 'Rio Grande do Sul' }, + { key: 'RO', title: 'Rondônia' }, + { key: 'RR', title: 'Roraima' }, + { key: 'SC', title: 'Santa Catarina' }, + { key: 'SP', title: 'São Paulo' }, + { key: 'SE', title: 'Sergipe' }, + { key: 'TO', title: 'Tocantins' } + ]); +}; \ No newline at end of file diff --git a/web/server.js b/web/server.js index 1beb80f..a85a697 100755 --- a/web/server.js +++ b/web/server.js @@ -6,6 +6,8 @@ var db = require('./middleware/db.js'); var SQLiteStore = require('connect-sqlite3')(express); var sessions = require('./routes/sessions.js'); +var cities = require('./routes/cities.js'); +var states = require('./routes/states.js'); var points = require('./routes/points.js'); var telecenters = require('./routes/telecenters.js'); var charts = require('./routes/charts.js'); @@ -29,6 +31,10 @@ app.post('/api/s', sessions.login); app.get('/api/s', sessions.get); app.delete('/api/s', sessions.logout); +app.get('/api/states', db.connect, states.list); + +app.get('/api/cities/:state', db.connect, cities.list); + app.all('/api/points', db.connect, points.list); app.all('/api/points/count', db.connect, points.count); -- GitLab