From 7b4d159fc2dade5d7921e64ad717cc5a354a96c0 Mon Sep 17 00:00:00 2001 From: Aashil Date: Wed, 14 Sep 2016 10:52:23 -0400 Subject: [PATCH 01/23] fix me later! PROD-278: Write test for fetching the results from Bing using it's API. --- .../src/app/search/search.component.spec.ts | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/default/src/app/search/search.component.spec.ts b/default/src/app/search/search.component.spec.ts index 7220fd6..c46cc92 100644 --- a/default/src/app/search/search.component.spec.ts +++ b/default/src/app/search/search.component.spec.ts @@ -106,4 +106,30 @@ describe('SearchComponent', () => { }) ); + + it('should get the Bing search data from the backend', + inject([SearchComponent, QueryService, AuthService], (component: SearchComponent, querySrv: MockQueryService, + auth: MockAuthService) => { + spyOn(querySrv, 'doQuery').and.callFake(() => { + return Observable.create( + (observer: Observer) => { + observer.next({ + 'success': 'true', + 'payload': { + 'redirect': 'http://google.com/q#=whatever', + }, + 'cursor': null + }); + observer.complete(); + } + ); + }); + + spyOn(component, 'getBingData'); + component.getBingData('search text'); + expect(component.data).toBe('whatever results bing api gives us'); + }) + + ); + }); From 5f7def4e7fb85c70f363625104db72aa1cadf2bd Mon Sep 17 00:00:00 2001 From: Aashil Date: Wed, 14 Sep 2016 10:57:10 -0400 Subject: [PATCH 02/23] fix me later! PROD-278: Write backend test to get the data from the bing. --- backend/tests/handlers_api_query_test.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/backend/tests/handlers_api_query_test.py b/backend/tests/handlers_api_query_test.py index 34777e3..3fc6b82 100644 --- a/backend/tests/handlers_api_query_test.py +++ b/backend/tests/handlers_api_query_test.py @@ -95,6 +95,11 @@ def test_create_google_redirect(self): redirect = query.create_google_redirect("&? Search test") self.assertEqual(redirect, "https://google.com/#q=%26%3F+Search+test") + def test_get_bing_data(self): + """ Test to get the data back from bing. """ + data = query.get_bing_data("Is google better than bing ?") + self.assertEqual(data, "No way") + def open_with_auth(self, url, method): fake_token = get_fake_jwt_token() return self.app.open(url, method=method, headers={"Authorization": "Bearer " + fake_token}, From c83d2d93659df40f388db63b9a93b4255a1e9793 Mon Sep 17 00:00:00 2001 From: Aashil Date: Wed, 14 Sep 2016 12:52:16 -0400 Subject: [PATCH 03/23] fix me later! PROD-278: Write code to make request to bing api in the backend. --- backend/handlers/api/query.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/backend/handlers/api/query.py b/backend/handlers/api/query.py index 5ad631c..04a0080 100644 --- a/backend/handlers/api/query.py +++ b/backend/handlers/api/query.py @@ -2,6 +2,7 @@ import datetime import logging import urllib +import requests from flask import request, abort, jsonify from shared import app @@ -46,6 +47,8 @@ def query_handler(): if source not in ['site-search', 'omnibox']: abort(400) # The source field should be required. + print get_bing_data(query_string) + # Create a new Query entity from the q value. # TODO: Add the other values that we want from the request headers. query = Query( @@ -107,3 +110,11 @@ def create_google_redirect(search_string): escaped_q = urllib.urlencode({'q': search_string}) redirect = 'https://google.com/#' + escaped_q return redirect + + +def get_bing_data(query_string): + """ Get the search result using Bing's api. """ + url = 'http://api.cognitive.microsoft.com/bing/v5.0/search' + payload = {'q': query_string} + headers = {'Ocp-Apim-Subscription-Key': 'd4ded470d517472da9b40836ab319538'} + return requests.get(url, params=payload, headers=headers).content; \ No newline at end of file From 3fd12a1c4db881871836919a487a0009216a8aa8 Mon Sep 17 00:00:00 2001 From: Aashil Date: Wed, 14 Sep 2016 13:18:59 -0400 Subject: [PATCH 04/23] fix me later! PROD-278: Use urllib2 instead of requests because it is not fully supported for GAE. --- backend/handlers/api/query.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/backend/handlers/api/query.py b/backend/handlers/api/query.py index 04a0080..4cca779 100644 --- a/backend/handlers/api/query.py +++ b/backend/handlers/api/query.py @@ -2,7 +2,7 @@ import datetime import logging import urllib -import requests +import urllib2 from flask import request, abort, jsonify from shared import app @@ -114,7 +114,10 @@ def create_google_redirect(search_string): def get_bing_data(query_string): """ Get the search result using Bing's api. """ - url = 'http://api.cognitive.microsoft.com/bing/v5.0/search' - payload = {'q': query_string} + url = 'https://api.cognitive.microsoft.com/bing/v5.0/search' + data = urllib.urlencode({'q': query_string}) + print data headers = {'Ocp-Apim-Subscription-Key': 'd4ded470d517472da9b40836ab319538'} - return requests.get(url, params=payload, headers=headers).content; \ No newline at end of file + req = urllib2.Request(url, data, headers) + response = urllib2.urlopen(req).read() + return response From ed3abd3ed1138f79d4f1df8dde99a12b04419537 Mon Sep 17 00:00:00 2001 From: Aashil Date: Wed, 14 Sep 2016 13:47:11 -0400 Subject: [PATCH 05/23] fix me later! PROD-278: Try adding User-Agent header but no luck --- backend/handlers/api/query.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/backend/handlers/api/query.py b/backend/handlers/api/query.py index 4cca779..f2eef06 100644 --- a/backend/handlers/api/query.py +++ b/backend/handlers/api/query.py @@ -117,7 +117,11 @@ def get_bing_data(query_string): url = 'https://api.cognitive.microsoft.com/bing/v5.0/search' data = urllib.urlencode({'q': query_string}) print data - headers = {'Ocp-Apim-Subscription-Key': 'd4ded470d517472da9b40836ab319538'} + headers = {'Ocp-Apim-Subscription-Key': 'd4ded470d517472da9b40836ab319538', + 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) ' + 'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116' + ' Safari/537.36' + } req = urllib2.Request(url, data, headers) response = urllib2.urlopen(req).read() return response From a871a854028a4d2e7f8e15bfdaed6ffea35e8efa Mon Sep 17 00:00:00 2001 From: Aashil Date: Wed, 14 Sep 2016 15:01:41 -0400 Subject: [PATCH 06/23] fix me later! PROD-278: fake commit for Frank to debug it. --- backend/handlers/api/query.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/backend/handlers/api/query.py b/backend/handlers/api/query.py index f2eef06..457f016 100644 --- a/backend/handlers/api/query.py +++ b/backend/handlers/api/query.py @@ -123,5 +123,10 @@ def get_bing_data(query_string): ' Safari/537.36' } req = urllib2.Request(url, data, headers) - response = urllib2.urlopen(req).read() + try: + req = urllib2.Request(url, data, headers) + response = urllib2.urlopen(req).read() + except urllib2.HTTPError as err: + print err + print 'hey' return response From be6daa84c84e7fec14bf4ae355740abe77eee45d Mon Sep 17 00:00:00 2001 From: Frank Carey Date: Wed, 14 Sep 2016 15:32:59 -0400 Subject: [PATCH 07/23] Got it working by adding the get params to the link itself. --- backend/handlers/api/query.py | 37 +++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/backend/handlers/api/query.py b/backend/handlers/api/query.py index 457f016..ccc7502 100644 --- a/backend/handlers/api/query.py +++ b/backend/handlers/api/query.py @@ -2,7 +2,7 @@ import datetime import logging import urllib -import urllib2 +from google.appengine.api import urlfetch from flask import request, abort, jsonify from shared import app @@ -18,9 +18,13 @@ def query_handler(): # Make sure the length of the query string is at least 1 char. search_string = request.args.get('q', '') + + tags = get_tags(search_string) query_string = get_query(search_string) + resp = get_bing_data(query_string) + # Return 400 bad request error if the search_string contains only # hashtags and no actual search query. if len(query_string) == 0: @@ -47,7 +51,7 @@ def query_handler(): if source not in ['site-search', 'omnibox']: abort(400) # The source field should be required. - print get_bing_data(query_string) + # Create a new Query entity from the q value. # TODO: Add the other values that we want from the request headers. @@ -114,19 +118,18 @@ def create_google_redirect(search_string): def get_bing_data(query_string): """ Get the search result using Bing's api. """ - url = 'https://api.cognitive.microsoft.com/bing/v5.0/search' - data = urllib.urlencode({'q': query_string}) - print data - headers = {'Ocp-Apim-Subscription-Key': 'd4ded470d517472da9b40836ab319538', - 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) ' - 'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116' - ' Safari/537.36' - } - req = urllib2.Request(url, data, headers) + url = 'https://api.cognitive.microsoft.com/bing/v5.0/search?q=asdf' + #url = 'http://www.bbc.co.uk/radio1/playlist.json' + try: - req = urllib2.Request(url, data, headers) - response = urllib2.urlopen(req).read() - except urllib2.HTTPError as err: - print err - print 'hey' - return response + headers = {'Ocp-Apim-Subscription-Key': 'd4ded470d517472da9b40836ab319538'} + result = urlfetch.fetch( + url=url, + method=urlfetch.GET, + headers=headers) + print(result.content) + except urlfetch.Error: + logging.exception('Caught exception fetching url') + + + return result From df9040e171236cca9559a66bd9a79864bafcedb6 Mon Sep 17 00:00:00 2001 From: Aashil Date: Wed, 14 Sep 2016 17:04:41 -0400 Subject: [PATCH 08/23] fix me later! PROD-278: done with setting up the structure of the response to the frontend --- backend/handlers/api/query.py | 40 +++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/backend/handlers/api/query.py b/backend/handlers/api/query.py index ccc7502..8e3334a 100644 --- a/backend/handlers/api/query.py +++ b/backend/handlers/api/query.py @@ -2,6 +2,7 @@ import datetime import logging import urllib +import json from google.appengine.api import urlfetch from flask import request, abort, jsonify @@ -23,8 +24,6 @@ def query_handler(): tags = get_tags(search_string) query_string = get_query(search_string) - resp = get_bing_data(query_string) - # Return 400 bad request error if the search_string contains only # hashtags and no actual search query. if len(query_string) == 0: @@ -34,8 +33,19 @@ def query_handler(): # If we get an unauthenticated query request, just go ahead and redirect them to google for now # without recording it in the database. (We may change this behavior soon) if not security.is_request_with_auth(request): - return jsonify(ApiResponse({'redirect': create_google_redirect(query_string)})) - + data = get_bing_data(query_string)['webPages']['value'] + payload = [] + count = 0 + for i in data: + count += 1 + data = { + 'name': i['name'], + 'url': i['url'] + } + payload.append(data) + if count == 3: + break + return jsonify(ApiResponse(payload)) # The request WAS trying to authenticate, so let's try to get the authenticated user. try: user = security.authenticate_user(request) @@ -72,7 +82,19 @@ def query_handler(): # Save to the datatore. query.put() logging.debug('query: %s', str(query)) - return jsonify(ApiResponse({'redirect': create_google_redirect(query_string)})) + data = get_bing_data(query_string)['webPages']['value'] + payload = [] + count = 0 + for i in data: + count += 1 + data = { + 'name': i['name'], + 'url': i['url'] + } + payload.append(data) + if count == 3: + break + return jsonify(ApiResponse(payload)) def get_tags(search_string): @@ -118,8 +140,7 @@ def create_google_redirect(search_string): def get_bing_data(query_string): """ Get the search result using Bing's api. """ - url = 'https://api.cognitive.microsoft.com/bing/v5.0/search?q=asdf' - #url = 'http://www.bbc.co.uk/radio1/playlist.json' + url = 'https://api.cognitive.microsoft.com/bing/v5.0/search?'+urllib.urlencode({'q':query_string}) try: headers = {'Ocp-Apim-Subscription-Key': 'd4ded470d517472da9b40836ab319538'} @@ -127,9 +148,6 @@ def get_bing_data(query_string): url=url, method=urlfetch.GET, headers=headers) - print(result.content) except urlfetch.Error: logging.exception('Caught exception fetching url') - - - return result + return json.loads(result.content) From d932dbbce549bc8bd2dc64054032f7ff966580f4 Mon Sep 17 00:00:00 2001 From: Aashil Date: Wed, 14 Sep 2016 17:52:10 -0400 Subject: [PATCH 09/23] fix me later! PROD-278: Trying to fix the bug when trying to make a request to bing which returns no results. --- backend/handlers/api/query.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/backend/handlers/api/query.py b/backend/handlers/api/query.py index 8e3334a..c071881 100644 --- a/backend/handlers/api/query.py +++ b/backend/handlers/api/query.py @@ -33,7 +33,11 @@ def query_handler(): # If we get an unauthenticated query request, just go ahead and redirect them to google for now # without recording it in the database. (We may change this behavior soon) if not security.is_request_with_auth(request): - data = get_bing_data(query_string)['webPages']['value'] + data = get_bing_data(query_string) + if 'webPages' in data: + data = data['webPages']['value'] + else: + return jsonify(ApiResponse(success=False)) payload = [] count = 0 for i in data: @@ -82,7 +86,11 @@ def query_handler(): # Save to the datatore. query.put() logging.debug('query: %s', str(query)) - data = get_bing_data(query_string)['webPages']['value'] + data = get_bing_data(query_string) + if 'webPages' in data: + data = data['webPages']['value'] + else: + return jsonify(ApiResponse(success=False)) payload = [] count = 0 for i in data: From d660ba1bc9b5f2c185cb3b106f3ec7d5fd48f447 Mon Sep 17 00:00:00 2001 From: Aashil Date: Wed, 14 Sep 2016 17:54:00 -0400 Subject: [PATCH 10/23] fix me later! PROD-278: Write the code to show the data in the frontend. --- default/src/app/search/search.component.html | 9 +++++++++ default/src/app/search/search.component.ts | 16 ++++++++++++++-- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/default/src/app/search/search.component.html b/default/src/app/search/search.component.html index af96607..384b6bd 100644 --- a/default/src/app/search/search.component.html +++ b/default/src/app/search/search.component.html @@ -8,4 +8,13 @@ +
+ + + + + +
link.namelink.url
+
+ diff --git a/default/src/app/search/search.component.ts b/default/src/app/search/search.component.ts index 33bb449..28eb44d 100644 --- a/default/src/app/search/search.component.ts +++ b/default/src/app/search/search.component.ts @@ -12,6 +12,7 @@ import {AuthService} from '../auth/auth.service'; export class SearchComponent { private preSearchText: any; + private res: any; constructor(private queryService: QueryService, private auth: AuthService) { this.preSearchText = this.populateSearch(window.location.href); this.recordOmniSearch(window.location.href); @@ -33,8 +34,8 @@ export class SearchComponent { this.queryService.doQuery(searchField, 'site-search').subscribe( data => { // If when data is returned from a query with a redirect set, do the redirect. - if (data['payload'] && data['payload']['redirect']) { - this._redirect(data['payload']['redirect']); + if (data['payload'] && data['success']) { + this.res = this.processData(data['payload']); } } ); @@ -79,4 +80,15 @@ export class SearchComponent { private _redirect(href: any) { window.location.href = href; } + + processData(items: any[]) { + let newData = []; + for (let item of items) { + newData.push({ + 'name' : item['name'], + 'url': item['url'], + }); + } + return newData; + } } From f2a1adc980a9931cc741cdc9cdda253c8538dbbc Mon Sep 17 00:00:00 2001 From: Aashil Date: Wed, 14 Sep 2016 17:57:56 -0400 Subject: [PATCH 11/23] PROD-278: Fix the bug where no results from bing threw an exception. --- backend/handlers/api/query.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/handlers/api/query.py b/backend/handlers/api/query.py index c071881..81571a0 100644 --- a/backend/handlers/api/query.py +++ b/backend/handlers/api/query.py @@ -37,7 +37,7 @@ def query_handler(): if 'webPages' in data: data = data['webPages']['value'] else: - return jsonify(ApiResponse(success=False)) + return jsonify(ApiResponse()) payload = [] count = 0 for i in data: @@ -90,7 +90,7 @@ def query_handler(): if 'webPages' in data: data = data['webPages']['value'] else: - return jsonify(ApiResponse(success=False)) + return jsonify(ApiResponse()) payload = [] count = 0 for i in data: From 10872979315e578a049e5126dfeb0f1220822393 Mon Sep 17 00:00:00 2001 From: Aashil Date: Thu, 15 Sep 2016 09:39:58 -0400 Subject: [PATCH 12/23] fix me later! PROD-278: Return all the results from bing (which is 10 results) --- backend/handlers/api/query.py | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/backend/handlers/api/query.py b/backend/handlers/api/query.py index 81571a0..831c90f 100644 --- a/backend/handlers/api/query.py +++ b/backend/handlers/api/query.py @@ -19,8 +19,6 @@ def query_handler(): # Make sure the length of the query string is at least 1 char. search_string = request.args.get('q', '') - - tags = get_tags(search_string) query_string = get_query(search_string) @@ -39,16 +37,12 @@ def query_handler(): else: return jsonify(ApiResponse()) payload = [] - count = 0 for i in data: - count += 1 data = { 'name': i['name'], 'url': i['url'] } payload.append(data) - if count == 3: - break return jsonify(ApiResponse(payload)) # The request WAS trying to authenticate, so let's try to get the authenticated user. try: @@ -65,8 +59,6 @@ def query_handler(): if source not in ['site-search', 'omnibox']: abort(400) # The source field should be required. - - # Create a new Query entity from the q value. # TODO: Add the other values that we want from the request headers. query = Query( @@ -92,16 +84,12 @@ def query_handler(): else: return jsonify(ApiResponse()) payload = [] - count = 0 for i in data: - count += 1 data = { 'name': i['name'], 'url': i['url'] } payload.append(data) - if count == 3: - break return jsonify(ApiResponse(payload)) From 43a56b06a680db0060a1b1a6a7c2e4bae9756fff Mon Sep 17 00:00:00 2001 From: Aashil Date: Thu, 15 Sep 2016 09:48:40 -0400 Subject: [PATCH 13/23] fix me later! PROD-278: Got the results to be displayed in the front end. --- default/src/app/search/search.component.html | 4 ++-- default/src/app/search/search.component.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/default/src/app/search/search.component.html b/default/src/app/search/search.component.html index 384b6bd..e05412e 100644 --- a/default/src/app/search/search.component.html +++ b/default/src/app/search/search.component.html @@ -11,8 +11,8 @@
- - + +
link.namelink.url{{link.name}}{{link.url}}
diff --git a/default/src/app/search/search.component.ts b/default/src/app/search/search.component.ts index 28eb44d..f436bc1 100644 --- a/default/src/app/search/search.component.ts +++ b/default/src/app/search/search.component.ts @@ -82,7 +82,7 @@ export class SearchComponent { } processData(items: any[]) { - let newData = []; + let newData: any = []; for (let item of items) { newData.push({ 'name' : item['name'], From 97aa1b59e3ae8be41a1d243cfe6e96b7638262d2 Mon Sep 17 00:00:00 2001 From: Aashil Date: Thu, 15 Sep 2016 09:55:11 -0400 Subject: [PATCH 14/23] fix me later! PROD-278: Return displayUrl as a part of response from the backend. --- backend/handlers/api/query.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/backend/handlers/api/query.py b/backend/handlers/api/query.py index 831c90f..5d88a58 100644 --- a/backend/handlers/api/query.py +++ b/backend/handlers/api/query.py @@ -40,7 +40,8 @@ def query_handler(): for i in data: data = { 'name': i['name'], - 'url': i['url'] + 'url': i['url'], + 'displayUrl': i['displayUrl'] } payload.append(data) return jsonify(ApiResponse(payload)) @@ -87,7 +88,8 @@ def query_handler(): for i in data: data = { 'name': i['name'], - 'url': i['url'] + 'url': i['url'], + 'displayUrl': i['displayUrl'] } payload.append(data) return jsonify(ApiResponse(payload)) From 965c67bb2353968afed1b2ee4a9b9fefa8a304f2 Mon Sep 17 00:00:00 2001 From: Aashil Date: Thu, 15 Sep 2016 10:20:20 -0400 Subject: [PATCH 15/23] fix me later! PROD-278: Return the snippet(description) of the website as a part of the response. * Display the results in the frontend nicely. --- backend/handlers/api/query.py | 6 ++++-- default/src/app/search/search.component.html | 13 ++++++------- default/src/app/search/search.component.ts | 2 ++ 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/backend/handlers/api/query.py b/backend/handlers/api/query.py index 5d88a58..687b2ce 100644 --- a/backend/handlers/api/query.py +++ b/backend/handlers/api/query.py @@ -41,7 +41,8 @@ def query_handler(): data = { 'name': i['name'], 'url': i['url'], - 'displayUrl': i['displayUrl'] + 'displayUrl': i['displayUrl'], + 'snippet': i['snippet'] } payload.append(data) return jsonify(ApiResponse(payload)) @@ -89,7 +90,8 @@ def query_handler(): data = { 'name': i['name'], 'url': i['url'], - 'displayUrl': i['displayUrl'] + 'displayUrl': i['displayUrl'], + 'snippet': i['snippet'] } payload.append(data) return jsonify(ApiResponse(payload)) diff --git a/default/src/app/search/search.component.html b/default/src/app/search/search.component.html index e05412e..82e4fec 100644 --- a/default/src/app/search/search.component.html +++ b/default/src/app/search/search.component.html @@ -7,14 +7,13 @@ - +
- - - - - -
{{link.name}}{{link.url}}
+ + {{link.name}}
+ {{link.displayUrl}}
+ {{link.snippet}}

+
diff --git a/default/src/app/search/search.component.ts b/default/src/app/search/search.component.ts index f436bc1..439b036 100644 --- a/default/src/app/search/search.component.ts +++ b/default/src/app/search/search.component.ts @@ -87,6 +87,8 @@ export class SearchComponent { newData.push({ 'name' : item['name'], 'url': item['url'], + 'displayUrl': item['displayUrl'], + 'snippet': item['snippet'] }); } return newData; From ab0ae5dbcfa46ced835e03bcf780644adcb7243c Mon Sep 17 00:00:00 2001 From: Aashil Date: Thu, 15 Sep 2016 10:43:08 -0400 Subject: [PATCH 16/23] fix me later! PROD-278: Create a service to handle the hiding of the report on fetching the queries. --- default/src/app/app.module.ts | 2 ++ default/src/app/report/report.component.html | 2 +- default/src/app/report/report.component.ts | 7 +++++-- default/src/app/search/search.component.ts | 4 +++- default/src/app/shared/toggle.report.service.ts | 9 +++++++++ 5 files changed, 20 insertions(+), 4 deletions(-) create mode 100644 default/src/app/shared/toggle.report.service.ts diff --git a/default/src/app/app.module.ts b/default/src/app/app.module.ts index 396183c..5ac3fc7 100644 --- a/default/src/app/app.module.ts +++ b/default/src/app/app.module.ts @@ -9,6 +9,7 @@ import { AUTH_PROVIDERS } from 'angular2-jwt'; import { FocusMeDirective } from './shared/focus-me.directive'; import { BackendService } from './shared/backend.service'; import { KeysPipe } from './shared/keys.pipe'; +import {ToggleReportService} from './shared/toggle.report.service'; import { AppComponent } from './app.component'; @@ -42,6 +43,7 @@ let providers = [ HTTP_PROVIDERS, AuthService, BackendService, + ToggleReportService ]; let declarations = [ diff --git a/default/src/app/report/report.component.html b/default/src/app/report/report.component.html index 75923f0..c3e000c 100644 --- a/default/src/app/report/report.component.html +++ b/default/src/app/report/report.component.html @@ -1,4 +1,4 @@ -
+
diff --git a/default/src/app/report/report.component.ts b/default/src/app/report/report.component.ts index 000cd9f..4277ec8 100644 --- a/default/src/app/report/report.component.ts +++ b/default/src/app/report/report.component.ts @@ -7,6 +7,7 @@ import { QueryService } from '../query/query.service'; import { AuthService } from '../auth/index'; // Note that this also imports moment itself. import * as moment from 'moment-timezone'; +import {ToggleReportService} from '../shared/toggle.report.service'; @Component({ selector: 'report', @@ -24,6 +25,8 @@ export class ReportComponent { public currDay: moment.Moment = null; + public showReport: boolean = true; + public formatMonth(dateTime: moment.Moment): string { return dateTime.format('MMM'); } @@ -46,9 +49,9 @@ export class ReportComponent { moment.tz.setDefault(this.tz); } - constructor(private queryService: QueryService, private auth: AuthService) { + constructor(private queryService: QueryService, private auth: AuthService, private toggleReport: ToggleReportService) { this.setTimezone(); - + this.showReport = toggleReport.showReport; this.auth.getUser().subscribe( user => { if (user && user.loggedIn) { diff --git a/default/src/app/search/search.component.ts b/default/src/app/search/search.component.ts index 439b036..4d4d727 100644 --- a/default/src/app/search/search.component.ts +++ b/default/src/app/search/search.component.ts @@ -2,6 +2,7 @@ import { Component } from '@angular/core'; import { QueryService } from '../query/index'; import {AuthService} from '../auth/auth.service'; +import {ToggleReportService} from '../shared/toggle.report.service'; @Component({ selector: 'search', @@ -13,7 +14,7 @@ export class SearchComponent { private preSearchText: any; private res: any; - constructor(private queryService: QueryService, private auth: AuthService) { + constructor(private queryService: QueryService, private auth: AuthService, private toggleReport: ToggleReportService) { this.preSearchText = this.populateSearch(window.location.href); this.recordOmniSearch(window.location.href); } @@ -36,6 +37,7 @@ export class SearchComponent { // If when data is returned from a query with a redirect set, do the redirect. if (data['payload'] && data['success']) { this.res = this.processData(data['payload']); + this.toggleReport.hideReport(); } } ); diff --git a/default/src/app/shared/toggle.report.service.ts b/default/src/app/shared/toggle.report.service.ts new file mode 100644 index 0000000..d662dd2 --- /dev/null +++ b/default/src/app/shared/toggle.report.service.ts @@ -0,0 +1,9 @@ +export class ToggleReportService { + + showReport: boolean = true; + + hideReport() { + this.showReport = false; + } + +} From 18b44655ff9db5935d0325cd24803c1795b0711e Mon Sep 17 00:00:00 2001 From: Aashil Date: Thu, 15 Sep 2016 11:00:37 -0400 Subject: [PATCH 17/23] fix me later! PROD-278: Add feature to hide the reports when making a search. * Return the redirect back as a response. --- backend/handlers/api/query.py | 2 ++ default/src/app/report/report.component.html | 2 +- default/src/app/report/report.component.ts | 3 --- default/src/app/search/search.component.html | 3 +++ 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/backend/handlers/api/query.py b/backend/handlers/api/query.py index 687b2ce..2f41ee7 100644 --- a/backend/handlers/api/query.py +++ b/backend/handlers/api/query.py @@ -45,6 +45,7 @@ def query_handler(): 'snippet': i['snippet'] } payload.append(data) + payload.append({'redirect': create_google_redirect(query_string)}) return jsonify(ApiResponse(payload)) # The request WAS trying to authenticate, so let's try to get the authenticated user. try: @@ -94,6 +95,7 @@ def query_handler(): 'snippet': i['snippet'] } payload.append(data) + payload.append({'redirect': create_google_redirect(query_string)}) return jsonify(ApiResponse(payload)) diff --git a/default/src/app/report/report.component.html b/default/src/app/report/report.component.html index c3e000c..69079d6 100644 --- a/default/src/app/report/report.component.html +++ b/default/src/app/report/report.component.html @@ -1,4 +1,4 @@ -
+
diff --git a/default/src/app/report/report.component.ts b/default/src/app/report/report.component.ts index 4277ec8..f2ae00e 100644 --- a/default/src/app/report/report.component.ts +++ b/default/src/app/report/report.component.ts @@ -25,8 +25,6 @@ export class ReportComponent { public currDay: moment.Moment = null; - public showReport: boolean = true; - public formatMonth(dateTime: moment.Moment): string { return dateTime.format('MMM'); } @@ -51,7 +49,6 @@ export class ReportComponent { constructor(private queryService: QueryService, private auth: AuthService, private toggleReport: ToggleReportService) { this.setTimezone(); - this.showReport = toggleReport.showReport; this.auth.getUser().subscribe( user => { if (user && user.loggedIn) { diff --git a/default/src/app/search/search.component.html b/default/src/app/search/search.component.html index 82e4fec..0068555 100644 --- a/default/src/app/search/search.component.html +++ b/default/src/app/search/search.component.html @@ -6,6 +6,9 @@ + + +
From b03983d7b24e997311e6bda214b966025e1212d5 Mon Sep 17 00:00:00 2001 From: Aashil Date: Thu, 15 Sep 2016 11:09:03 -0400 Subject: [PATCH 18/23] PROD-278: Add a 'google instead' button if the user decides to google the search instead of using ours. --- backend/handlers/api/query.py | 4 ++-- default/src/app/search/search.component.html | 4 ++-- default/src/app/search/search.component.ts | 5 +++++ 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/backend/handlers/api/query.py b/backend/handlers/api/query.py index 2f41ee7..8f749d7 100644 --- a/backend/handlers/api/query.py +++ b/backend/handlers/api/query.py @@ -45,7 +45,7 @@ def query_handler(): 'snippet': i['snippet'] } payload.append(data) - payload.append({'redirect': create_google_redirect(query_string)}) + payload.append({'googleRedirectLink': create_google_redirect(query_string)}) return jsonify(ApiResponse(payload)) # The request WAS trying to authenticate, so let's try to get the authenticated user. try: @@ -95,7 +95,7 @@ def query_handler(): 'snippet': i['snippet'] } payload.append(data) - payload.append({'redirect': create_google_redirect(query_string)}) + payload.append({'googleRedirectLink': create_google_redirect(query_string)}) return jsonify(ApiResponse(payload)) diff --git a/default/src/app/search/search.component.html b/default/src/app/search/search.component.html index 0068555..bde30ce 100644 --- a/default/src/app/search/search.component.html +++ b/default/src/app/search/search.component.html @@ -6,8 +6,8 @@ - - + +

diff --git a/default/src/app/search/search.component.ts b/default/src/app/search/search.component.ts index 4d4d727..5357bb2 100644 --- a/default/src/app/search/search.component.ts +++ b/default/src/app/search/search.component.ts @@ -14,6 +14,7 @@ export class SearchComponent { private preSearchText: any; private res: any; + private googleRedirectLink: any; constructor(private queryService: QueryService, private auth: AuthService, private toggleReport: ToggleReportService) { this.preSearchText = this.populateSearch(window.location.href); this.recordOmniSearch(window.location.href); @@ -86,6 +87,10 @@ export class SearchComponent { processData(items: any[]) { let newData: any = []; for (let item of items) { + if(item['googleRedirectLink']) { + this.googleRedirectLink = item['googleRedirectLink'] + continue; + } newData.push({ 'name' : item['name'], 'url': item['url'], From 29a946d141184399e5cf5e4aaf3c27ca961d8ad6 Mon Sep 17 00:00:00 2001 From: Aashil Date: Thu, 15 Sep 2016 11:20:57 -0400 Subject: [PATCH 19/23] fix me later! PROD-278: Not working. Trying to make the searches from the omnibox work. --- default/src/app/search/search.component.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/default/src/app/search/search.component.ts b/default/src/app/search/search.component.ts index 5357bb2..244cead 100644 --- a/default/src/app/search/search.component.ts +++ b/default/src/app/search/search.component.ts @@ -17,6 +17,9 @@ export class SearchComponent { private googleRedirectLink: any; constructor(private queryService: QueryService, private auth: AuthService, private toggleReport: ToggleReportService) { this.preSearchText = this.populateSearch(window.location.href); + if (this.preSearchText) { + this.submit(this.preSearchText); + } this.recordOmniSearch(window.location.href); } From 64ea117b8ad4d917da8cc52ba549db70d3ff02ac Mon Sep 17 00:00:00 2001 From: Aashil Date: Thu, 15 Sep 2016 13:49:06 -0400 Subject: [PATCH 20/23] PROD-278: Fix the failing tests because of the changes introduced in the frontend. * todo: fix the backend test. * one of the frontend test fails which I don't think is relevant anymore. Keeping it as of now. --- .../src/app/report/report.component.spec.ts | 4 ++- .../src/app/search/search.component.spec.ts | 33 +++++++++++++++---- default/src/app/search/search.component.ts | 4 +-- 3 files changed, 31 insertions(+), 10 deletions(-) diff --git a/default/src/app/report/report.component.spec.ts b/default/src/app/report/report.component.spec.ts index e628d82..cf6ece0 100644 --- a/default/src/app/report/report.component.spec.ts +++ b/default/src/app/report/report.component.spec.ts @@ -6,6 +6,7 @@ import { Observable, BehaviorSubject, Observer } from 'rxjs'; import { User } from '../shared/user'; // Note that this also imports moment itself. import * as moment from 'moment-timezone'; +import {ToggleReportService} from '../shared/toggle.report.service'; class MockQueryService { @@ -46,7 +47,8 @@ describe('SearchComponent', () => { addProviders([ ReportComponent, {provide: QueryService, useClass: MockQueryService}, - {provide: AuthService, useClass: MockAuthService} + {provide: AuthService, useClass: MockAuthService}, + {provide: ToggleReportService, useClass: ToggleReportService} ]); }); it('should not call QueryService.getQueries() when user is logged out.', diff --git a/default/src/app/search/search.component.spec.ts b/default/src/app/search/search.component.spec.ts index c46cc92..ed59a91 100644 --- a/default/src/app/search/search.component.spec.ts +++ b/default/src/app/search/search.component.spec.ts @@ -4,6 +4,7 @@ import { QueryService } from '../query/index'; import { AuthService} from '../auth/auth.service'; import { Observable, BehaviorSubject, Observer } from 'rxjs'; import { User } from '../shared/user'; +import { ToggleReportService } from '../shared/toggle.report.service'; class MockQueryService { @@ -46,7 +47,8 @@ describe('SearchComponent', () => { addProviders([ SearchComponent, {provide: QueryService, useClass: MockQueryService}, - {provide: AuthService, useClass: MockAuthService} + {provide: AuthService, useClass: MockAuthService}, + {provide: ToggleReportService, useClass: ToggleReportService} ]); }); it('submit button should NOT send a query if search field is empty', @@ -115,9 +117,16 @@ describe('SearchComponent', () => { (observer: Observer) => { observer.next({ 'success': 'true', - 'payload': { - 'redirect': 'http://google.com/q#=whatever', - }, + 'payload': [ + { + 'name': 'fake', + 'url': 'fake.com', + 'snippet': 'this is fake' + }, + { + 'redirect': 'http://google.com/q#=whatever', + } + ], 'cursor': null }); observer.complete(); @@ -125,9 +134,19 @@ describe('SearchComponent', () => { ); }); - spyOn(component, 'getBingData'); - component.getBingData('search text'); - expect(component.data).toBe('whatever results bing api gives us'); + spyOn(component, 'processData'); + component.doSearch('search text'); + expect(component.processData).toHaveBeenCalledWith([ + { + 'name': 'fake', + 'url': 'fake.com', + 'snippet': 'this is fake' + }, + { + 'redirect': 'http://google.com/q#=whatever', + } + ] + ); }) ); diff --git a/default/src/app/search/search.component.ts b/default/src/app/search/search.component.ts index 244cead..e1ec472 100644 --- a/default/src/app/search/search.component.ts +++ b/default/src/app/search/search.component.ts @@ -90,8 +90,8 @@ export class SearchComponent { processData(items: any[]) { let newData: any = []; for (let item of items) { - if(item['googleRedirectLink']) { - this.googleRedirectLink = item['googleRedirectLink'] + if (item['googleRedirectLink']) { + this.googleRedirectLink = item['googleRedirectLink']; continue; } newData.push({ From 4b3e352c9a6427aaf3366f7c526e76418f15253d Mon Sep 17 00:00:00 2001 From: Aashil Date: Thu, 15 Sep 2016 16:37:31 -0400 Subject: [PATCH 21/23] fix me later! PROD-278: Add new result component to hold the results data. Not able to display the results though. --- default/src/app/app.component.html | 1 + default/src/app/app.module.ts | 6 ++++- default/src/app/result/index.ts | 1 + default/src/app/result/result.component.html | 7 +++++ default/src/app/result/result.component.ts | 13 ++++++++++ default/src/app/result/result.service.ts | 21 +++++++++++++++ default/src/app/search/search.component.html | 11 +------- default/src/app/search/search.component.ts | 27 +++++--------------- 8 files changed, 56 insertions(+), 31 deletions(-) create mode 100644 default/src/app/result/index.ts create mode 100644 default/src/app/result/result.component.html create mode 100644 default/src/app/result/result.component.ts create mode 100644 default/src/app/result/result.service.ts diff --git a/default/src/app/app.component.html b/default/src/app/app.component.html index eeb00db..cdfd408 100644 --- a/default/src/app/app.component.html +++ b/default/src/app/app.component.html @@ -12,6 +12,7 @@

Stackbot

+
diff --git a/default/src/app/app.module.ts b/default/src/app/app.module.ts index 5ac3fc7..ba1b70c 100644 --- a/default/src/app/app.module.ts +++ b/default/src/app/app.module.ts @@ -16,10 +16,12 @@ import { AppComponent } from './app.component'; import { ReportComponent } from './report/index'; import { AuthService, AuthButtonComponent, AuthIntegrationsComponent } from './auth/index'; import { SearchComponent } from './search/index'; +import { ResultComponent } from './result/index'; // DO NOT DELETE: This is needed or the compiler says, Cannot find namespace 'firebase'. /* tslint:disable */ import * as firebase from 'firebase'; +import {ResultService} from './result/result.service'; /* tslint:enable */ const firebaseConfig = { @@ -43,7 +45,8 @@ let providers = [ HTTP_PROVIDERS, AuthService, BackendService, - ToggleReportService + ToggleReportService, + ResultService ]; let declarations = [ @@ -54,6 +57,7 @@ let declarations = [ FocusMeDirective, AuthIntegrationsComponent, KeysPipe, + ResultComponent, ]; let imports = [ diff --git a/default/src/app/result/index.ts b/default/src/app/result/index.ts new file mode 100644 index 0000000..beae3b5 --- /dev/null +++ b/default/src/app/result/index.ts @@ -0,0 +1 @@ +export * from './result.component'; diff --git a/default/src/app/result/result.component.html b/default/src/app/result/result.component.html new file mode 100644 index 0000000..11dd5eb --- /dev/null +++ b/default/src/app/result/result.component.html @@ -0,0 +1,7 @@ +
+ + {{link.name}}
+ {{link.displayUrl}}
+ {{link.snippet}}

+
+
\ No newline at end of file diff --git a/default/src/app/result/result.component.ts b/default/src/app/result/result.component.ts new file mode 100644 index 0000000..375a12d --- /dev/null +++ b/default/src/app/result/result.component.ts @@ -0,0 +1,13 @@ +import { Component, Input } from '@angular/core'; +import {ResultService} from './result.service'; + +@Component({ + selector: 'result', + templateUrl: 'result.component.html', +}) + +export class ResultComponent { + + constructor(private resultService: ResultService) {} + +} diff --git a/default/src/app/result/result.service.ts b/default/src/app/result/result.service.ts new file mode 100644 index 0000000..5687db4 --- /dev/null +++ b/default/src/app/result/result.service.ts @@ -0,0 +1,21 @@ +export class ResultService { + + public data = []; + + processData(items: any[]) { + let newData: any = []; + for (let item of items) { + if (item['googleRedirectLink']) { + continue; + } + newData.push({ + 'name' : item['name'], + 'url': item['url'], + 'displayUrl': item['displayUrl'], + 'snippet': item['snippet'] + }); + } + this.data = newData; + } + +} diff --git a/default/src/app/search/search.component.html b/default/src/app/search/search.component.html index bde30ce..165ebf1 100644 --- a/default/src/app/search/search.component.html +++ b/default/src/app/search/search.component.html @@ -7,16 +7,7 @@ - +
-
-
- - {{link.name}}
- {{link.displayUrl}}
- {{link.snippet}}

-
-
- diff --git a/default/src/app/search/search.component.ts b/default/src/app/search/search.component.ts index e1ec472..3ab1d49 100644 --- a/default/src/app/search/search.component.ts +++ b/default/src/app/search/search.component.ts @@ -3,6 +3,7 @@ import { Component } from '@angular/core'; import { QueryService } from '../query/index'; import {AuthService} from '../auth/auth.service'; import {ToggleReportService} from '../shared/toggle.report.service'; +import {ResultService} from '../result/result.service'; @Component({ selector: 'search', @@ -13,9 +14,9 @@ import {ToggleReportService} from '../shared/toggle.report.service'; export class SearchComponent { private preSearchText: any; - private res: any; private googleRedirectLink: any; - constructor(private queryService: QueryService, private auth: AuthService, private toggleReport: ToggleReportService) { + constructor(private queryService: QueryService, private auth: AuthService, + private toggleReport: ToggleReportService, private resultService: ResultService) { this.preSearchText = this.populateSearch(window.location.href); if (this.preSearchText) { this.submit(this.preSearchText); @@ -40,8 +41,11 @@ export class SearchComponent { data => { // If when data is returned from a query with a redirect set, do the redirect. if (data['payload'] && data['success']) { - this.res = this.processData(data['payload']); + this.resultService.processData(data['payload']); this.toggleReport.hideReport(); + if (data['payload'][data['payload'].length - 1]['googleRedirectLink']) { + this.googleRedirectLink = data['payload'][data['payload'].length - 1]['googleRedirectLink']; + } } } ); @@ -86,21 +90,4 @@ export class SearchComponent { private _redirect(href: any) { window.location.href = href; } - - processData(items: any[]) { - let newData: any = []; - for (let item of items) { - if (item['googleRedirectLink']) { - this.googleRedirectLink = item['googleRedirectLink']; - continue; - } - newData.push({ - 'name' : item['name'], - 'url': item['url'], - 'displayUrl': item['displayUrl'], - 'snippet': item['snippet'] - }); - } - return newData; - } } From 268ed7e40651af71c19437e974440f2510c68781 Mon Sep 17 00:00:00 2001 From: Aashil Date: Thu, 15 Sep 2016 16:51:08 -0400 Subject: [PATCH 22/23] fix me later! PROD-278: Finally made it to display the results using a separate service instead of injecting the ResultComponent directly. --- default/src/app/result/result.component.html | 3 ++- default/src/app/result/result.service.ts | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/default/src/app/result/result.component.html b/default/src/app/result/result.component.html index 11dd5eb..7f3d91f 100644 --- a/default/src/app/result/result.component.html +++ b/default/src/app/result/result.component.html @@ -1,5 +1,6 @@ +
- + {{link.name}}
{{link.displayUrl}}
{{link.snippet}}

diff --git a/default/src/app/result/result.service.ts b/default/src/app/result/result.service.ts index 5687db4..d09cf91 100644 --- a/default/src/app/result/result.service.ts +++ b/default/src/app/result/result.service.ts @@ -1,6 +1,6 @@ export class ResultService { - public data = []; + data: any = []; processData(items: any[]) { let newData: any = []; From f87793b165fcb868eb8d0cf81da6bc6e16291ed6 Mon Sep 17 00:00:00 2001 From: Aashil Date: Thu, 15 Sep 2016 16:56:32 -0400 Subject: [PATCH 23/23] fix me later! PROD-278: Separate the 'search' and 'google instead?' button by 2px. --- default/src/app/search/search.component.css | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/default/src/app/search/search.component.css b/default/src/app/search/search.component.css index af5fbfa..766d9bd 100644 --- a/default/src/app/search/search.component.css +++ b/default/src/app/search/search.component.css @@ -40,4 +40,6 @@ button:hover { .left-addon input { padding-left: 30px; } .right-addon input { padding-right: 30px; } - +#google-search-button { + margin-left: 2px; +}