From 75446421b49b9d8e5fa3df923d7a8bbf36597b4c Mon Sep 17 00:00:00 2001 From: Alex Swindler Date: Fri, 17 Apr 2015 22:14:57 -0600 Subject: [PATCH 01/22] Fixing typos --- BE/settings/dev.py | 2 +- seed/static/seed/js/directives/beUploader.js | 6 +++--- seed/static/seed/js/filters/stripImportPrefix.js | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/BE/settings/dev.py b/BE/settings/dev.py index 3ceb6b2185..d7eef9a3a3 100644 --- a/BE/settings/dev.py +++ b/BE/settings/dev.py @@ -49,7 +49,7 @@ LOGGING = { 'version': 1, 'disable_existing_loggers': True, - # set up some log message handers to chose from + # set up some log message handlers to choose from 'handlers': { 'sentry': { 'level': 'ERROR', diff --git a/seed/static/seed/js/directives/beUploader.js b/seed/static/seed/js/directives/beUploader.js index 458669bf29..b3d99fda97 100644 --- a/seed/static/seed/js/directives/beUploader.js +++ b/seed/static/seed/js/directives/beUploader.js @@ -11,7 +11,7 @@ * `message` - string - options: "upload_submitted", * "upload_in_progress", "upload_complete", and "invalid_extension" * `filename` - string name of the file uploaded - * `progress` - JS object with keys `loaded` and `total` wehere + * `progress` - JS object with keys `loaded` and `total` where * `loaded` / `total` * 100.0 is the percent uploaded * importrecord - int or string - id of import record or dataset * @@ -111,7 +111,7 @@ var makeS3Uploader = function(scope, element, attrs, filename) { * onComplete: overloaded callback that calls the callback defined * in the element attribute unless the upload failed, which will * fire a window alert. Passes as arguments to the callback - * a message indicating upload has copmleted, "upload_complete", and + * a message indicating upload has completed, "upload_complete", and * the filename. */ onComplete: function(id, fileName, responseJSON) { @@ -242,7 +242,7 @@ var makeFileSystemUploader = function(scope, element, attrs, filename) { * onComplete: overloaded callback that calls the callback defined * in the element attribute unless the upload failed, which will * fire a window alert. Passes as arguments to the callback - * a message indicating upload has copmleted, "upload_complete", and + * a message indicating upload has completed, "upload_complete", and * the filename. */ onComplete: function(id, fileName, responseJSON) { diff --git a/seed/static/seed/js/filters/stripImportPrefix.js b/seed/static/seed/js/filters/stripImportPrefix.js index 32dbb2a52d..4f824a5b4d 100644 --- a/seed/static/seed/js/filters/stripImportPrefix.js +++ b/seed/static/seed/js/filters/stripImportPrefix.js @@ -10,11 +10,11 @@ angular.module('stripImportPrefix', []).filter('stripImportPrefix', [ function($filter) { /** ids are sometime prefixed by the Import Record id. * e.g. import 28 would prefix all assessor data ids with 'IMP28-' and - * stripImportPrefix would stip out the 'IMP28-'s from the html and only + * stripImportPrefix would strip out the 'IMP28-'s from the html and only * display the ids. * * Usage: building.id = "IMP12-007" - * HTML: {{ buidling.id | stripImportPrefix }} + * HTML: {{ building.id | stripImportPrefix }} * compiles to: 007 * JS : stripImportPrefix(building.id) * returns: "007" From 94bb4e9b5073dda37a8ab3692ebf3505e145e89e Mon Sep 17 00:00:00 2001 From: Alex Swindler Date: Fri, 17 Apr 2015 22:28:00 -0600 Subject: [PATCH 02/22] Initial upload improvements --- .../js/controllers/data_upload_modal_ctrl.js | 7 +- .../seed/js/services/uploader_service.js | 2 +- .../seed/partials/data_upload_modal.html | 20 ++++- seed/tasks.py | 76 ++++++++++++------- 4 files changed, 72 insertions(+), 33 deletions(-) diff --git a/seed/static/seed/js/controllers/data_upload_modal_ctrl.js b/seed/static/seed/js/controllers/data_upload_modal_ctrl.js index d9bac3ed74..4297efb272 100644 --- a/seed/static/seed/js/controllers/data_upload_modal_ctrl.js +++ b/seed/static/seed/js/controllers/data_upload_modal_ctrl.js @@ -18,6 +18,8 @@ * ng-switch-when="8" == Add files to your Data Set. * ng-switch-when="9" == Add files to {$ dataset.name $} * ng-switch-when="10" == No matches found + * ng-switch-when="11" == Confirm Save Mappings? + * ng-switch-when="12" == Error Processing Data */ angular.module('BE.seed.controller.data_upload_modal', []) .controller('data_upload_modal_ctrl', [ @@ -161,7 +163,6 @@ angular.module('BE.seed.controller.data_upload_modal', []) } if (event_message === "upload_complete") { var current_step = $scope.step.number; - var data_is_green_button = $scope.uploader.status_message = "upload complete"; $scope.dataset.import_file_id = file.file_id; @@ -272,6 +273,10 @@ angular.module('BE.seed.controller.data_upload_modal', []) } }, $scope.uploader); + }, function(data){ + $scope.step_12_error_message = data.message; + console.error($scope.step_12_error_message); + $scope.step.number = 12; }); }; diff --git a/seed/static/seed/js/services/uploader_service.js b/seed/static/seed/js/services/uploader_service.js index a08fa2bad3..1c52ba8441 100644 --- a/seed/static/seed/js/services/uploader_service.js +++ b/seed/static/seed/js/services/uploader_service.js @@ -136,7 +136,7 @@ angular.module('BE.seed.service.uploader', []).factory('uploader_service', [ }, 750); }, function (data, status) { // reject promise - console.log(data, status); + console.error(data, status); }); }; diff --git a/seed/static/seed/partials/data_upload_modal.html b/seed/static/seed/partials/data_upload_modal.html index 1632793a28..5cedd2477a 100644 --- a/seed/static/seed/partials/data_upload_modal.html +++ b/seed/static/seed/partials/data_upload_modal.html @@ -10,6 +10,7 @@ + diff --git a/seed/static/seed/partials/dataset_list.html b/seed/static/seed/partials/dataset_list.html index fb2a593a99..5bbad22f2e 100644 --- a/seed/static/seed/partials/dataset_list.html +++ b/seed/static/seed/partials/dataset_list.html @@ -59,10 +59,10 @@

{$ datasets.length | number:0 $} Data Sets

diff --git a/seed/static/seed/partials/matching_detail.html b/seed/static/seed/partials/matching_detail.html index d7162a9413..aec2f8880c 100644 --- a/seed/static/seed/partials/matching_detail.html +++ b/seed/static/seed/partials/matching_detail.html @@ -105,11 +105,11 @@

Matching ({$ import_file.file_name $})

diff --git a/seed/static/seed/partials/matching_detail_table.html b/seed/static/seed/partials/matching_detail_table.html index 771fb9602a..f7c8465340 100644 --- a/seed/static/seed/partials/matching_detail_table.html +++ b/seed/static/seed/partials/matching_detail_table.html @@ -67,11 +67,11 @@ diff --git a/seed/static/seed/partials/matching_list_table.html b/seed/static/seed/partials/matching_list_table.html index b13aa3cc56..9a09a69c74 100644 --- a/seed/static/seed/partials/matching_list_table.html +++ b/seed/static/seed/partials/matching_list_table.html @@ -130,11 +130,11 @@ From 3d4641da1cad6897ad06e4295ffe17b9c6a4beac Mon Sep 17 00:00:00 2001 From: Nicholas Serra Date: Wed, 22 Apr 2015 18:52:59 -0400 Subject: [PATCH 05/22] Exact and empty matching on search fields. --- seed/search.py | 26 ++++++--- seed/tests/test_views.py | 114 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 134 insertions(+), 6 deletions(-) diff --git a/seed/search.py b/seed/search.py index edd78eee5e..ed95383fd9 100644 --- a/seed/search.py +++ b/seed/search.py @@ -8,6 +8,7 @@ # python import operator import json +import re # django from django.db.models import Q @@ -187,21 +188,34 @@ def is_column(k, columns): else: return False - query_dict = {} + # Build query as Q objects so we can AND and OR. + query_filters = Q() for k, v in other_params.iteritems(): in_columns = is_column(k, db_columns) - if in_columns and k != 'q' and v is not None and v != '': - if ('__lt' in k or + if in_columns and k != 'q' and v is not None: + + # Is this query a string? + is_string_query = isinstance(v, basestring) + + # Is this query surrounded by matching quotes? + exact_match = re.match(r"""^(["'])(.+)\1$""", v) if is_string_query else False + empty_match = re.match(r"""^(["'])\1$""", v) if is_string_query else False + + if exact_match: + query_filters &= Q(**{"%s__exact" % k: exact_match.group(2)}) + elif empty_match: + query_filters &= Q(**{"%s__exact" % k: ''}) | Q(**{"%s__isnull" % k: True}) + elif ('__lt' in k or '__lte' in k or '__gt' in k or '__gte' in k or '__isnull' in k or k == 'import_file_id' or k == 'source_type'): - query_dict["%s" % k] = v + query_filters &= Q(**{"%s" % k: v}) else: - query_dict["%s__icontains" % k] = v + query_filters &= Q(**{"%s__icontains" % k: v}) - queryset = queryset.filter(**query_dict) + queryset = queryset.filter(query_filters) # handle extra_data with json_query for k, v in other_params.iteritems(): diff --git a/seed/tests/test_views.py b/seed/tests/test_views.py index 89c3093397..5b31ec366a 100644 --- a/seed/tests/test_views.py +++ b/seed/tests/test_views.py @@ -625,6 +625,120 @@ def test_search_filter_range(self): self.assertEqual(data['buildings'][1]['year_built'], 6) self.assertEqual(data['buildings'][2]['year_built'], 7) + def test_search_exact_match(self): + """ + Tests search_buidlings method when called with an exact match. + """ + + # Uppercase address + cb1 = CanonicalBuilding(active=True) + cb1.save() + b1 = SEEDFactory.building_snapshot( + canonical_building=cb1, + address_line_1="Address" + ) + cb1.canonical_snapshot = b1 + cb1.save() + b1.super_organization = self.org + b1.save() + + # Lowercase address + cb2 = CanonicalBuilding(active=True) + cb2.save() + b2 = SEEDFactory.building_snapshot( + canonical_building=cb2, + address_line_1="address" + ) + cb2.canonical_snapshot = b2 + cb2.save() + b2.super_organization = self.org + b2.save() + + url = reverse_lazy("seed:search_buildings") + post_data = { + 'filter_params': { + 'address_line_1': '"Address"' + }, + 'number_per_page': 10, + 'order_by': '', + 'page': 1, + 'q': '', + 'sort_reverse': False, + 'project_id': None, + } + + # act + response = self.client.post( + url, + content_type='application/json', + data=json.dumps(post_data) + ) + json_string = response.content + data = json.loads(json_string) + + # assert + self.assertEqual(data['status'], 'success') + self.assertEqual(data['number_matching_search'], 1) + self.assertEqual(len(data['buildings']), 1) + self.assertEqual(data['buildings'][0]['address_line_1'], 'Address') + + def test_search_empty_column(self): + """ + Tests search_buidlings method when called with an empty column query. + """ + + # Empty column + cb1 = CanonicalBuilding(active=True) + cb1.save() + b1 = SEEDFactory.building_snapshot( + canonical_building=cb1, + address_line_1="" + ) + cb1.canonical_snapshot = b1 + cb1.save() + b1.super_organization = self.org + b1.save() + + # Populated column + cb2 = CanonicalBuilding(active=True) + cb2.save() + b2 = SEEDFactory.building_snapshot( + canonical_building=cb2, + address_line_1="Address" + ) + cb2.canonical_snapshot = b2 + cb2.save() + b2.super_organization = self.org + b2.save() + + url = reverse_lazy("seed:search_buildings") + post_data = { + 'filter_params': { + 'address_line_1': '""' + }, + 'number_per_page': 10, + 'order_by': '', + 'page': 1, + 'q': '', + 'sort_reverse': False, + 'project_id': None, + } + + # act + response = self.client.post( + url, + content_type='application/json', + data=json.dumps(post_data) + ) + json_string = response.content + data = json.loads(json_string) + + # assert + self.assertEqual(data['status'], 'success') + self.assertEqual(data['number_matching_search'], 1) + self.assertEqual(len(data['buildings']), 1) + self.assertEqual(data['buildings'][0]['address_line_1'], '') + self.assertEqual(data['buildings'][0]['pk'], b1.pk) def test_apply_label_to_project_buildings(self): """ From 98a7a758aa5b4277daecea47de69e2b02023855f Mon Sep 17 00:00:00 2001 From: Nicholas Long Date: Fri, 24 Apr 2015 16:16:56 -0600 Subject: [PATCH 06/22] cleanup osx instructions --- README-osx.md | 60 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 39 insertions(+), 21 deletions(-) diff --git a/README-osx.md b/README-osx.md index 64cd1367cd..51ef1e0e30 100644 --- a/README-osx.md +++ b/README-osx.md @@ -4,18 +4,27 @@ These instructions are for installing and running SEED on Mac OSX in development ## Prerequisites -These instructions assume you have/use [Macports](https://www.macports.org/). +These instructions assume you have/use [Macports](https://www.macports.org/). The workflow has been testing with homebrew as well, but is not directly supported. You system should have the following dependencies already installed: -Although you _could_ install Python packages globally, the easiest way to install Python packages is with [virtualenv](https://virtualenv.pypa.io/en/latest/) and [virtualenvwrapper](https://virtualenvwrapper.readthedocs.org/en/latest/). Setting these up first will help avoid polluting your base Python installation and make it much easier to switch between different versions of the code. +* git (`port install git` or `brew install git`) +* Mercurial (`port install hg` or `brew install mercurial`) -Once you have these installed, creating and entering a new virtualenv called "``seed``" for SEED development is as easy as: +(Recommended) - mkvirtualenv --python=python2.7 seed - +* [virtualenv](https://virtualenv.pypa.io/en/latest/) and [virtualenvwrapper](https://virtualenvwrapper.readthedocs.org/en/latest/). + * Although you _could_ install Python packages globally, this is the easiest way to install Python packages. Setting these up first will help avoid polluting your base Python installation and make it much easier to switch between different versions of the code. + + pip install virtualenv + pip install virtualenvwrapper + + * Follow instructions on [virtualenvwrapper](https://virtualenvwrapper.readthedocs.org/en/latest/) to setup your environment. + * Once you have these installed, creating and entering a new virtualenv called "``seed``" for SEED development is as easy as: + + mkvirtualenv --python=python2.7 seed ## Install PostgreSQL 9.4 -Perform the following commands as 'root' +Perform the following commands as 'root' if using port sudo su - root @@ -25,7 +34,12 @@ Install Postgres 9.4 # init db mkdir -p /opt/local/var/db/postgresql94/defaultdb chown postgres:postgres /opt/local/var/db/postgresql94/defaultdb - + + # homebrew + brew install postgres + # follow the post install instructions to add to launchagents or call manually with `postgres -D /usr/local/var/postgres` + # Skip the remaining Postgres instructions + Finish initializing the DB sudo su postgres - c '/opt/local/lib/postgresql94/bin/initdb -D /opt/local/var/db/postgresql94/defaultdb' @@ -44,11 +58,10 @@ Start Postgres Switch to postgres user - sudo su - postgres - PATH=$PATH:/opt/local/lib/postgresql94/bin/ + sudo su - postgres + PATH=$PATH:/opt/local/lib/postgresql94/bin/ -Configure Postgresql. Replace 'seeddb', 'seeduser' with desired db/user. -seedpass +Configure PostgreSQL. Replace 'seeddb', 'seeduser' with desired db/user. By default use password `seedpass` when prompted createdb seeddb createuser -P seeduser @@ -60,13 +73,15 @@ Now exit any root environments, becoming just yourself (even though it's not tha Run these commands as your normal user id. -Change to a virtualenv (using virtualenvwrapper) or do the following as a superuser. A virtualenv is usually better for development. +Change to a virtualenv (using virtualenvwrapper) or do the following as a superuser. A virtualenv is usually better for development. Set the virtualenv to seed. -Make sure PostgreSQL command line scripts are in your PATH + workon seed + +Make sure PostgreSQL command line scripts are in your PATH (if using port) export PATH=$PATH:/opt/local/lib/postgresql94/bin - -Install requirements with `pip` + +Install requirements with `pip`. pip install -r requirements.txt @@ -80,13 +95,11 @@ Install library with `setup.py` First, install [npm](https://www.npmjs.com/) if you haven't already. You can do this by installing from [nodejs.org](http://nodejs.org/), or use Macports: + # port sudo port install npm -### Install libraries - -Then run, from the top-level, a script to install the JS libraries: - - ./bin/install_javascript_dependencies.sh + # homebrew + brew install npm ## Configure Django and its back-end DBs @@ -145,7 +158,7 @@ If you want to do any API testing (and of course you do!), you will need to add an API KEY for this user. You can do this in postgresql directly: - psql94 seeddb seeduser + psql seeddb seeduser seeddb=> update landing_seeduser set api_key='DEADBEEF' where id=1; The 'secret' key DEADBEEF is hard-coded into the test scripts. @@ -154,8 +167,13 @@ The 'secret' key DEADBEEF is hard-coded into the test scripts. You need to manually install Redis for Celery to work. + # port sudo port install redis + # homebrew + brew install redis + # follow the post install instructions to add to launchagents or call manually with `redis-server` + ### Install Javascript dependencies The JS dependencies are installed using node.js package management (npm), with From 11632c728595c0f087f278a88fea737d31c33b37 Mon Sep 17 00:00:00 2001 From: Alex Swindler Date: Wed, 29 Apr 2015 00:17:36 -0600 Subject: [PATCH 07/22] Adding error handling for specific failures --- .../js/controllers/data_upload_modal_ctrl.js | 4 ++- .../controllers/dataset_detail_controller.js | 2 +- .../seed/js/controllers/menu_controller.js | 2 +- .../seed/partials/data_upload_modal.html | 2 +- seed/static/seed/partials/dataset_detail.html | 6 ++-- seed/tasks.py | 30 ++++++++++++++----- 6 files changed, 31 insertions(+), 15 deletions(-) diff --git a/seed/static/seed/js/controllers/data_upload_modal_ctrl.js b/seed/static/seed/js/controllers/data_upload_modal_ctrl.js index 4297efb272..45ab734dd6 100644 --- a/seed/static/seed/js/controllers/data_upload_modal_ctrl.js +++ b/seed/static/seed/js/controllers/data_upload_modal_ctrl.js @@ -25,6 +25,7 @@ angular.module('BE.seed.controller.data_upload_modal', []) .controller('data_upload_modal_ctrl', [ '$scope', '$modalInstance', + '$log', 'step', 'dataset', '$timeout', @@ -36,6 +37,7 @@ angular.module('BE.seed.controller.data_upload_modal', []) function ( $scope, $modalInstance, + $log, step, dataset, $timeout, @@ -275,7 +277,7 @@ angular.module('BE.seed.controller.data_upload_modal', []) }, $scope.uploader); }, function(data){ $scope.step_12_error_message = data.message; - console.error($scope.step_12_error_message); + $log.error(data.stacktrace); $scope.step.number = 12; }); }; diff --git a/seed/static/seed/js/controllers/dataset_detail_controller.js b/seed/static/seed/js/controllers/dataset_detail_controller.js index 0fbee7d83d..3b339e1743 100644 --- a/seed/static/seed/js/controllers/dataset_detail_controller.js +++ b/seed/static/seed/js/controllers/dataset_detail_controller.js @@ -12,7 +12,7 @@ angular.module('BE.seed.controller.dataset_detail', []) function ($scope, dataset_payload, $log, dataset_service, $modal, urls) { $scope.dataset = dataset_payload.dataset; - $log.info({dataset_payload: dataset_payload}); + $log.info('dataset_payload:', dataset_payload); $scope.confirm_delete = function (file) { var yes = confirm("Are you sure you want to PERMANENTLY delete '" + file.name + "'?"); diff --git a/seed/static/seed/js/controllers/menu_controller.js b/seed/static/seed/js/controllers/menu_controller.js index 4032dd22fb..5836e6f77e 100644 --- a/seed/static/seed/js/controllers/menu_controller.js +++ b/seed/static/seed/js/controllers/menu_controller.js @@ -63,7 +63,7 @@ angular.module('BE.seed.controller.menu', []) }); $scope.$on("$routeChangeStart", function($event, next, current) { $scope.menu.loading = next.controller === "mapping_controller"; - }) + }); $scope.$on("$routeChangeSuccess", function() { $scope.menu.loading = false; $scope.menu.route_load_error = false; diff --git a/seed/static/seed/partials/data_upload_modal.html b/seed/static/seed/partials/data_upload_modal.html index 5cedd2477a..eb771dabeb 100644 --- a/seed/static/seed/partials/data_upload_modal.html +++ b/seed/static/seed/partials/data_upload_modal.html @@ -158,7 +158,7 @@

An error occurred while processing the file. Please ensure that your file meets the required specifications.

-
{$ step_12_error_message $}
+
{$ step_12_error_message $}
diff --git a/seed/static/seed/partials/dataset_detail.html b/seed/static/seed/partials/dataset_detail.html index f7c2d42cb1..fdcdc58483 100644 --- a/seed/static/seed/partials/dataset_detail.html +++ b/seed/static/seed/partials/dataset_detail.html @@ -33,9 +33,9 @@

{$ dataset.name $}

- {$ f.num_rows $} - {$ f.number_of_mappings $} Data Mapping - {$ f.number_of_matchings $} Data Matching + {$ f.num_rows || 0 $} + {$ f.number_of_mappings $} Data Mapping + {$ f.number_of_matchings $} Data Matching diff --git a/seed/tasks.py b/seed/tasks.py index 4f6bc240e7..7a86c84011 100644 --- a/seed/tasks.py +++ b/seed/tasks.py @@ -10,6 +10,8 @@ import os import traceback +from _csv import Error + from django.core.mail import send_mail from django.conf import settings from django.utils.http import urlsafe_base64_encode @@ -702,8 +704,7 @@ def _save_raw_green_button_data(file_pk, *args, **kwargs): @lock_and_track def _save_raw_data(file_pk, *args, **kwargs): """Chunk up the CSV and save data into the DB raw.""" - status = '' - error_msg = '' + status = error_msg = stacktrace = None try: import_file = ImportFile.objects.get(pk=file_pk) @@ -736,23 +737,36 @@ def _save_raw_data(file_pk, *args, **kwargs): status = 'success' except StopIteration: - error_msg = traceback.format_exc() + error_msg = 'StopIteration Exception' + stacktrace = traceback.format_exc() + status = 'error' + except Error as e: + error_msg = 'CSV Error: ' + e.message + stacktrace = traceback.format_exc() + logger.info(error_msg) + status = 'error' + except KeyError as e: + error_msg = 'Invalid Column Name: "' + e.message + '"' + stacktrace = traceback.format_exc() + logger.info(error_msg) + status = 'error' + except Exception as e: + error_msg = 'Unhandled Error: ' + e.message + stacktrace = traceback.format_exc() + logger.info(error_msg) status = 'error' if status == 'success': return {'status': status} else: - return {'status': status, 'message': error_msg} + return {'status': status, 'message': error_msg, 'stacktrace': stacktrace} @task @lock_and_track def save_raw_data(file_pk, *args, **kwargs): response = _save_raw_data.delay(file_pk, *args, **kwargs) - if response.result['status'] == 'success': - return {'status': response.result['status']} - else: - return {'status': response.result['status'], 'message': response.result['message']} + return response.result def _stringify(values): From c4c190a83cf555a2dde26e0270538224843f566e Mon Sep 17 00:00:00 2001 From: Nicholas Serra Date: Wed, 29 Apr 2015 13:00:58 -0400 Subject: [PATCH 08/22] Save building sort column and order in sessionStorage --- .../js/controllers/building_list_controller.js | 1 + seed/static/seed/js/seed.js | 10 +++++++++- seed/static/seed/js/services/search_service.js | 18 ++++++++++++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/seed/static/seed/js/controllers/building_list_controller.js b/seed/static/seed/js/controllers/building_list_controller.js index f9e2ef4e86..e30e33ecec 100644 --- a/seed/static/seed/js/controllers/building_list_controller.js +++ b/seed/static/seed/js/controllers/building_list_controller.js @@ -66,6 +66,7 @@ angular.module('BE.seed.controller.building_list', []) */ var get_columns = function() { $scope.assessor_fields = all_columns.fields; + $scope.search.init_storage(); $scope.columns = $scope.search.generate_columns( all_columns.fields, default_columns.columns, diff --git a/seed/static/seed/js/seed.js b/seed/static/seed/js/seed.js index d8399b288a..27e0c37b79 100644 --- a/seed/static/seed/js/seed.js +++ b/seed/static/seed/js/seed.js @@ -256,8 +256,16 @@ SEED_app.config(['$routeProvider', function ($routeProvider) { 'search_payload': ['building_services', '$route', function(building_services, $route){ var params = $route.current.params; var q = params.q || ""; + + // Check session storage for order and sort values. + var orderBy = (typeof(Storage) !== "undefined" && sessionStorage.getItem('seedBuildingOrderBy') !== null) ? + sessionStorage.getItem('seedBuildingOrderBy') : ""; + + var sortReverse = (typeof(Storage) !== "undefined" && sessionStorage.getItem('seedBuildingSortReverse') !== null) ? + JSON.parse(sessionStorage.getItem('seedBuildingSortReverse')) : false; + // params: (query, number_per_page, page_number, order_by, sort_reverse, other_params, project_id) - return building_services.search_buildings(q, 10, 1, "", false, params, null); + return building_services.search_buildings(q, 10, 1, orderBy, sortReverse, params, null); }], 'default_columns': ['user_service', function(user_service){ return user_service.get_default_columns(); diff --git a/seed/static/seed/js/services/search_service.js b/seed/static/seed/js/services/search_service.js index 8f1c56e15f..91f263b850 100644 --- a/seed/static/seed/js/services/search_service.js +++ b/seed/static/seed/js/services/search_service.js @@ -78,6 +78,18 @@ angular.module('BE.seed.service.search', []) * functions */ + search_service.init_storage = function () { + // Check session storage for order and sort values. + if (typeof(Storage) !== "undefined" && sessionStorage.getItem('seedBuildingOrderBy') !== null) { + saas.order_by = sessionStorage.getItem('seedBuildingOrderBy'); + saas.sort_column = sessionStorage.getItem('seedBuildingOrderBy'); + } + + if (typeof(Storage) !== "undefined" && sessionStorage.getItem('seedBuildingSortReverse') !== null) { + saas.sort_reverse = JSON.parse(sessionStorage.getItem('seedBuildingSortReverse')); + } + }; + /** * sanitize_params: removes filter params with null or undefined values */ @@ -306,6 +318,12 @@ angular.module('BE.seed.service.search', []) saas.sort_column = this.sort_column; } } + + if (typeof(Storage) !== "undefined") { + sessionStorage.setItem('seedBuildingOrderBy', saas.sort_column); + sessionStorage.setItem('seedBuildingSortReverse', saas.sort_reverse); + } + saas.order_by = this.sort_column; saas.current_page = 1; saas.search_buildings(); From dd29b2a7c6c46eff055e05df80cb4d0f2427cc62 Mon Sep 17 00:00:00 2001 From: Alex Swindler Date: Thu, 30 Apr 2015 09:52:59 -0600 Subject: [PATCH 09/22] Fixing mixed tabs and spaces --- seed/static/seed/css/mapping.css | 6 +- seed/static/seed/partials/about.html | 4 +- seed/static/seed/partials/accounts.html | 72 ++--- seed/static/seed/partials/add_project.html | 12 +- .../seed/partials/building_area_section.html | 6 +- .../seed/partials/building_audit_log.html | 16 +- .../partials/building_contacts_section.html | 6 +- .../partials/building_detail_section.html | 6 +- .../partials/building_energy_section.html | 6 +- .../partials/building_projects_section.html | 6 +- seed/static/seed/partials/buildings.html | 200 +++++++------- .../seed/partials/buildings_settings.html | 76 +++--- seed/static/seed/partials/concat_modal.html | 2 +- .../partials/create_organization_modal.html | 62 ++--- .../seed/partials/data_upload_modal.html | 252 +++++++++--------- seed/static/seed/partials/dataset_list.html | 94 +++---- .../seed/partials/existing_members_modal.html | 108 ++++---- seed/static/seed/partials/export_modal.html | 62 ++--- seed/static/seed/partials/feedback.html | 28 +- seed/static/seed/partials/home.html | 136 +++++----- seed/static/seed/partials/mapping.html | 4 +- seed/static/seed/partials/matching.html | 76 +++--- .../static/seed/partials/matching_detail.html | 64 ++--- .../seed/partials/matching_detail_table.html | 4 +- .../seed/partials/matching_list_table.html | 34 +-- seed/static/seed/partials/members.html | 18 +- .../seed/partials/new_member_modal.html | 72 ++--- .../seed/partials/new_project_modal.html | 12 +- seed/static/seed/partials/project_detail.html | 158 +++++------ .../seed/partials/project_settings.html | 62 ++--- seed/static/seed/partials/projects.html | 12 +- seed/static/seed/partials/settings.html | 42 +-- seed/static/seed/partials/sharing.html | 85 +++--- seed/static/seed/partials/sub_org.html | 6 +- seed/tests/test_matching.py | 12 +- 35 files changed, 911 insertions(+), 910 deletions(-) diff --git a/seed/static/seed/css/mapping.css b/seed/static/seed/css/mapping.css index c586218d56..7c41a9634f 100644 --- a/seed/static/seed/css/mapping.css +++ b/seed/static/seed/css/mapping.css @@ -7,9 +7,9 @@ margin: 10px; } .fa-arrows { - padding-right: 7px; - color: #444; - } + padding-right: 7px; + color: #444; +} .tree-handle { padding: 10px; background: #428bca; diff --git a/seed/static/seed/partials/about.html b/seed/static/seed/partials/about.html index 8687301246..b0aefb9d10 100644 --- a/seed/static/seed/partials/about.html +++ b/seed/static/seed/partials/about.html @@ -24,8 +24,8 @@

Development Team:

Funding from: U.S. Department of Energy

Software developer: Building Energy

-

Version

-

1.1.4

+

Version

+

1.1.4

diff --git a/seed/static/seed/partials/accounts.html b/seed/static/seed/partials/accounts.html index 0e37c1304e..ed82d56a97 100644 --- a/seed/static/seed/partials/accounts.html +++ b/seed/static/seed/partials/accounts.html @@ -12,29 +12,29 @@

Organizations

-
+

Pending Organization Invites

-
+
- + - - - - - - + + + + + +
-
+
@@ -44,32 +44,32 @@

Organizations I Manage

@@ -79,33 +79,33 @@

Organizations I Belong To

-
+
- + - - + + - - - + - - + +
Organization Name Number of Buildings Your Role Organization Owner(s)
+ {$ org.name $} {$ org.name $} {$ org.num_buildings $} {$ org.user_role || "-" $} + {$ org.user_role || "-" $} {$ owner.first_name $} {$ owner.last_name $}
-
+
diff --git a/seed/static/seed/partials/add_project.html b/seed/static/seed/partials/add_project.html index 966827856c..c7a366fe2a 100644 --- a/seed/static/seed/partials/add_project.html +++ b/seed/static/seed/partials/add_project.html @@ -13,12 +13,12 @@

Create a New Project

-
-
- - Sorry. The project name {$ project.name $} is already in use. -
-
+
+
+ + Sorry. The project name {$ project.name $} is already in use. +
+
diff --git a/seed/static/seed/partials/building_area_section.html b/seed/static/seed/partials/building_area_section.html index 9ca30a2b93..c636462c3f 100644 --- a/seed/static/seed/partials/building_area_section.html +++ b/seed/static/seed/partials/building_area_section.html @@ -2,14 +2,14 @@ diff --git a/seed/static/seed/partials/building_audit_log.html b/seed/static/seed/partials/building_audit_log.html index de20a356e1..20c5bbce19 100644 --- a/seed/static/seed/partials/building_audit_log.html +++ b/seed/static/seed/partials/building_audit_log.html @@ -2,14 +2,14 @@
-

Audit Log & Notes

+

Audit Log & Notes

@@ -25,12 +25,12 @@

Audit Log & Notes

- - {$ entry.user.first_name $} {$ entry.user.last_name $} + + {$ entry.user.first_name $} {$ entry.user.last_name $} {$ entry.action_note || entry.action $} - {$ entry.action_note $} edit - {$ entry.created | date:"MM/dd/yyyy 'at' h:mma" $} - + {$ entry.action_note $} edit + {$ entry.created | date:"MM/dd/yyyy 'at' h:mma" $} +
diff --git a/seed/static/seed/partials/building_contacts_section.html b/seed/static/seed/partials/building_contacts_section.html index bf42e23c71..586c0d6b34 100644 --- a/seed/static/seed/partials/building_contacts_section.html +++ b/seed/static/seed/partials/building_contacts_section.html @@ -2,14 +2,14 @@
-

Contact Information

+

Contact Information

diff --git a/seed/static/seed/partials/building_detail_section.html b/seed/static/seed/partials/building_detail_section.html index 3c3c16ae99..2ce0ebe388 100644 --- a/seed/static/seed/partials/building_detail_section.html +++ b/seed/static/seed/partials/building_detail_section.html @@ -2,14 +2,14 @@
-

Building Information

+

Building Information

diff --git a/seed/static/seed/partials/building_energy_section.html b/seed/static/seed/partials/building_energy_section.html index c78c3f877d..4e8933cf07 100644 --- a/seed/static/seed/partials/building_energy_section.html +++ b/seed/static/seed/partials/building_energy_section.html @@ -2,14 +2,14 @@
-

Energy Data

+

Energy Data

diff --git a/seed/static/seed/partials/building_projects_section.html b/seed/static/seed/partials/building_projects_section.html index eb4850219a..3c780f9b54 100644 --- a/seed/static/seed/partials/building_projects_section.html +++ b/seed/static/seed/partials/building_projects_section.html @@ -2,14 +2,14 @@
-

Projects That Include This Building

+

Projects That Include This Building

diff --git a/seed/static/seed/partials/buildings.html b/seed/static/seed/partials/buildings.html index 145df30255..98af3ef7e6 100644 --- a/seed/static/seed/partials/buildings.html +++ b/seed/static/seed/partials/buildings.html @@ -7,38 +7,38 @@

{$ search.number_matching_search | number:0 $} Buildings

- +
-
-
- - You successfully created the project {$ project.name $}. -
-
+
+
+ + You successfully created the project {$ project.name $}. +
+
-
- +
@@ -57,80 +57,80 @@

{$ search.number_matching_search | number:0

@@ -149,11 +149,11 @@
diff --git a/seed/static/seed/partials/buildings_settings.html b/seed/static/seed/partials/buildings_settings.html index 2972c3faca..162ed3a5bf 100644 --- a/seed/static/seed/partials/buildings_settings.html +++ b/seed/static/seed/partials/buildings_settings.html @@ -7,74 +7,74 @@

Buildings

- +
-
-

Building List Settings

-
-
- -
+
+

Building List Settings

+
+
+ +
-

Add Shared Buildings.

-
- -
-

There are {$ fields.length | number $} columns of data available to you.

+

Add Shared Buildings.

+
+ +
+

There are {$ fields.length | number $} columns of data available to you.

Select columns from the list below to make them appear in your Buildings List table.

-
-
+
+
- + - - + + - +
Column Name
- - + +
- - - - - - + + + + + +
- - - {$ field.title $} -
+ + + {$ field.title $} +
-
+
- +
diff --git a/seed/static/seed/partials/concat_modal.html b/seed/static/seed/partials/concat_modal.html index caaa52dd6e..30679d5bd1 100644 --- a/seed/static/seed/partials/concat_modal.html +++ b/seed/static/seed/partials/concat_modal.html @@ -45,7 +45,7 @@
Drag headers from your list on the left into the area below to combine them.
A preview of your concatenated data will appear in the box below.
- {$ c.raw_data[0] $} + {$ c.raw_data[0] $}
diff --git a/seed/static/seed/partials/create_organization_modal.html b/seed/static/seed/partials/create_organization_modal.html index 0bc525a79e..2e4f08cc6e 100644 --- a/seed/static/seed/partials/create_organization_modal.html +++ b/seed/static/seed/partials/create_organization_modal.html @@ -1,35 +1,35 @@
- - + +
diff --git a/seed/static/seed/partials/data_upload_modal.html b/seed/static/seed/partials/data_upload_modal.html index eb771dabeb..0500711e69 100644 --- a/seed/static/seed/partials/data_upload_modal.html +++ b/seed/static/seed/partials/data_upload_modal.html @@ -13,108 +13,108 @@ diff --git a/seed/static/seed/partials/mapping.html b/seed/static/seed/partials/mapping.html index a491756ab1..0fc03dca5c 100644 --- a/seed/static/seed/partials/mapping.html +++ b/seed/static/seed/partials/mapping.html @@ -184,8 +184,8 @@

Data Mapping & Validation ({$ import_file.name $})

- - + +
diff --git a/seed/static/seed/partials/matching.html b/seed/static/seed/partials/matching.html index 54258a7385..d7d4a7f95d 100644 --- a/seed/static/seed/partials/matching.html +++ b/seed/static/seed/partials/matching.html @@ -14,56 +14,56 @@

Data Matching ({$ import_file.dataset.name $})

{$ alert.msg $} -
- - -
-
-

HOW THE SYSTEM AUTO-MATCHES YOUR BUILDINGS:

-

Your source data file(s) are presented in the table on the left. All buildings where a possible data match exists are presented in a table on the right. The system attempts to auto-match building records using shared unique IDs like: PM Proprty ID, Tax Lot ID, and Custom IDs as well as Address information. Where the system believes a match exists between a record in your source file and an existing building record it will auto-check the 'match' checkbox — effectively making a match between these buildings. A confidence number (0 - 100%) is included to indicate the systems confidence that this match is correct.

-
-
-

FIELDS NEEDED TO MAKE BUILDING MATCHES:

-

The following is a list of the fields we use to match up buildings between different records. The more data you have in these four (4) fields the better our system will auto-match your buildings.

-

Tax Lot ID PM Property ID

-

Custom ID Address Line 1

-
-
-
- -
-
-

HOW TO MANUALLY MATCH YOUR BUILDINGS:

-

You can review and edit each individual match by clicking one of the linked IDs in the table. This will open a new table that shows the source data for the individual building record you are attempting to match. Underneath this building is a searchable list of all potential existing building matches. Use this table to explore all your building records and to select single or multiple building records to match you source data to.

-
-
-

VIEW/HIDE COLUMNS

-

You can customize the columns displayed in the table below by clicking the 'View/Hide Columns' button and then selecting the column headers you want to review from the modal window.

-
-
+
+ + +
+
+

HOW THE SYSTEM AUTO-MATCHES YOUR BUILDINGS:

+

Your source data file(s) are presented in the table on the left. All buildings where a possible data match exists are presented in a table on the right. The system attempts to auto-match building records using shared unique IDs like: PM Proprty ID, Tax Lot ID, and Custom IDs as well as Address information. Where the system believes a match exists between a record in your source file and an existing building record it will auto-check the 'match' checkbox — effectively making a match between these buildings. A confidence number (0 - 100%) is included to indicate the systems confidence that this match is correct.

+
+
+

FIELDS NEEDED TO MAKE BUILDING MATCHES:

+

The following is a list of the fields we use to match up buildings between different records. The more data you have in these four (4) fields the better our system will auto-match your buildings.

+

Tax Lot ID PM Property ID

+

Custom ID Address Line 1

+
+
+
+ +
+
+

HOW TO MANUALLY MATCH YOUR BUILDINGS:

+

You can review and edit each individual match by clicking one of the linked IDs in the table. This will open a new table that shows the source data for the individual building record you are attempting to match. Underneath this building is a searchable list of all potential existing building matches. Use this table to explore all your building records and to select single or multiple building records to match you source data to.

+
+
+

VIEW/HIDE COLUMNS

+

You can customize the columns displayed in the table below by clicking the 'View/Hide Columns' button and then selecting the column headers you want to review from the modal window.

+
+
-
- -
-
-
+ + + +
+
-
- -
+
+ +
- +
- + - + diff --git a/seed/static/seed/partials/matching_detail.html b/seed/static/seed/partials/matching_detail.html index aec2f8880c..d247539217 100644 --- a/seed/static/seed/partials/matching_detail.html +++ b/seed/static/seed/partials/matching_detail.html @@ -59,19 +59,19 @@

Matching ({$ import_file.file_name $})

- - - - - {$ building.property_id $} - {$ building.extra_data['Custom Property ID 1 - ID'] $} - {$ building.property_name $} - {$ building.address_line_1 $} - {$ building.year_built $} - {$ building.postal_code $} - {$ building.property_floor_area_bldg_park | number:0 $} - - + + + + + {$ building.property_id $} + {$ building.extra_data['Custom Property ID 1 - ID'] $} + {$ building.property_name $} + {$ building.address_line_1 $} + {$ building.year_built $} + {$ building.postal_code $} + {$ building.property_floor_area_bldg_park | number:0 $} + + @@ -92,27 +92,27 @@

Matching ({$ import_file.file_name $})

diff --git a/seed/static/seed/partials/matching_detail_table.html b/seed/static/seed/partials/matching_detail_table.html index f7c8465340..8e7f07a600 100644 --- a/seed/static/seed/partials/matching_detail_table.html +++ b/seed/static/seed/partials/matching_detail_table.html @@ -26,7 +26,7 @@ - Building from Source: {$ file_select.file.name $} Matched! Next unmatched building. + Building from Source: {$ file_select.file.name $} Matched! Next unmatched building. @@ -34,7 +34,7 @@ {$ building[c.sort_column] $} - Potential Matches from Source: Existing Buildings + Potential Matches from Source: Existing Buildings diff --git a/seed/static/seed/partials/matching_list_table.html b/seed/static/seed/partials/matching_list_table.html index 9a09a69c74..919b455830 100644 --- a/seed/static/seed/partials/matching_list_table.html +++ b/seed/static/seed/partials/matching_list_table.html @@ -6,23 +6,23 @@
-
-
- - -
-
+ +
+ + +
+
-
- - -
-
- +
+ + +
+
+
@@ -88,7 +88,7 @@ - {$ b.confidence * 100 | number:0 $}% + {$ b.confidence * 100 | number:0 $}% diff --git a/seed/static/seed/partials/members.html b/seed/static/seed/partials/members.html index 3a2455f352..dafc461f5d 100644 --- a/seed/static/seed/partials/members.html +++ b/seed/static/seed/partials/members.html @@ -1,7 +1,7 @@
+
- Remove + Remove diff --git a/seed/static/seed/partials/new_member_modal.html b/seed/static/seed/partials/new_member_modal.html index cdfefcd0fb..05678dd9d7 100644 --- a/seed/static/seed/partials/new_member_modal.html +++ b/seed/static/seed/partials/new_member_modal.html @@ -1,40 +1,40 @@
- - + +
diff --git a/seed/static/seed/partials/new_project_modal.html b/seed/static/seed/partials/new_project_modal.html index 043b148ab2..c69c40a6cc 100644 --- a/seed/static/seed/partials/new_project_modal.html +++ b/seed/static/seed/partials/new_project_modal.html @@ -19,16 +19,16 @@
-
- -
+
+ +