From d27db1a12476bfb3096fcd873f27fa53640935b0 Mon Sep 17 00:00:00 2001 From: Daniel Karlsson Date: Wed, 18 Feb 2015 08:51:16 +0100 Subject: [PATCH 1/3] [#1118] Removed old commented code The commented code was moved to the general scripts.js earlier. --- .../static/rsr/v3/js/src/project_directory.js | 78 ------------------- 1 file changed, 78 deletions(-) diff --git a/akvo/rsr/static/rsr/v3/js/src/project_directory.js b/akvo/rsr/static/rsr/v3/js/src/project_directory.js index 48dc48920e..a4338bdc9c 100644 --- a/akvo/rsr/static/rsr/v3/js/src/project_directory.js +++ b/akvo/rsr/static/rsr/v3/js/src/project_directory.js @@ -121,82 +121,4 @@ $(document).ready(function(){ insertParam('sort_by', $(event.target).attr('param')); })); - // var googleMap = { - // canvas: document.getElementById('haj'), - // options: { - // mapTypeId: google.maps.MapTypeId.ROADMAP, - // streetViewControl: false, - // scrollwheel: false - // }, - // load: function() { - // var map = new google.maps.Map(this.canvas, this.options); - // var bounds = new google.maps.LatLngBounds(); - // } - // }; - // googleMap.load(); - - - - - // $('.akvo_map').each(function() { - // var mapId = $(this).attr('id'); - // var domNode = document.getElementById("haj"); - // // var mapObj = window[mapId]; - - // var googleMap = { - // // canvas: document.getElementById($(this).attr('id')), - // // mapObj: window[mapId], - // mapObj: window[mapId], - - // options: { - // mapTypeId: google.maps.MapTypeId.ROADMAP, - // streetViewControl: false, - // scrollwheel: false - // }, - // // locations: this.mapObj["locations"], - // // locations: this.mapObj["locations"], - // load: function() { - // // console.log(this.mapObj); - // // console.log(this.domNode); - // var map = new google.maps.Map(document.getElementById("haj"), - // this.options); - // //var bounds = new google.maps.LatLngBounds(); - // // $.each(this.mapObj["locations"], function(index, value) { - // // console.log(value); - // // var position = new google.maps.LatLng(value['latitude'], value['longitude']); - // // var marker = new google.maps.Marker({ - // // icon: 'haj.png', - // // position: position, - // // map: map - // // }); - - // // // bounds.extend(marker.position); - - // // // console.log(value); - - // // // var position = new google.maps.LatLng(this.locations[i][0], this.locations[i][1]); - // // // var marker = new google.maps.Marker({ - // // // icon: '{{ marker_icon }}', - // // // position: position, - // // // map: map - // // // }); - // // // map.fitBounds(bounds); - // // // map.panToBounds(bounds); - - // // }); - // } - // }; - // googleMap.load(); - - // // window.onload = function (){googleMap.load()}; - - // // var map_data = window[$(this).attr('id')]; - // // console.log(map_data); - - // // $.each($(this).attr('id') , function(index, value) { - // // alert(value); - // // }); - // // alert($(this).attr('id')); - // }); - }); From 68af39c1484ce93ca73f9edaede12818c192d6f2 Mon Sep 17 00:00:00 2001 From: Daniel Karlsson Date: Wed, 18 Feb 2015 10:44:07 +0100 Subject: [PATCH 2/3] [#1118] Inital work for chache invalidation --- .../static/rsr/v3/js/src/project_directory.js | 10 ++++++---- akvo/rsr/views/project.py | 1 + akvo/templates/project_directory.html | 16 +++++++++++++--- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/akvo/rsr/static/rsr/v3/js/src/project_directory.js b/akvo/rsr/static/rsr/v3/js/src/project_directory.js index a4338bdc9c..569b31c236 100644 --- a/akvo/rsr/static/rsr/v3/js/src/project_directory.js +++ b/akvo/rsr/static/rsr/v3/js/src/project_directory.js @@ -19,7 +19,7 @@ function insertParam(key, value) } -$(document).ready(function(){ +$(document).ready(function() { // Submit filter form on select change $('#filter select').change(function() { @@ -38,6 +38,8 @@ $(document).ready(function(){ queryTokenizer: Bloodhound.tokenizers.whitespace, prefetch: { url: '/rest/v1/project/?format=json&limit=10000', + cacheKey: 'akvoRsrProjects', + thumbprint: AKVO_RSR.typeahead.thumbs.numberOfProjects, filter: function(response) { f = [ 'id', @@ -54,11 +56,11 @@ $(document).ready(function(){ } }); - var focus_areas = new Bloodhound({ + var sectors = new Bloodhound({ datumTokenizer: Bloodhound.tokenizers.obj.whitespace('name'), queryTokenizer: Bloodhound.tokenizers.whitespace, prefetch: { - url: '/rest/v1/focus_area/?format=json&limit=1000', + url: '/rest/v1/sector/?format=json&limit=1000', filter: function(response) { f = [ 'id', @@ -71,7 +73,7 @@ $(document).ready(function(){ }); projects.initialize(); - focus_areas.initialize(); + sectors.initialize(); $('#id_title').typeahead( { diff --git a/akvo/rsr/views/project.py b/akvo/rsr/views/project.py index 94a0e5964b..9ffde0f7d4 100644 --- a/akvo/rsr/views/project.py +++ b/akvo/rsr/views/project.py @@ -176,6 +176,7 @@ def directory(request): page, paginator, page_range = pagination(page, sorted_projects, 10) context = { + 'project_count': sorted_projects.count(), 'filter': f, 'page': page, 'page_range': page_range, diff --git a/akvo/templates/project_directory.html b/akvo/templates/project_directory.html index fc26ee386d..d13ece06b2 100644 --- a/akvo/templates/project_directory.html +++ b/akvo/templates/project_directory.html @@ -40,12 +40,12 @@
{% bootstrap_field filter.form.status %}
- +
{% bootstrap_field filter.form.organisation %}
-
+
{% bootstrap_field filter.form.sector %} @@ -65,7 +65,7 @@
-

Viewing {{ page.start_index }} - {{ page.end_index }} of {{ paginator.count }} projects

+

Viewing {{ page.start_index }} - {{ page.end_index }} of {{ paginator.count }} projects

{% include 'navigation/pagination.html' %} @@ -132,6 +132,16 @@

{% trans "Finance" %}

{% block js %} {{ block.super }} + + + {% compressed_js 'rsr_v3_project_directory' %} {% endblock js %} From 90366e5e64cd2de1ef21ed280472a2e88db94e55 Mon Sep 17 00:00:00 2001 From: Daniel Karlsson Date: Thu, 19 Feb 2015 09:07:52 +0100 Subject: [PATCH 3/3] [#1118 #1119] Typeaheads updated - New resources for typeaheads that are public for non authenticated users. - Added simple cache invalidation (based on count() on Objects). --- akvo/rest/serializers/__init__.py | 38 ++++-- akvo/rest/serializers/typeahead.py | 72 ++++++++++++ akvo/rest/urls.py | 64 ++++++++-- akvo/rest/views/__init__.py | 20 +++- akvo/rest/views/typeahead.py | 80 +++++++++++++ akvo/rsr/static/rsr/v3/js/src/my-details.js | 52 ++++---- .../rsr/v3/js/src/organisation_directory.js | 22 ++-- .../static/rsr/v3/js/src/project_directory.js | 111 ++++++++++++------ .../static/rsr/v3/js/src/react-my-details.js | 4 +- .../static/rsr/v3/js/src/update_directory.js | 31 ++--- akvo/rsr/views/my_rsr.py | 6 + akvo/rsr/views/organisation.py | 1 + akvo/rsr/views/project.py | 4 + akvo/rsr/views/project_update.py | 1 + akvo/templates/myrsr/my_details.html | 11 ++ akvo/templates/organisation_directory.html | 12 +- akvo/templates/project_directory.html | 1 + akvo/templates/update_directory.html | 16 ++- 18 files changed, 414 insertions(+), 132 deletions(-) create mode 100644 akvo/rest/serializers/typeahead.py create mode 100644 akvo/rest/views/typeahead.py diff --git a/akvo/rest/serializers/__init__.py b/akvo/rest/serializers/__init__.py index 4f8da47bc4..4599d66a5d 100644 --- a/akvo/rest/serializers/__init__.py +++ b/akvo/rest/serializers/__init__.py @@ -1,8 +1,11 @@ # -*- coding: utf-8 -*- -# Akvo RSR is covered by the GNU Affero General Public License. -# See more details in the license.txt file located at the root folder of the Akvo RSR module. -# For additional details on the GNU license please see < http://www.gnu.org/licenses/agpl.html >. +"""Akvo RSR is covered by the GNU Affero General Public License. +See more details in the license.txt file located at the root folder of the +Akvo RSR module. For additional details on the GNU license please +see < http://www.gnu.org/licenses/agpl.html >. +""" + from .benchmark import BenchmarkSerializer from .benchmark_name import BenchmarknameSerializer @@ -32,7 +35,8 @@ from .project_contact import ProjectContactSerializer from .project_document import ProjectDocumentSerializer from .project_location import ProjectLocationSerializer -from .project_update import ProjectUpdateSerializer, ProjectUpdateExtraSerializer +from .project_update import (ProjectUpdateSerializer, + ProjectUpdateExtraSerializer) from .project_update_location import ProjectUpdateLocationSerializer from .publishing_status import PublishingStatusSerializer from .recipient_country import RecipientCountrySerializer @@ -41,14 +45,17 @@ from .result import ResultSerializer from .sector import SectorSerializer from .transaction import TransactionSerializer +from .typeahead import (TypeaheadCountrySerializer, + TypeaheadOrganisationSerializer, + TypeaheadProjectSerializer, + TypeaheadProjectUpdateSerializer) from .user import UserSerializer, UserDetailsSerializer, UserPasswordSerializer -from .project import ProjectSerializer, ProjectExtraSerializer __all__ = [ 'BenchmarkSerializer', 'BenchmarknameSerializer', - 'BudgetItemSerializer', 'BudgetItemLabelSerializer', + 'BudgetItemSerializer', 'CategorySerializer', 'CountrySerializer', 'EmploymentSerializer', @@ -61,23 +68,25 @@ 'KeywordSerializer', 'LegacyDataSerializer', 'LinkSerializer', - 'OrganisationSerializer', 'OrganisationLocationSerializer', + 'OrganisationSerializer', 'PartnerSiteSerializer', 'PartnerTypeSerializer', 'PartnershipSerializer', 'PlannedDisbursementSerializer', 'PolicyMarkerSerializer', - 'ProjectSerializer', - 'ProjectExtraSerializer', 'ProjectCommentSerializer', 'ProjectConditionSerializer', 'ProjectContactSerializer', 'ProjectDocumentSerializer', + 'ProjectExtraSerializer', + 'ProjectExtraSerializer', 'ProjectLocationSerializer', - 'ProjectUpdateSerializer', + 'ProjectSerializer', + 'ProjectSerializer', 'ProjectUpdateExtraSerializer', 'ProjectUpdateLocationSerializer', + 'ProjectUpdateSerializer', 'PublishingStatusSerializer', 'RecipientCountrySerializer', 'RecipientRegionSerializer', @@ -85,9 +94,12 @@ 'ResultSerializer', 'SectorSerializer', 'TransactionSerializer', - 'UserSerializer', + 'TypeaheadCountrySerializer', + 'TypeaheadOrganisationSerializer', + 'TypeaheadProjectSerializer', + 'TypeaheadProjectUpdateSerializer', + # 'TypeaheadSectorSerializer', 'UserDetailsSerializer', 'UserPasswordSerializer', - 'ProjectSerializer', - 'ProjectExtraSerializer', + 'UserSerializer', ] diff --git a/akvo/rest/serializers/typeahead.py b/akvo/rest/serializers/typeahead.py new file mode 100644 index 0000000000..befb5cba54 --- /dev/null +++ b/akvo/rest/serializers/typeahead.py @@ -0,0 +1,72 @@ +# -*- coding: utf-8 -*- + +"""Akvo RSR is covered by the GNU Affero General Public License. +See more details in the license.txt file located at the root folder of the +Akvo RSR module. For additional details on the GNU license please +see < http://www.gnu.org/licenses/agpl.html >. +""" + +from rest_framework import serializers +# from akvo.codelists.models import SectorCategory +from akvo.rsr.models import Country, Organisation, Project, ProjectUpdate + + +class TypeaheadCountrySerializer(serializers.ModelSerializer): + + class Meta: + model = Country + fields = ( + 'id', + 'name', + 'iso_code', + 'continent_code', + ) + + +class TypeaheadOrganisationSerializer(serializers.ModelSerializer): + + class Meta: + model = Organisation + fields = ( + 'id', + 'name', + 'long_name', + ) + + +class TypeaheadProjectSerializer(serializers.ModelSerializer): + + class Meta: + model = Project + fields = ( + 'id', + 'project_plan_summary', + 'subtitle', + 'title', + ) + + +class TypeaheadProjectUpdateSerializer(serializers.ModelSerializer): + + class Meta: + model = ProjectUpdate + fields = ( + 'id', + 'project', + 'title' + ) + +# class TypeaheadSectorSerializer(serializers.ModelSerializer): + +# class Meta: +# model = Project +# depth = 1 +# fields = ( +# 'id', +# 'sectors', +# ) +# # fields = ( +# # 'id', +# # # 'categories', +# # 'name', +# # ) diff --git a/akvo/rest/urls.py b/akvo/rest/urls.py index caa80389db..8c7484bdcf 100644 --- a/akvo/rest/urls.py +++ b/akvo/rest/urls.py @@ -1,13 +1,15 @@ # -*- coding: utf-8 -*- -# Akvo RSR is covered by the GNU Affero General Public License. -# See more details in the license.txt file located at the root folder of the Akvo RSR module. -# For additional details on the GNU license please see < http://www.gnu.org/licenses/agpl.html >. +"""Akvo RSR is covered by the GNU Affero General Public License. +See more details in the license.txt file located at the root folder of the +Akvo RSR module. For additional details on the GNU license please +see < http://www.gnu.org/licenses/agpl.html >. +""" +import views from django.conf.urls import patterns, url, include from rest_framework import routers -import views router = routers.DefaultRouter() @@ -22,7 +24,8 @@ router.register(r'goal', views.GoalViewSet) router.register(r'indicator', views.IndicatorViewSet) router.register(r'indicator_period', views.IndicatorPeriodViewSet) -router.register(r'internal_organisation_id', views.InternalOrganisationIDViewSet) +router.register(r'internal_organisation_id', + views.InternalOrganisationIDViewSet) router.register(r'invoice', views.InvoiceViewSet) router.register(r'keyword', views.KeywordViewSet) router.register(r'legacy_data', views.LegacyDataViewSet) @@ -35,14 +38,17 @@ router.register(r'planned_disbursement', views.PlannedDisbursementViewSet) router.register(r'policy_marker', views.PolicyMarkerViewSet) router.register(r'project', views.ProjectViewSet) -router.register(r'project_extra', views.ProjectExtraViewSet, base_name='project_extra') +router.register(r'project_extra', views.ProjectExtraViewSet, + base_name='project_extra') router.register(r'project_comment', views.ProjectCommentViewSet) router.register(r'project_condition', views.ProjectConditionViewSet) router.register(r'project_contact', views.ProjectContactViewSet) router.register(r'project_document', views.ProjectDocumentViewSet) router.register(r'project_location', views.ProjectLocationViewSet) -router.register(r'project_update_extra', views.ProjectUpdateExtraViewSet, base_name='project_update_extra') -router.register(r'project_update', views.ProjectUpdateViewSet, base_name='project_update') +router.register(r'project_update_extra', views.ProjectUpdateExtraViewSet, + base_name='project_update_extra') +router.register(r'project_update', views.ProjectUpdateViewSet, + base_name='project_update') router.register(r'project_update_location', views.ProjectUpdateLocationViewSet) router.register(r'publishing_status', views.PublishingStatusViewSet) router.register(r'recipient_country', views.RecipientCountryViewSet) @@ -55,12 +61,44 @@ # Wire up our API using automatic URL routing. # Additionally, we include URLs for non-viewsets (functional views). + urlpatterns = patterns( '', url(r'^', include(router.urls)), - url(r'^employment/(?P[0-9]+)/approve/$', views.approve_employment, name='approve_employment'), - url(r'^employment/(?P[0-9]+)/set_group/(?P[0-9]+)/$', views.set_group, name='set_group'), - url(r'^user/(?P[0-9]+)/change_password/$', views.change_password, name='user_change_password'), - url(r'^user/(?P[0-9]+)/update_details/$', views.update_details, name='user_update_details'), - url(r'^user/(?P[0-9]+)/request_organisation/$', views.request_organisation, name='user_request_organisation'), + url(r'^employment/(?P[0-9]+)/approve/$', + views.approve_employment, + name='approve_employment'), + url(r'^employment/(?P[0-9]+)/set_group/(?P[0-9]+)/$', + views.set_group, + name='set_group'), + url(r'^user/(?P[0-9]+)/change_password/$', + views.change_password, + name='user_change_password'), + url(r'^user/(?P[0-9]+)/update_details/$', + views.update_details, + name='user_update_details'), + url(r'^user/(?P[0-9]+)/request_organisation/$', + views.request_organisation, + name='user_request_organisation'), +) + +# Typeahead +urlpatterns += patterns( + '', + url(r'typeaheads/countries$', + views.typeahead_country, + name='country_typeahead'), + url(r'typeaheads/organisations$', + views.typeahead_organisation, + name='organisation_typeahead'), + url(r'typeaheads/projects$', + views.typeahead_project, + name='project_typeahead'), + url(r'typeaheads/project_updates$', + views.typeahead_projectupdate, + name='projectupdate_typeahead'), + + # url(r'typeaheads/sectors$', + # views.typeahead_sector, + # name='sector_typeahead'), ) diff --git a/akvo/rest/views/__init__.py b/akvo/rest/views/__init__.py index b439ad98a6..dcf249854f 100644 --- a/akvo/rest/views/__init__.py +++ b/akvo/rest/views/__init__.py @@ -1,8 +1,10 @@ # -*- coding: utf-8 -*- -# Akvo RSR is covered by the GNU Affero General Public License. -# See more details in the license.txt file located at the root folder of the Akvo RSR module. -# For additional details on the GNU license please see < http://www.gnu.org/licenses/agpl.html >. +"""Akvo RSR is covered by the GNU Affero General Public License. +See more details in the license.txt file located at the root folder of the +Akvo RSR module. For additional details on the GNU license please +see < http://www.gnu.org/licenses/agpl.html >. +""" from .benchmark import BenchmarkViewSet @@ -42,7 +44,12 @@ from .result import ResultViewSet from .sector import SectorViewSet from .transaction import TransactionViewSet -from .user import UserViewSet, change_password, update_details, request_organisation +from .typeahead import (typeahead_country, + typeahead_organisation, + typeahead_project, + typeahead_projectupdate) +from .user import (UserViewSet, change_password, update_details, + request_organisation) __all__ = [ 'BenchmarkViewSet', @@ -87,6 +94,11 @@ 'ResultViewSet', 'SectorViewSet', 'TransactionViewSet', + 'typeahead_country,', + 'typeahead_project', + 'typeahead_projectupdate', + 'typeahead_organisation', + # 'typeahead_sector', 'UserViewSet', 'change_password', 'update_details', diff --git a/akvo/rest/views/typeahead.py b/akvo/rest/views/typeahead.py new file mode 100644 index 0000000000..d578d00888 --- /dev/null +++ b/akvo/rest/views/typeahead.py @@ -0,0 +1,80 @@ +# -*- coding: utf-8 -*- + +"""Akvo RSR is covered by the GNU Affero General Public License. +See more details in the license.txt file located at the root folder of the +Akvo RSR module. For additional details on the GNU license please +see < http://www.gnu.org/licenses/agpl.html >. +""" + +from rest_framework.decorators import api_view +from rest_framework.response import Response + +from akvo.rest.serializers import (TypeaheadCountrySerializer, + TypeaheadOrganisationSerializer, + TypeaheadProjectSerializer, + TypeaheadProjectUpdateSerializer) +# from akvo.codelists.models import SectorCategory +from akvo.rsr.models import Country, Organisation, Project, ProjectUpdate + + +def rejig(queryset, serializer): + """Rearrange & add queryset count to the response data.""" + return { + 'count': queryset.count(), + 'results': serializer.data + } + + +@api_view(['GET']) +def typeahead_country(request): + countries = Country.objects.all() + return Response( + rejig(countries, TypeaheadCountrySerializer(countries, many=True)) + ) + + +@api_view(['GET']) +def typeahead_organisation(request): + organisations = Organisation.objects.all() + return Response( + rejig(organisations, TypeaheadOrganisationSerializer(organisations, + many=True)) + ) + + +@api_view(['GET']) +def typeahead_project(request): + projects = Project.objects.published() + return Response( + rejig(projects, TypeaheadProjectSerializer(projects, many=True)) + ) + + +@api_view(['GET']) +def typeahead_projectupdate(request): + updates = ProjectUpdate.objects.all() + return Response( + rejig(updates, TypeaheadProjectUpdateSerializer(updates, many=True)) + ) + + +# @api_view(['GET']) +# def typeahead_sector(request): +# """ +# """ + +# sectors = Sector.objects.all() + +# return Response( +# rejig(sectors, TypeaheadSectorSerializer(sectors, many=True)) +# ) + + +# @api_view(['GET']) +# def typeahead_sector(request): +# """ +# """ +# sectors = SectorCategory.objects.all() +# return Response( +# rejig(sectors, TypeaheadSectorSerializer(sectors, many=True)) +# ) diff --git a/akvo/rsr/static/rsr/v3/js/src/my-details.js b/akvo/rsr/static/rsr/v3/js/src/my-details.js index 23f7cf5c71..a4fab82c3a 100644 --- a/akvo/rsr/static/rsr/v3/js/src/my-details.js +++ b/akvo/rsr/static/rsr/v3/js/src/my-details.js @@ -3,34 +3,38 @@ // Akvo RSR module. For additional details on the GNU license please see // < http://www.gnu.org/licenses/agpl.html >. -// Typeahead for organisation and country input -var organisations = new Bloodhound({ - datumTokenizer: Bloodhound.tokenizers.obj.whitespace('long_name'), - queryTokenizer: Bloodhound.tokenizers.whitespace, - prefetch: { - url: '/rest/v1/organisation/?format=json&limit=3000', - filter: function(response) { - return response.results; - } - } -}); +// Jquery dependent code +$(function() { -var countries = new Bloodhound({ - datumTokenizer: Bloodhound.tokenizers.obj.whitespace('name'), - queryTokenizer: Bloodhound.tokenizers.whitespace, - prefetch: { - url: '/rest/v1/country/?format=json&limit=150', - filter: function(response) { - return response.results; + // Typeahead + var organisations = new Bloodhound({ + datumTokenizer: Bloodhound.tokenizers.obj.whitespace('long_name', + 'name'), + queryTokenizer: Bloodhound.tokenizers.whitespace, + prefetch: { + url: '/rest/v1/typeaheads/organisations?format=json', + thumbprint: AKVO_RSR.typeahead.thumbs.numberOfOrganisations, + filter: function(response) { + return response.results; + } } - } -}); + }); -organisations.initialize(); -countries.initialize(); + var countries = new Bloodhound({ + datumTokenizer: Bloodhound.tokenizers.obj.whitespace('long_name', + 'name'), + queryTokenizer: Bloodhound.tokenizers.whitespace, + prefetch: { + url: '/rest/v1/typeaheads/countries?format=json', + thumbprint: AKVO_RSR.typeahead.thumbs.numberOfCountries, + filter: function(response) { + return response.results; + } + } + }); -// Jquery dependent code -$(function() { + organisations.initialize(); + countries.initialize(); // When an avatar image is selected $("#id_avatar").change(function () { diff --git a/akvo/rsr/static/rsr/v3/js/src/organisation_directory.js b/akvo/rsr/static/rsr/v3/js/src/organisation_directory.js index d3ad0ce2e5..61acaeb114 100644 --- a/akvo/rsr/static/rsr/v3/js/src/organisation_directory.js +++ b/akvo/rsr/static/rsr/v3/js/src/organisation_directory.js @@ -5,22 +5,15 @@ $(document).ready(function(){ $('#filterForm').submit(); }); - // setup Bloodhound for typeahead var organisations = new Bloodhound({ - datumTokenizer: Bloodhound.tokenizers.obj.whitespace('description', - 'long_name', - 'name'), + datumTokenizer: Bloodhound.tokenizers.obj.whitespace('name', + 'long_name'), queryTokenizer: Bloodhound.tokenizers.whitespace, prefetch: { - url: '/rest/v1/organisation/?format=json&limit=10000', + url: '/rest/v1/typeaheads/organisations?format=json', + thumbprint: AKVO_RSR.typeahead.thumbs.numberOfOrgs, filter: function(response) { - f = [ - 'id', - 'description', - 'long_name', - 'name' - ]; - return _.map(response.results, _.partialRight(_.pick, f)); + return response.results; } } }); @@ -39,7 +32,8 @@ $(document).ready(function(){ header: '

Organisations

', suggestion: _.template('

<%= name %>!

') } - }); - + } + ) + ; }); diff --git a/akvo/rsr/static/rsr/v3/js/src/project_directory.js b/akvo/rsr/static/rsr/v3/js/src/project_directory.js index 569b31c236..546e33f510 100644 --- a/akvo/rsr/static/rsr/v3/js/src/project_directory.js +++ b/akvo/rsr/static/rsr/v3/js/src/project_directory.js @@ -1,3 +1,8 @@ +// Akvo RSR is covered by the GNU Affero General Public License. +// See more details in the license.txt file located at the root folder of the +// Akvo RSR module. For additional details on the GNU license please see +// < http://www.gnu.org/licenses/agpl.html >. + function insertParam(key, value) { key = encodeURI(key); value = encodeURI(value); @@ -27,6 +32,19 @@ $(document).ready(function() { }); // setup Bloodhound for typeahead + var organisations = new Bloodhound({ + datumTokenizer: Bloodhound.tokenizers.obj.whitespace('name', + 'long_name'), + queryTokenizer: Bloodhound.tokenizers.whitespace, + prefetch: { + url: '/rest/v1/typeaheads/organisations?format=json', + thumbprint: AKVO_RSR.typeahead.thumbs.numberOfOrgs, + filter: function(response) { + return response.results; + } + } + }); + var projects = new Bloodhound({ datumTokenizer: Bloodhound.tokenizers.obj.whitespace('background', 'current_image_credit', @@ -37,48 +55,64 @@ $(document).ready(function() { 'title'), queryTokenizer: Bloodhound.tokenizers.whitespace, prefetch: { - url: '/rest/v1/project/?format=json&limit=10000', - cacheKey: 'akvoRsrProjects', + url: '/rest/v1/typeaheads/projects?format=json', thumbprint: AKVO_RSR.typeahead.thumbs.numberOfProjects, - filter: function(response) { - f = [ - 'id', - 'background', - 'current_image_credit', - 'current_status', - 'project_plan', - 'project_plan_summary', - 'subtitle', - 'title' - ]; - return _.map(response.results, _.partialRight(_.pick, f)); - } - } - }); - var sectors = new Bloodhound({ - datumTokenizer: Bloodhound.tokenizers.obj.whitespace('name'), - queryTokenizer: Bloodhound.tokenizers.whitespace, - prefetch: { - url: '/rest/v1/sector/?format=json&limit=1000', filter: function(response) { - f = [ - 'id', - 'name', - 'slug' - ]; - return _.map(response.results, _.partialRight(_.pick, f)); + return response.results; } + + // Do we need to filter client side to? + // filter: function(response) { + // f = [ // Match fields in resource + // 'id', + // 'project_plan_summary', + // 'subtitle', + // 'title' + // ]; + // return _.map(response.results, _.partialRight(_.pick, f)); + // } } }); + // var sectors = new Bloodhound({ + // datumTokenizer: Bloodhound.tokenizers.obj.whitespace('name'), + // queryTokenizer: Bloodhound.tokenizers.whitespace, + // prefetch: { + // url: '/rest/v1/typeaheads/sectors?format=json', + // thumbprint: AKVO_RSR.typeahead.thumbs.numberOfSectors, + // filter: function(response) { + // return response.results; + // } + + // // filter: function(response) { + // // f = [ + // // 'id', + // // 'name', + // // 'slug' + // // ]; + // // return _.map(response.results, _.partialRight(_.pick, f)); + // // } + // } + // }); + + organisations.initialize(); projects.initialize(); - sectors.initialize(); + // sectors.initialize(); $('#id_title').typeahead( { highlight: true }, + { + name: 'organisations', + displayKey: 'name', + source: organisations.ttAdapter(), + templates: { + header: '

Organisations

', + suggestion: _.template('

<%= name %>!

') + } + }, { name: 'projects', displayKey: 'title', @@ -87,16 +121,17 @@ $(document).ready(function() { header: '

Projects

', suggestion: _.template('

<%= title %>!

<%= subtitle %>

') } - }, - { - name: 'focus_areas', - displayKey: 'name', - source: focus_areas.ttAdapter(), - templates: { - header: '

Filter on focus area

', - suggestion: _.template('<%= name %>') - } } + // , + // { + // name: 'sectors', + // displayKey: 'name', + // source: sectors.ttAdapter(), + // templates: { + // header: '

Sectors

', + // suggestion: _.template('

<%= name %>!

') + // } + // } ); $('#filterForm').on('click', '.filter_focus_area', function (event) { diff --git a/akvo/rsr/static/rsr/v3/js/src/react-my-details.js b/akvo/rsr/static/rsr/v3/js/src/react-my-details.js index c260bf4b89..b8171b1e5d 100644 --- a/akvo/rsr/static/rsr/v3/js/src/react-my-details.js +++ b/akvo/rsr/static/rsr/v3/js/src/react-my-details.js @@ -193,9 +193,9 @@ var AddEmploymentForm = React.createClass({displayName: 'AddEmploymentForm', render: function() { return ( - React.DOM.span(null, + React.DOM.span(null, React.DOM.h4(null, "Connect with your employer"), - React.DOM.form(null, + React.DOM.form(null, OrganisationInput( {ref:"organisationInput"} ), CountryInput( {ref:"countryInput"} ), JobTitleInput( {ref:"jobtitleInput"} ), diff --git a/akvo/rsr/static/rsr/v3/js/src/update_directory.js b/akvo/rsr/static/rsr/v3/js/src/update_directory.js index 6948a32495..abc4ff3f8b 100644 --- a/akvo/rsr/static/rsr/v3/js/src/update_directory.js +++ b/akvo/rsr/static/rsr/v3/js/src/update_directory.js @@ -1,3 +1,9 @@ +// Akvo RSR is covered by the GNU Affero General Public License. +// See more details in the license.txt file located at the root folder of the +// Akvo RSR module. For additional details on the GNU license please see +// < http://www.gnu.org/licenses/agpl.html >. + + $(document).ready(function(){ // Submit filter form on select change @@ -5,29 +11,17 @@ $(document).ready(function(){ $('#filterForm').submit(); }); - // setup Bloodhound for typeahead + // setup Bloodhound for typeahead var updates = new Bloodhound({ - datumTokenizer: Bloodhound.tokenizers.obj.whitespace('text', - 'notes', - 'photo_caption', - 'title', - 'video_caption' - ), + datumTokenizer: Bloodhound.tokenizers.obj.whitespace('title'), queryTokenizer: Bloodhound.tokenizers.whitespace, prefetch: { - url: '/rest/v1/project_update/?format=json&limit=10000', + url: '/rest/v1/typeaheads/project_updates?format=json', + thumbprint: AKVO_RSR.typeahead.thumbs.numberOfUpdates, filter: function(response) { - f = [ - 'id', - 'notes', - 'photo_caption', - 'project', - 'text', - 'title', - 'video_caption' - ]; - return _.map(response.results, _.partialRight(_.pick, f)); + return response.results; } + } }); @@ -47,5 +41,4 @@ $(document).ready(function(){ } }); - }); diff --git a/akvo/rsr/views/my_rsr.py b/akvo/rsr/views/my_rsr.py index d3fa3ef5cb..6aaa4b85eb 100644 --- a/akvo/rsr/views/my_rsr.py +++ b/akvo/rsr/views/my_rsr.py @@ -10,6 +10,7 @@ from ..forms import PasswordForm, ProfileForm, UserOrganisationForm, UserAvatarForm from ...utils import pagination +from ..models import Country, Organisation from django.contrib.auth.decorators import login_required from django.core.exceptions import PermissionDenied @@ -40,7 +41,12 @@ def my_details(request): json_data = json.dumps({'user': request.user.employments_dict([])}) + organisation_count = Organisation.objects.all().count() + country_count = Country.objects.all().count() + context = { + 'organisation_count': organisation_count, + 'country_count': country_count, 'user_data': json_data, 'profileform': profile_form, 'organisationform': organisation_form, diff --git a/akvo/rsr/views/organisation.py b/akvo/rsr/views/organisation.py index 488426bb28..3e575c8d25 100644 --- a/akvo/rsr/views/organisation.py +++ b/akvo/rsr/views/organisation.py @@ -27,6 +27,7 @@ def directory(request): page, paginator, page_range = pagination(page, f.qs.distinct(), 10) context = { + 'orgs_count': f.qs.distinct().count(), 'filter': f, 'page': page, 'paginator': paginator, diff --git a/akvo/rsr/views/project.py b/akvo/rsr/views/project.py index 9ffde0f7d4..2872858c1e 100644 --- a/akvo/rsr/views/project.py +++ b/akvo/rsr/views/project.py @@ -12,6 +12,7 @@ from ..filters import remove_empty_querydict_items, ProjectFilter from ..models import Invoice, Project, ProjectUpdate from ...utils import pagination, filter_query_string +from akvo.codelists.models import SectorCategory from django.contrib.auth.decorators import login_required from django.core.exceptions import PermissionDenied @@ -175,8 +176,11 @@ def directory(request): page = request.GET.get('page') page, paginator, page_range = pagination(page, sorted_projects, 10) + # sector_count = SectorCategory.objects.all().count() + context = { 'project_count': sorted_projects.count(), + # 'sector_count': sector_count, 'filter': f, 'page': page, 'page_range': page_range, diff --git a/akvo/rsr/views/project_update.py b/akvo/rsr/views/project_update.py index d48fd87e0d..371a5d558c 100644 --- a/akvo/rsr/views/project_update.py +++ b/akvo/rsr/views/project_update.py @@ -25,6 +25,7 @@ def directory(request): page, paginator, page_range = pagination(page, f.qs.distinct(), 10) context = { + 'updates_count': f.qs.distinct().count(), 'filter': f, 'page': page, 'page_range': page_range, diff --git a/akvo/templates/myrsr/my_details.html b/akvo/templates/myrsr/my_details.html index 5c91d7066e..8f2e3e0ecb 100644 --- a/akvo/templates/myrsr/my_details.html +++ b/akvo/templates/myrsr/my_details.html @@ -45,6 +45,17 @@

My details

{% block js %} {{ block.super }} + + + {# App data #} + + {% compressed_js 'rsr_v3_organisation_directory' %} {% endblock js %} @@ -122,4 +131,3 @@

{% trans "Social Media" %}

$("a.showFilters > i").toggleClass("fa-toggle-off fa-toggle-on"); }); {% endblock %} - diff --git a/akvo/templates/project_directory.html b/akvo/templates/project_directory.html index d13ece06b2..5bb6fd8e72 100644 --- a/akvo/templates/project_directory.html +++ b/akvo/templates/project_directory.html @@ -135,6 +135,7 @@

{% trans "Finance" %}

+ + + {% compressed_js 'rsr_v3_update_directory' %} {% endblock js %}