[Search] Moved search folder location
Moved search from platform/features/search to platform/search. Added more style corrections.
This commit is contained in:
58
platform/search/bundle.json
Normal file
58
platform/search/bundle.json
Normal file
@@ -0,0 +1,58 @@
|
||||
{
|
||||
"name": "Search",
|
||||
"description": "Allows the user to search through the file tree.",
|
||||
"extensions": {
|
||||
"controllers": [
|
||||
{
|
||||
"key": "SearchController",
|
||||
"implementation": "controllers/SearchController.js",
|
||||
"depends": [ "$scope", "searchService" ]
|
||||
},
|
||||
{
|
||||
"key": "SearchItemController",
|
||||
"implementation": "controllers/SearchItemController.js",
|
||||
"depends": [ "$scope" ]
|
||||
}
|
||||
],
|
||||
"templates": [
|
||||
{
|
||||
"key": "search",
|
||||
"templateUrl": "templates/search.html",
|
||||
"uses": [ "controls", "forms" ]
|
||||
}
|
||||
],
|
||||
"representations": [
|
||||
{
|
||||
"key": "search-item",
|
||||
"templateUrl": "templates/search-item.html"
|
||||
}
|
||||
],
|
||||
"components": [
|
||||
{
|
||||
"provides": "searchService",
|
||||
"type": "provider",
|
||||
"implementation": "providers/GenericSearchProvider.js",
|
||||
"depends": [ "$q", "objectService", "workerService", "roots[]" ]
|
||||
},
|
||||
{
|
||||
"provides": "searchService",
|
||||
"type": "provider",
|
||||
"implementation": "providers/ElasticsearchSearchProvider.js",
|
||||
"depends": [ "$http", "objectService", "ELASTIC_ROOT" ]
|
||||
},
|
||||
{
|
||||
"provides": "searchService",
|
||||
"type": "aggregator",
|
||||
"implementation": "SearchAggregator.js",
|
||||
"depends": [ "$q" ]
|
||||
}
|
||||
],
|
||||
"workers": [
|
||||
{
|
||||
"key": "genericSearchWorker",
|
||||
"scriptUrl": "workers/GenericSearchWorker.js",
|
||||
"depends": [ "objectService" ]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
46
platform/search/res/templates/search-item.html
Normal file
46
platform/search/res/templates/search-item.html
Normal file
@@ -0,0 +1,46 @@
|
||||
<!--
|
||||
Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||
as represented by the Administrator of the National Aeronautics and Space
|
||||
Administration. All rights reserved.
|
||||
|
||||
Open MCT Web is licensed under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0.
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
License for the specific language governing permissions and limitations
|
||||
under the License.
|
||||
|
||||
Open MCT Web includes source code licensed under additional open source
|
||||
licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
this source code distribution or the Licensing information page available
|
||||
at runtime from the About dialog for additional information.
|
||||
-->
|
||||
|
||||
<span ng-controller="SearchItemController as controller">
|
||||
<div class="search-result-item"
|
||||
ng-class="{selected: controller.isSelected()}">
|
||||
<mct-representation key="'label'"
|
||||
mct-object="domainObject"
|
||||
ng-model="ngModel"
|
||||
ng-click="ngModel.selectedObject = domainObject">
|
||||
</mct-representation>
|
||||
|
||||
<!--span
|
||||
class="search-result-item menus-to-left"
|
||||
ng-class="{selected: controller.isSelected()}"
|
||||
>
|
||||
asdf
|
||||
<!--span
|
||||
class='ui-symbol view-control'
|
||||
ng-click="toggle.toggle(); controller.trackExpansion()"
|
||||
ng-if="model.composition !== undefined"
|
||||
>
|
||||
{{toggle.isActive() ? "v" : ">"}}
|
||||
</span->
|
||||
</span-->
|
||||
</div>
|
||||
</span>
|
||||
57
platform/search/res/templates/search-view.html
Normal file
57
platform/search/res/templates/search-view.html
Normal file
@@ -0,0 +1,57 @@
|
||||
<!--
|
||||
Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||
as represented by the Administrator of the National Aeronautics and Space
|
||||
Administration. All rights reserved.
|
||||
|
||||
Open MCT Web is licensed under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0.
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
License for the specific language governing permissions and limitations
|
||||
under the License.
|
||||
|
||||
Open MCT Web includes source code licensed under additional open source
|
||||
licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
this source code distribution or the Licensing information page available
|
||||
at runtime from the About dialog for additional information.
|
||||
-->
|
||||
|
||||
<div class="items-holder grid abs"
|
||||
ng-controller="SearchViewController as controller">
|
||||
|
||||
<!-- Search bar -->
|
||||
<div>
|
||||
<div style="height: 30px">Search:</div>
|
||||
<input type="text"
|
||||
id="searchinput"
|
||||
value=""
|
||||
ng-keyup="controller.search('searchinput')"
|
||||
style="width: 66%"/>
|
||||
</div>
|
||||
|
||||
<!-- some spacing -->
|
||||
<div style="height: 30px"></div>
|
||||
|
||||
<!-- Results list -->
|
||||
<div ng-if="controller.areResults()"
|
||||
style="height: 60px">
|
||||
<p>
|
||||
Results:
|
||||
</p>
|
||||
<div ng-if="controller.areMore()">
|
||||
<button ng-click="controller.loadMore()">
|
||||
Load more
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<mct-representation key="'grid-item'"
|
||||
ng-repeat="result in results"
|
||||
mct-object="result.object">
|
||||
</mct-representation>
|
||||
</div>
|
||||
</div>
|
||||
67
platform/search/res/templates/search.html
Normal file
67
platform/search/res/templates/search.html
Normal file
@@ -0,0 +1,67 @@
|
||||
<!--
|
||||
Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||
as represented by the Administrator of the National Aeronautics and Space
|
||||
Administration. All rights reserved.
|
||||
|
||||
Open MCT Web is licensed under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0.
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
License for the specific language governing permissions and limitations
|
||||
under the License.
|
||||
|
||||
Open MCT Web includes source code licensed under additional open source
|
||||
licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
this source code distribution or the Licensing information page available
|
||||
at runtime from the About dialog for additional information.
|
||||
-->
|
||||
<div class="search"
|
||||
ng-controller="SearchController as controller">
|
||||
|
||||
<!-- Search bar input -->
|
||||
<div>
|
||||
<input class="search-input"
|
||||
type="text"
|
||||
value=""
|
||||
ng-model="ngModel.input"
|
||||
ng-keyup="controller.search()" />
|
||||
<!--mct-control key="textfield"
|
||||
ng-model="ngModel"
|
||||
structure="{cssclass: 'search-input', size: '50px'}">
|
||||
</mct-control-->
|
||||
</div>
|
||||
|
||||
<!-- This div exists to determine scroll bar location -->
|
||||
<div class="search-scroll">
|
||||
|
||||
<!-- Results list -->
|
||||
<div class="results">
|
||||
<mct-representation key="'search-item'"
|
||||
ng-repeat="result in results"
|
||||
mct-object="result.object"
|
||||
ng-model="ngModel">
|
||||
</mct-representation>
|
||||
</div>
|
||||
|
||||
<!-- Loading icon -->
|
||||
<div class="load-icon"
|
||||
ng-class="{loading: controller.isLoading()}"
|
||||
ng-if="controller.isLoading()">
|
||||
<span class="icon wait-spinner"></span>
|
||||
<span class="title-label">Loading...</span>
|
||||
</div>
|
||||
|
||||
<!-- Load more button -->
|
||||
<div ng-if="controller.areMore()">
|
||||
<button class="load-more-button btn very-subtle"
|
||||
ng-click="controller.loadMore()">
|
||||
Load more
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
152
platform/search/src/SearchAggregator.js
Normal file
152
platform/search/src/SearchAggregator.js
Normal file
@@ -0,0 +1,152 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT Web includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
/*global define*/
|
||||
|
||||
/**
|
||||
* Module defining SearchAggregator. Created by shale on 07/16/2015.
|
||||
*/
|
||||
define(
|
||||
[],
|
||||
function () {
|
||||
"use strict";
|
||||
|
||||
var DEFUALT_TIMEOUT = 1000,
|
||||
DEFAULT_MAX_RESULTS = 100;
|
||||
|
||||
/**
|
||||
* Allows multiple services which provide search functionality
|
||||
* to be treated as one.
|
||||
*
|
||||
* @constructor
|
||||
* @param $q Angular's $q, for promise consolidation
|
||||
* @param {SearchProvider[]} providers the search providers to be
|
||||
* aggregated
|
||||
*/
|
||||
function SearchAggregator($q, providers) {
|
||||
var loading;
|
||||
|
||||
// Remove duplicate objects that have the same ID. Modifies the passed
|
||||
// array, and returns the number that were removed.
|
||||
function filterDuplicates(results, total) {
|
||||
var ids = [],
|
||||
numRemoved = 0,
|
||||
i;
|
||||
|
||||
for (i = 0; i < results.length; i += 1) {
|
||||
if (ids.indexOf(results[i].id) !== -1) {
|
||||
// If this result's ID is already there, remove the object
|
||||
results.splice(i, 1);
|
||||
numRemoved += 1;
|
||||
|
||||
// Reduce loop index because we shortened the array
|
||||
i -= 1;
|
||||
} else {
|
||||
// Otherwise add the ID to the list of the ones we have seen
|
||||
ids.push(results[i].id);
|
||||
}
|
||||
}
|
||||
|
||||
return numRemoved;
|
||||
}
|
||||
|
||||
// Order the objects from highest to lowest score in the array.
|
||||
// Modifies the passed array, as well as returns the modified array.
|
||||
function orderByScore(results) {
|
||||
results.sort(function (a, b) {
|
||||
if (a.score > b.score) {
|
||||
return -1;
|
||||
} else if (b.score > a.score) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
return results;
|
||||
}
|
||||
|
||||
// For documentation, see sendQuery below.
|
||||
function queryAll(inputText) {
|
||||
var i,
|
||||
timestamp = Date.now(),
|
||||
resultPromises = [];
|
||||
|
||||
// We are loading
|
||||
loading = true;
|
||||
|
||||
// Send the query to all the providers
|
||||
for (i = 0; i < providers.length; i += 1) {
|
||||
resultPromises.push(
|
||||
providers[i].query(inputText, timestamp, DEFAULT_MAX_RESULTS, DEFUALT_TIMEOUT)
|
||||
);
|
||||
}
|
||||
|
||||
// Get promises for results arrays
|
||||
return $q.all(resultPromises).then(function (resultObjects) {
|
||||
var results = [],
|
||||
totalSum = 0,
|
||||
i;
|
||||
|
||||
// Merge results
|
||||
for (i = 0; i < resultObjects.length; i += 1) {
|
||||
results = results.concat(resultObjects[i].hits);
|
||||
totalSum += resultObjects[i].total;
|
||||
}
|
||||
// Order by score first, so that when removing repeats we keep the higher scored ones
|
||||
orderByScore(results);
|
||||
totalSum -= filterDuplicates(results, totalSum);
|
||||
|
||||
// We are done loading
|
||||
loading = false;
|
||||
|
||||
return {
|
||||
hits: results,
|
||||
total: totalSum,
|
||||
timedOut: resultObjects.some(function (obj) {
|
||||
return obj.timedOut;
|
||||
})
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
/**
|
||||
* Sends a query to each of the providers. Returns a promise for
|
||||
* a result object that has the format
|
||||
* {hits: domainObject[], total: number}
|
||||
*
|
||||
* @param inputText The text input that is the query.
|
||||
*/
|
||||
query: queryAll,
|
||||
|
||||
/**
|
||||
* Checks to see if we are still waiting for the results to be
|
||||
* fully updated.
|
||||
*/
|
||||
isLoading: function () {
|
||||
return loading;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return SearchAggregator;
|
||||
}
|
||||
);
|
||||
94
platform/search/src/controllers/SearchController.js
Normal file
94
platform/search/src/controllers/SearchController.js
Normal file
@@ -0,0 +1,94 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT Web includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
/*global define*/
|
||||
|
||||
/**
|
||||
* Module defining SearchController. Created by shale on 07/15/2015.
|
||||
*/
|
||||
define(function () {
|
||||
"use strict";
|
||||
|
||||
var INITIAL_LOAD_NUMBER = 20,
|
||||
LOAD_INCREMENT = 5;
|
||||
|
||||
function SearchController($scope, searchService) {
|
||||
// Starting amount of results to load. Will get increased.
|
||||
var numResults = INITIAL_LOAD_NUMBER,
|
||||
fullResults = [];
|
||||
|
||||
function search() {
|
||||
var inputText = $scope.ngModel.input;
|
||||
|
||||
// Update whether the file tree should be displayed
|
||||
if (inputText === '' || inputText === undefined) {
|
||||
$scope.ngModel.search = false;
|
||||
} else {
|
||||
$scope.ngModel.search = true;
|
||||
}
|
||||
|
||||
// Reset 'load more'
|
||||
numResults = INITIAL_LOAD_NUMBER;
|
||||
|
||||
// Send the query
|
||||
searchService.query(inputText).then(function (result) {
|
||||
fullResults = result.hits;
|
||||
$scope.results = result.hits.slice(0, numResults);
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
/**
|
||||
* Search the filetree.
|
||||
* Assumes that any search text will be in ngModel.input
|
||||
*/
|
||||
search: search,
|
||||
|
||||
/**
|
||||
* Checks to see if we are still waiting for the results to be
|
||||
* fully updated.
|
||||
*/
|
||||
isLoading: function () {
|
||||
return searchService.isLoading();
|
||||
},
|
||||
|
||||
/**
|
||||
* Checks to see if there are more search results to display.
|
||||
*/
|
||||
areMore: function () {
|
||||
return numResults < fullResults.length;
|
||||
// TODO: See loadMore() todo.
|
||||
},
|
||||
|
||||
/**
|
||||
* Increases the number of search results to display, and then
|
||||
* load them.
|
||||
*/
|
||||
loadMore: function () {
|
||||
numResults += LOAD_INCREMENT;
|
||||
$scope.results = fullResults.slice(0, numResults);
|
||||
// TODO: Let load more see if total > fullResults.length, and then
|
||||
// if so, resend a query.
|
||||
}
|
||||
};
|
||||
}
|
||||
return SearchController;
|
||||
});
|
||||
60
platform/search/src/controllers/SearchItemController.js
Normal file
60
platform/search/src/controllers/SearchItemController.js
Normal file
@@ -0,0 +1,60 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT Web includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
/*global define*/
|
||||
|
||||
/**
|
||||
* Module defining SearchItemController. Created by shale on 07/22/2015.
|
||||
*/
|
||||
define(function () {
|
||||
"use strict";
|
||||
|
||||
function SearchItemController($scope) {
|
||||
var selectedObject = ($scope.ngModel || {}).selectedObject;
|
||||
|
||||
// Callback for the selection updates; track the currently
|
||||
// navigated object and update display parameters as needed.
|
||||
function setSelection(object) {
|
||||
selectedObject = object;
|
||||
}
|
||||
|
||||
// Listen for changes which will effect display parameters
|
||||
$scope.$watch("ngModel.selectedObject", setSelection);
|
||||
|
||||
return {
|
||||
/**
|
||||
* Check whether or not the domain object represented by
|
||||
* this search item should be highlighted.
|
||||
* An object will be highlighted if its ID matches
|
||||
* ngModel.selectedObject
|
||||
*
|
||||
* @returns true if this should be highlighted
|
||||
*/
|
||||
isSelected: function () {
|
||||
// If this object is the same as the model's selected object
|
||||
// Same being them having the same ID (this allows different
|
||||
// instances of the same thing to be recognized as the same)
|
||||
return $scope.ngModel.selectedObject.getId() === $scope.domainObject.getId();
|
||||
}
|
||||
};
|
||||
}
|
||||
return SearchItemController;
|
||||
});
|
||||
109
platform/search/src/controllers/SearchViewController.js
Normal file
109
platform/search/src/controllers/SearchViewController.js
Normal file
@@ -0,0 +1,109 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT Web includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
/*global define*/
|
||||
|
||||
/**
|
||||
* Module defining SearchViewController. Created by shale on 07/08/2015.
|
||||
*/
|
||||
define(function () {
|
||||
"use strict";
|
||||
|
||||
var INITIAL_LOAD_NUMBER = 20,
|
||||
LOAD_INCREMENT = 5;
|
||||
|
||||
function SearchViewController($scope, $timeout, searchService) {
|
||||
// Starting amount of results to load. Will get increased.
|
||||
var numResults = INITIAL_LOAD_NUMBER;
|
||||
|
||||
function update(timestamp) {
|
||||
// Get the results
|
||||
$scope.results = searchService.getLatestResults(0, numResults);
|
||||
|
||||
// Check to make sure that these results are the latest ones
|
||||
function waitForLatest() {
|
||||
var timestamps = searchService.getLatestTimestamps(),
|
||||
areOld = timestamps.some(function (c) {return c < timestamp; });
|
||||
// If any of the timestamps are older than the one we made the query with
|
||||
if (areOld) {
|
||||
// Then wait and try to update again
|
||||
searchService.updateResults();
|
||||
$timeout(waitForLatest, 100);
|
||||
} else {
|
||||
// We got the latest results now
|
||||
$scope.results = searchService.getLatestResults(0, numResults);
|
||||
}
|
||||
}
|
||||
waitForLatest();
|
||||
}
|
||||
|
||||
function search(inputID) {
|
||||
var date = new Date(),
|
||||
timestamp = date.getTime();
|
||||
|
||||
// Reset 'load more'
|
||||
numResults = INITIAL_LOAD_NUMBER;
|
||||
|
||||
// Send the query
|
||||
searchService.sendQuery(inputID, timestamp);
|
||||
|
||||
update(timestamp);
|
||||
}
|
||||
|
||||
return {
|
||||
/**
|
||||
* Search the filetree.
|
||||
*
|
||||
* @param inputID The name of the ID property of the html text
|
||||
* input where this funcion should find the search term.
|
||||
*/
|
||||
search: search,
|
||||
|
||||
/**
|
||||
* Checks to see if there are any search results to display.
|
||||
*/
|
||||
areResults: function () {
|
||||
if ($scope.results) {
|
||||
return $scope.results.length > 0;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Checks to see if there are more search results to display.
|
||||
*/
|
||||
areMore: function () {
|
||||
return numResults < searchService.getNumResults();
|
||||
},
|
||||
|
||||
/**
|
||||
* Increases the number of search results to display, and then
|
||||
* load them.
|
||||
*/
|
||||
loadMore: function () {
|
||||
numResults += LOAD_INCREMENT;
|
||||
update();
|
||||
}
|
||||
};
|
||||
}
|
||||
return SearchViewController;
|
||||
});
|
||||
212
platform/search/src/providers/ElasticsearchSearchProvider.js
Normal file
212
platform/search/src/providers/ElasticsearchSearchProvider.js
Normal file
@@ -0,0 +1,212 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT Web includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
/*global define*/
|
||||
|
||||
/**
|
||||
* Module defining ElasticsearchSearchProvider. Created by shale on 07/16/2015.
|
||||
*/
|
||||
define(
|
||||
[],
|
||||
function () {
|
||||
"use strict";
|
||||
|
||||
// JSLint doesn't like underscore-prefixed properties,
|
||||
// so hide them here.
|
||||
var ID = "_id",
|
||||
SCORE = "_score",
|
||||
DEFAULT_MAX_RESULTS = 100;
|
||||
|
||||
/**
|
||||
* A search service which searches through domain objects in
|
||||
* the filetree using ElasticSearch.
|
||||
*
|
||||
* @constructor
|
||||
* @param $http Angular's $http service, for working with urls.
|
||||
* @param {ObjectService} objectService the service from which
|
||||
* domain objects can be gotten.
|
||||
* @param ROOT the constant ELASTIC_ROOT which allows us to
|
||||
* interact with ElasticSearch.
|
||||
*/
|
||||
function ElasticsearchSearchProvider($http, objectService, ROOT) {
|
||||
|
||||
// Add the fuzziness operator to the search term
|
||||
function addFuzziness(searchTerm, editDistance) {
|
||||
if (!editDistance) {
|
||||
editDistance = '';
|
||||
}
|
||||
|
||||
return searchTerm.split(' ').map(function (s) {
|
||||
if (s.indexOf('"') !== -1) {
|
||||
return s;
|
||||
} else {
|
||||
return s + '~' + editDistance;
|
||||
}
|
||||
}).join(' ');
|
||||
}
|
||||
|
||||
// Currently specific to elasticsearch
|
||||
function processSearchTerm(searchTerm) {
|
||||
var spaceIndex;
|
||||
|
||||
// Cut out any extra spaces
|
||||
while (searchTerm.substr(0, 1) === ' ') {
|
||||
searchTerm = searchTerm.substring(1, searchTerm.length);
|
||||
}
|
||||
while (searchTerm.substr(searchTerm.length - 1, 1) === ' ') {
|
||||
searchTerm = searchTerm.substring(0, searchTerm.length - 1);
|
||||
}
|
||||
spaceIndex = searchTerm.indexOf(' ');
|
||||
while (spaceIndex !== -1) {
|
||||
searchTerm = searchTerm.substring(0, spaceIndex) +
|
||||
searchTerm.substring(spaceIndex + 1, searchTerm.length);
|
||||
spaceIndex = searchTerm.indexOf(' ');
|
||||
}
|
||||
|
||||
// Add fuzziness for completeness
|
||||
searchTerm = addFuzziness(searchTerm);
|
||||
|
||||
//console.log('search term ', searchTerm);
|
||||
return searchTerm;
|
||||
}
|
||||
|
||||
// Processes results from the format that elasticsearch returns to
|
||||
// a list of search result objects (that contain domain objects), then
|
||||
// returns an object in the format {hits: searchResult[], total: number}
|
||||
function processResults(rawResults, timestamp) {
|
||||
var results = rawResults.data.hits.hits,
|
||||
resultsLength = results.length,
|
||||
ids = [],
|
||||
scores = {},
|
||||
searchResults = [],
|
||||
i;
|
||||
|
||||
// Get the result objects' IDs
|
||||
for (i = 0; i < resultsLength; i += 1) {
|
||||
ids.push(results[i][ID]);
|
||||
}
|
||||
|
||||
// Get the result objects' scores
|
||||
for (i = 0; i < resultsLength; i += 1) {
|
||||
scores[ids[i]] = results[i][SCORE];
|
||||
}
|
||||
|
||||
// Get the domain objects from their IDs
|
||||
return objectService.getObjects(ids).then(function (objects) {
|
||||
var j,
|
||||
id;
|
||||
|
||||
for (j = 0; j < resultsLength; j += 1) {
|
||||
id = ids[j];
|
||||
|
||||
// Include items we can get models for
|
||||
if (objects[id].getModel) {
|
||||
// Format the results as searchResult objects
|
||||
searchResults.push({
|
||||
id: id,
|
||||
object: objects[id],
|
||||
score: scores[id]
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
hits: searchResults,
|
||||
total: rawResults.data.hits.total,
|
||||
timedOut: rawResults.data.timed_out
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
// For documentation, see query below.
|
||||
function query(searchTerm, timestamp, maxResults, timeout) {
|
||||
var esQuery;
|
||||
|
||||
// Check to see if the user provided a maximum
|
||||
// number of results to display
|
||||
if (!maxResults) {
|
||||
// Else, we provide a default value.
|
||||
maxResults = DEFAULT_MAX_RESULTS;
|
||||
}
|
||||
|
||||
// If the user input is empty, we want to have no search results.
|
||||
if (searchTerm !== '') {
|
||||
// Process the search term
|
||||
searchTerm = processSearchTerm(searchTerm);
|
||||
|
||||
// Create the query to elasticsearch
|
||||
esQuery = ROOT + "/_search/?q=" + searchTerm +
|
||||
"&size=" + maxResults;
|
||||
if (timeout) {
|
||||
esQuery += "&timeout=" + timeout;
|
||||
}
|
||||
|
||||
// Get the data...
|
||||
return $http({
|
||||
method: "GET",
|
||||
url: esQuery
|
||||
}).then(function (rawResults) {
|
||||
// ...then process the data
|
||||
return processResults(rawResults, timestamp);
|
||||
})['catch'](function (err) {
|
||||
// In case of error, return nothing. (To prevent
|
||||
// infinite loading time.)
|
||||
return {hits: [], total: 0};
|
||||
});
|
||||
} else {
|
||||
return {hits: [], total: 0};
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
/**
|
||||
* Searches through the filetree for domain objects using a search
|
||||
* term. This is done through querying elasticsearch. Returns a
|
||||
* promise for a result object that has the format
|
||||
* {hits: searchResult[], total: number, timedOut: boolean}
|
||||
* where a searchResult has the format
|
||||
* {id: domainObject ID, object: domainObject, score: number}
|
||||
*
|
||||
* Notes:
|
||||
* * The order of the results is from highest to lowest score,
|
||||
* as elsaticsearch determines them to be.
|
||||
* * Uses the fuzziness operator to get more results.
|
||||
* * More about this search's behavior at
|
||||
* https://www.elastic.co/guide/en/elasticsearch/reference/current/search-uri-request.html
|
||||
*
|
||||
* @param searchTerm The text input that is the query.
|
||||
* @param timestamp The time at which this function was called.
|
||||
* This timestamp is used as a unique identifier for this
|
||||
* query and the corresponding results.
|
||||
* @param maxResults (optional) The maximum number of results
|
||||
* that this function should return.
|
||||
* @param timeout (optional) The time after which the search should
|
||||
* stop calculations and return partial results. Elasticsearch
|
||||
* does not guarentee that this timeout will be strictly followed.
|
||||
*/
|
||||
query: query
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
return ElasticsearchSearchProvider;
|
||||
}
|
||||
);
|
||||
236
platform/search/src/providers/GenericSearchProvider.js
Normal file
236
platform/search/src/providers/GenericSearchProvider.js
Normal file
@@ -0,0 +1,236 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT Web includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
/*global define*/
|
||||
|
||||
/**
|
||||
* Module defining GenericSearchProvider. Created by shale on 07/16/2015.
|
||||
*/
|
||||
define(
|
||||
[],
|
||||
function () {
|
||||
"use strict";
|
||||
|
||||
var DEFAULT_MAX_RESULTS = 100,
|
||||
DEFAULT_TIMEOUT = 1000,
|
||||
stopTime;
|
||||
|
||||
/**
|
||||
* A search service which searches through domain objects in
|
||||
* the filetree without using external search implementations.
|
||||
*
|
||||
* @constructor
|
||||
* @param $q
|
||||
* @param {ObjectService} objectService the service from which
|
||||
* domain objects can be gotten.
|
||||
* @param {WorkerService} workerService the service which allows
|
||||
* more easy creation of web workers.
|
||||
* @param {roots[]} roots an array of all the root domain objects.
|
||||
*/
|
||||
function GenericSearchProvider($q, objectService, workerService, roots) {
|
||||
var worker = workerService.run('genericSearchWorker'),
|
||||
pendingQueries = {};
|
||||
// pendingQueries is a dictionary with the key value pairs st
|
||||
// the key is the timestamp and the value is the promise
|
||||
|
||||
// Tell the web worker to add a domain object's model to its list of items.
|
||||
function indexItem(domainObject) {
|
||||
var message;
|
||||
|
||||
// undefined check
|
||||
if (domainObject && domainObject.getModel) {
|
||||
// Using model instead of whole domain object because
|
||||
// it's a JSON object.
|
||||
message = {
|
||||
request: 'index',
|
||||
model: domainObject.getModel(),
|
||||
id: domainObject.getId()
|
||||
};
|
||||
worker.postMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
// Tell the worker to search for items it has that match this searchInput.
|
||||
// Takes the searchInput, as well as a max number of results (will return
|
||||
// less than that if there are fewer matches).
|
||||
function workerSearch(searchInput, maxResults, timestamp, timeout) {
|
||||
var message = {
|
||||
request: 'search',
|
||||
input: searchInput,
|
||||
maxNumber: maxResults,
|
||||
timestamp: timestamp,
|
||||
timeout: timeout
|
||||
};
|
||||
worker.postMessage(message);
|
||||
}
|
||||
|
||||
function handleResponse(event) {
|
||||
var ids = [],
|
||||
id;
|
||||
|
||||
// If we have the results from a search
|
||||
if (event.data.request === 'search') {
|
||||
// Convert the ids given from the web worker into domain objects
|
||||
for (id in event.data.results) {
|
||||
ids.push(id);
|
||||
}
|
||||
objectService.getObjects(ids).then(function (objects) {
|
||||
var searchResults = [],
|
||||
id;
|
||||
|
||||
// Reset and repopulate the latest results
|
||||
for (id in objects) {
|
||||
searchResults.push({
|
||||
object: objects[id],
|
||||
id: id,
|
||||
score: event.data.results[id]
|
||||
});
|
||||
}
|
||||
|
||||
// Resove the promise corresponding to this
|
||||
pendingQueries[event.data.timestamp].resolve(
|
||||
{
|
||||
hits: searchResults,
|
||||
total: event.data.total,
|
||||
timedOut: event.data.timedOut
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
worker.onmessage = handleResponse;
|
||||
|
||||
// Recursive helper function for getItems()
|
||||
function itemsHelper(children, i) {
|
||||
// Index the current node
|
||||
indexItem(children[i]);
|
||||
|
||||
if (i >= children.length) {
|
||||
// Done!
|
||||
return children;
|
||||
} else if (children[i].hasCapability('composition')) {
|
||||
// This child has children
|
||||
return children[i].getCapability('composition').invoke().then(function (grandchildren) {
|
||||
// Add grandchildren to the end of the list
|
||||
// They will also be checked for composition
|
||||
return itemsHelper(children.concat(grandchildren), i + 1);
|
||||
});
|
||||
} else {
|
||||
// This child is a leaf
|
||||
return itemsHelper(children, i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Converts the filetree into a list
|
||||
function getItems(timeout) {
|
||||
var rootIds = [],
|
||||
i;
|
||||
for (i = 0; i < roots.length; i += 1) {
|
||||
rootIds.push(roots[i].id);
|
||||
}
|
||||
|
||||
// Aquire root objects
|
||||
objectService.getObjects(rootIds).then(function (objectsById) {
|
||||
var objects = [],
|
||||
id;
|
||||
|
||||
// Get each of the objects in objectsById
|
||||
for (id in objectsById) {
|
||||
objects.push(objectsById[id]);
|
||||
}
|
||||
|
||||
// Index all of the roots' descendents
|
||||
itemsHelper(objects, 0);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// For documentation, see query below.
|
||||
function query(input, timestamp, maxResults, timeout) {
|
||||
var terms = [],
|
||||
searchResults = [],
|
||||
defer = $q.defer();
|
||||
|
||||
pendingQueries[timestamp] = defer;
|
||||
|
||||
// Check to see if the user provided a maximum
|
||||
// number of results to display
|
||||
if (!maxResults) {
|
||||
// Else, we provide a default value.
|
||||
maxResults = DEFAULT_MAX_RESULTS;
|
||||
}
|
||||
// Similarly, check if timeout was provided
|
||||
if (!timeout) {
|
||||
timeout = DEFAULT_TIMEOUT;
|
||||
}
|
||||
|
||||
// Instead, assume that the items have already been indexed, and
|
||||
// just send the query to the worker.
|
||||
workerSearch(input, maxResults, timestamp, timeout);
|
||||
|
||||
return defer.promise;
|
||||
}
|
||||
|
||||
// Index the tree's contents once at the beginning
|
||||
getItems();
|
||||
// TODO: Is this a good assumption that the tree's contents will not
|
||||
// change often enough?
|
||||
// TODO: This makes the timeout parameter that query takes
|
||||
// useless. See if timing out worker is an idea that works.
|
||||
|
||||
|
||||
return {
|
||||
/**
|
||||
* Searches through the filetree for domain objects which match
|
||||
* the search term. This function is to be used as a fallback
|
||||
* in the case where other search services are not avaliable.
|
||||
* Returns a promise for a result object that has the format
|
||||
* {hits: searchResult[], total: number, timedOut: boolean}
|
||||
* where a searchResult has the format
|
||||
* {id: domainObject ID, object: domainObject, score: number}
|
||||
*
|
||||
* Notes:
|
||||
* * The order of the results is not guarenteed.
|
||||
* * A domain object qualifies as a match for a search input if
|
||||
* the object's name property contains any of the search terms
|
||||
* (which are generated by splitting the input at spaces).
|
||||
* * Scores are higher for matches that have more than one of
|
||||
* the terms as substrings.
|
||||
*
|
||||
* @param input The text input that is the query.
|
||||
* @param timestamp The time at which this function was called.
|
||||
* This timestamp is used as a unique identifier for this
|
||||
* query and the corresponding results.
|
||||
* @param maxResults (optional) The maximum number of results
|
||||
* that this function should return.
|
||||
* @param timeout (optional) The time after which the search should
|
||||
* stop calculations and return partial results.
|
||||
*/
|
||||
query: query
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
return GenericSearchProvider;
|
||||
}
|
||||
);
|
||||
187
platform/search/src/workers/GenericSearchWorker.js
Normal file
187
platform/search/src/workers/GenericSearchWorker.js
Normal file
@@ -0,0 +1,187 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT Web includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
/*global self*/
|
||||
|
||||
/**
|
||||
* Module defining GenericSearchWorker. Created by shale on 07/21/2015.
|
||||
*/
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
// An array of objects composed of domain object IDs and models
|
||||
// {id: domainObject's ID, model: domainObject's model}
|
||||
var indexedItems = [];
|
||||
|
||||
// Helper function for index()
|
||||
function conainsItem(id) {
|
||||
var i;
|
||||
for (i = 0; i < indexedItems.length; i += 1) {
|
||||
if (indexedItems[i].id === id) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indexes an item to indexedItems.
|
||||
*
|
||||
* @param data An object which contains:
|
||||
* * model: The model of the domain object
|
||||
* * id: The ID of the domain object
|
||||
*/
|
||||
function index(data) {
|
||||
var message;
|
||||
|
||||
if (!conainsItem(data.id)) {
|
||||
indexedItems.push({
|
||||
id: data.id,
|
||||
model: data.model
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function for serach()
|
||||
function convertToTerms(input) {
|
||||
var terms = input;
|
||||
// Shave any spaces off of the ends of the input
|
||||
while (terms.substr(0, 1) === ' ') {
|
||||
terms = terms.substring(1, terms.length);
|
||||
}
|
||||
while (terms.substr(terms.length - 1, 1) === ' ') {
|
||||
terms = terms.substring(0, terms.length - 1);
|
||||
}
|
||||
|
||||
// Then split it at spaces and asterisks
|
||||
terms = terms.split(/ |\*/);
|
||||
|
||||
// Remove any empty strings from the terms
|
||||
while (terms.indexOf('') !== -1) {
|
||||
terms.splice(terms.indexOf(''), 1);
|
||||
}
|
||||
|
||||
return terms;
|
||||
}
|
||||
|
||||
// Helper function for search()
|
||||
function scoreItem(item, input, terms) {
|
||||
var name = item.model.name.toLocaleLowerCase(),
|
||||
weight = 0.65,
|
||||
score = 0.0,
|
||||
i;
|
||||
|
||||
// Make the score really big if the item name and
|
||||
// the original search input are the same
|
||||
if (name === input) {
|
||||
score = 42;
|
||||
}
|
||||
|
||||
for (i = 0; i < terms.length; i += 1) {
|
||||
// Increase the score if the term is in the item name
|
||||
if (name.indexOf(terms[i]) !== -1) {
|
||||
score += 1;
|
||||
|
||||
// Add extra to the score if the search term exists
|
||||
// as its own term within the items
|
||||
// TODO: This may be undesired
|
||||
if (name.split(' ').indexOf(terms[i]) !== -1) {
|
||||
score += 0.5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return score * weight;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets search results from the indexedItems based on provided search
|
||||
* input. Returns matching results from indexedItems, as well as the
|
||||
* timestamp that was passed to it.
|
||||
*
|
||||
* @param data An object which contains:
|
||||
* * input: The original string which we are searching with
|
||||
* * maxNumber: The maximum number of search results desired
|
||||
* * timestamp: The time identifier from when the query was made
|
||||
*/
|
||||
function search(data) {
|
||||
// This results 'dictionary' will have domain object ID keys which
|
||||
// point to the domain object's score. (The score is wrt only this
|
||||
// specific search input.)
|
||||
var results = {},
|
||||
input = data.input.toLocaleLowerCase(),
|
||||
terms = convertToTerms(input),
|
||||
i,
|
||||
id,
|
||||
score,
|
||||
message = {
|
||||
request: 'search',
|
||||
results: {},
|
||||
total: 0,
|
||||
timestamp: data.timestamp, // TODO: This may be no longer necissary
|
||||
timedOut: false
|
||||
};
|
||||
|
||||
// If the user input is empty, we want to have no search results.
|
||||
if (input !== '') {
|
||||
for (i = 0; i < indexedItems.length; i += 1) {
|
||||
// If this is taking too long, then stop
|
||||
if (Date.now() > data.timestamp + data.timeout) {
|
||||
message.timedOut = true;
|
||||
break;
|
||||
}
|
||||
|
||||
score = scoreItem(indexedItems[i], input, terms);
|
||||
if (score > 0) {
|
||||
results[indexedItems[i].id] = score;
|
||||
message.total += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Truncate results if there are more than maxResults
|
||||
if (message.total > data.maxResults) {
|
||||
i = 0;
|
||||
for (id in results) {
|
||||
message.results[id] = results[id];
|
||||
i += 1;
|
||||
if (i >= data.maxResults) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// TODO: This seems inefficient.
|
||||
} else {
|
||||
message.results = results;
|
||||
}
|
||||
|
||||
return message;
|
||||
|
||||
// TODO: This function is too long.
|
||||
}
|
||||
|
||||
self.onmessage = function (event) {
|
||||
if (event.data.request === 'index') {
|
||||
index(event.data);
|
||||
} else if (event.data.request === 'search') {
|
||||
self.postMessage(search(event.data));
|
||||
}
|
||||
};
|
||||
}());
|
||||
113
platform/search/test/SearchAggregatorSpec.js
Normal file
113
platform/search/test/SearchAggregatorSpec.js
Normal file
@@ -0,0 +1,113 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT Web includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
/*global define,describe,it,expect,beforeEach,jasmine*/
|
||||
|
||||
/**
|
||||
* SearchSpec. Created by shale on 07/31/2015.
|
||||
*/
|
||||
define(
|
||||
["../src/SearchAggregator"],
|
||||
function (SearchAggregator) {
|
||||
"use strict";
|
||||
|
||||
describe("The search aggregator ", function () {
|
||||
var mockQ,
|
||||
mockPromise,
|
||||
mockProviders = [],
|
||||
aggregator,
|
||||
mockProviderResults = [],
|
||||
mockAggregatorResults,
|
||||
i;
|
||||
|
||||
beforeEach(function () {
|
||||
mockQ = jasmine.createSpyObj(
|
||||
"$q",
|
||||
[ "all" ]
|
||||
);
|
||||
mockPromise = jasmine.createSpyObj(
|
||||
"promise",
|
||||
[ "then" ]
|
||||
);
|
||||
for (i = 0; i < 3; i += 1) {
|
||||
mockProviders.push(
|
||||
jasmine.createSpyObj(
|
||||
"mockProvider" + i,
|
||||
[ "query" ]
|
||||
)
|
||||
);
|
||||
mockProviders[i].query.andReturn(mockPromise);
|
||||
}
|
||||
mockQ.all.andReturn(mockPromise);
|
||||
|
||||
aggregator = new SearchAggregator(mockQ, mockProviders);
|
||||
aggregator.query();
|
||||
|
||||
for (i = 0; i < mockProviders.length; i += 1) {
|
||||
mockProviderResults.push({
|
||||
hits: [
|
||||
{
|
||||
id: i,
|
||||
score: 42 - i
|
||||
},
|
||||
{
|
||||
id: i + 1,
|
||||
score: 42 - (2 * i)
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
mockAggregatorResults = mockPromise.then.mostRecentCall.args[0](mockProviderResults);
|
||||
});
|
||||
|
||||
it("sends queries to all providers", function () {
|
||||
for (i = 0; i < mockProviders.length; i += 1) {
|
||||
expect(mockProviders[i].query).toHaveBeenCalled();
|
||||
}
|
||||
});
|
||||
|
||||
it("filters out duplicate objects", function () {
|
||||
expect(mockAggregatorResults.hits.length).toEqual(mockProviders.length + 1);
|
||||
expect(mockAggregatorResults.total).not.toBeLessThan(mockAggregatorResults.hits.length);
|
||||
});
|
||||
|
||||
it("orders results by score", function () {
|
||||
for (i = 1; i < mockAggregatorResults.hits.length; i += 1) {
|
||||
expect(mockAggregatorResults.hits[i].score)
|
||||
.not.toBeGreaterThan(mockAggregatorResults.hits[i - 1].score);
|
||||
}
|
||||
});
|
||||
|
||||
it("is loading until all the providers' promises fufill", function () {
|
||||
expect(aggregator.isLoading()).toBeFalsy();
|
||||
|
||||
// Send query
|
||||
aggregator.query();
|
||||
expect(aggregator.isLoading()).toBeTruthy();
|
||||
|
||||
// Then resolve the promises
|
||||
mockAggregatorResults = mockPromise.then.mostRecentCall.args[0]([]);
|
||||
expect(aggregator.isLoading()).toBeFalsy();
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
);
|
||||
119
platform/search/test/controllers/SearchControllerSpec.js
Normal file
119
platform/search/test/controllers/SearchControllerSpec.js
Normal file
@@ -0,0 +1,119 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT Web includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
/*global define,describe,it,expect,beforeEach,jasmine*/
|
||||
|
||||
/**
|
||||
* SearchSpec. Created by shale on 07/31/2015.
|
||||
*/
|
||||
define(
|
||||
["../../src/controllers/SearchController"],
|
||||
function (SearchController) {
|
||||
"use strict";
|
||||
|
||||
describe("The search controller", function () {
|
||||
var mockScope,
|
||||
mockSearchService,
|
||||
mockPromise,
|
||||
controller;
|
||||
|
||||
function bigArray(size) {
|
||||
var array = [],
|
||||
i;
|
||||
for (i = 0; i < size; i += 1) {
|
||||
array.push(i);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
|
||||
beforeEach(function () {
|
||||
mockScope = jasmine.createSpyObj(
|
||||
"$scope",
|
||||
[ "" ]
|
||||
);
|
||||
mockScope.ngModel = {};
|
||||
mockScope.ngModel.input = "test input";
|
||||
|
||||
mockSearchService = jasmine.createSpyObj(
|
||||
"searchService",
|
||||
[ "query", "isLoading" ]
|
||||
);
|
||||
mockPromise = jasmine.createSpyObj(
|
||||
"promise",
|
||||
[ "then" ]
|
||||
);
|
||||
mockSearchService.query.andReturn(mockPromise);
|
||||
|
||||
controller = new SearchController(mockScope, mockSearchService);
|
||||
controller.search();
|
||||
});
|
||||
|
||||
it("sends queries to the search service", function () {
|
||||
expect(mockSearchService.query).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("populates the results with results from the search service", function () {
|
||||
expect(mockPromise.then).toHaveBeenCalledWith(jasmine.any(Function));
|
||||
mockPromise.then.mostRecentCall.args[0]({hits: []});
|
||||
|
||||
expect(mockScope.results).toBeDefined();
|
||||
});
|
||||
|
||||
it("checks if the search service is loading", function () {
|
||||
controller.isLoading();
|
||||
expect(mockSearchService.isLoading).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("displays only some results when there are many", function () {
|
||||
expect(mockPromise.then).toHaveBeenCalledWith(jasmine.any(Function));
|
||||
mockPromise.then.mostRecentCall.args[0]({hits: bigArray(100)});
|
||||
|
||||
expect(mockScope.results).toBeDefined();
|
||||
expect(mockScope.results.length).toBeLessThan(100);
|
||||
});
|
||||
|
||||
it("can load more results", function () {
|
||||
var oldSize;
|
||||
|
||||
expect(mockPromise.then).toHaveBeenCalledWith(jasmine.any(Function));
|
||||
mockPromise.then.mostRecentCall.args[0]({hits: bigArray(100)});
|
||||
oldSize = mockScope.results.length;
|
||||
|
||||
// If this doesn't pass, need to make the big array bigger
|
||||
expect(controller.areMore()).toBeTruthy();
|
||||
|
||||
controller.loadMore();
|
||||
expect(mockScope.results.length).toBeGreaterThan(oldSize);
|
||||
});
|
||||
|
||||
it("sets the ngModel.search flag", function () {
|
||||
// Flag should be true with nonempty input
|
||||
expect(mockScope.ngModel.search).toEqual(true);
|
||||
|
||||
// Flag should be flase with empty input
|
||||
mockScope.ngModel.input = "";
|
||||
controller.search();
|
||||
expect(mockScope.ngModel.search).toEqual(false);
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
72
platform/search/test/controllers/SearchItemControllerSpec.js
Normal file
72
platform/search/test/controllers/SearchItemControllerSpec.js
Normal file
@@ -0,0 +1,72 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT Web includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
/*global define,describe,it,expect,beforeEach,jasmine*/
|
||||
|
||||
/**
|
||||
* SearchSpec. Created by shale on 07/31/2015.
|
||||
*/
|
||||
define(
|
||||
["../../src/controllers/SearchItemController"],
|
||||
function (SearchItemController) {
|
||||
"use strict";
|
||||
|
||||
describe("The search item controller", function () {
|
||||
var mockScope,
|
||||
mockDomainObject1,
|
||||
mockDomainObject2,
|
||||
controller;
|
||||
|
||||
beforeEach(function () {
|
||||
mockScope = jasmine.createSpyObj(
|
||||
"$scope",
|
||||
[ "$watch" ]
|
||||
);
|
||||
mockDomainObject1 = jasmine.createSpyObj(
|
||||
"domainObject",
|
||||
[ "getId" ]
|
||||
);
|
||||
mockDomainObject1.getId.andReturn("1");
|
||||
mockDomainObject2 = jasmine.createSpyObj(
|
||||
"domainObject",
|
||||
[ "getId" ]
|
||||
);
|
||||
mockDomainObject2.getId.andReturn("2");
|
||||
|
||||
mockScope.ngModel = {};
|
||||
mockScope.ngModel.selectedObject = mockDomainObject1;
|
||||
mockScope.domainObject = mockDomainObject1;
|
||||
|
||||
controller = new SearchItemController(mockScope);
|
||||
});
|
||||
|
||||
it("keeps track of object selection", function () {
|
||||
expect(controller.isSelected()).toBeTruthy();
|
||||
|
||||
mockScope.ngModel.selectedObject = mockDomainObject2;
|
||||
expect(mockScope.$watch).toHaveBeenCalled();
|
||||
mockScope.$watch.mostRecentCall.args[1](mockDomainObject2);
|
||||
expect(controller.isSelected()).toBeFalsy();
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
);
|
||||
@@ -0,0 +1,115 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT Web includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
/*global define,describe,it,expect,beforeEach,jasmine*/
|
||||
|
||||
/**
|
||||
* SearchSpec. Created by shale on 07/31/2015.
|
||||
*/
|
||||
define(
|
||||
["../../src/providers/ElasticsearchSearchProvider"],
|
||||
function (ElasticsearchSearchProvider) {
|
||||
"use strict";
|
||||
|
||||
// JSLint doesn't like underscore-prefixed properties,
|
||||
// so hide them here.
|
||||
var ID = "_id",
|
||||
SCORE = "_score";
|
||||
|
||||
describe("The ElasticSearch search provider ", function () {
|
||||
var mockHttp,
|
||||
mockHttpPromise,
|
||||
mockObjectPromise,
|
||||
mockObjectService,
|
||||
mockDomainObject,
|
||||
provider,
|
||||
mockProviderResults;
|
||||
|
||||
beforeEach(function () {
|
||||
mockHttp = jasmine.createSpy("$http");
|
||||
mockHttpPromise = jasmine.createSpyObj(
|
||||
"promise",
|
||||
[ "then", "catch" ]
|
||||
);
|
||||
mockHttp.andReturn(mockHttpPromise);
|
||||
// allow chaining of promise.then().catch();
|
||||
mockHttpPromise.then.andReturn(mockHttpPromise);
|
||||
|
||||
mockObjectService = jasmine.createSpyObj(
|
||||
"objectService",
|
||||
[ "getObjects" ]
|
||||
);
|
||||
mockObjectPromise = jasmine.createSpyObj(
|
||||
"promise",
|
||||
[ "then", "catch" ]
|
||||
);
|
||||
mockObjectService.getObjects.andReturn(mockObjectPromise);
|
||||
|
||||
mockDomainObject = jasmine.createSpyObj(
|
||||
"domainObject",
|
||||
[ "getId", "getModel" ]
|
||||
);
|
||||
|
||||
provider = new ElasticsearchSearchProvider(mockHttp, mockObjectService, "");
|
||||
provider.query(' test "query" ', 0, undefined, 1000);
|
||||
});
|
||||
|
||||
it("sends a query to ElasticSearch", function () {
|
||||
expect(mockHttp).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("gets data from ElasticSearch", function () {
|
||||
var data = {
|
||||
hits: {
|
||||
hits: [
|
||||
{},
|
||||
{}
|
||||
],
|
||||
total: 0
|
||||
},
|
||||
timed_out: false
|
||||
};
|
||||
data.hits.hits[0][ID] = 1;
|
||||
data.hits.hits[0][SCORE] = 1;
|
||||
data.hits.hits[1][ID] = 2;
|
||||
data.hits.hits[1][SCORE] = 2;
|
||||
|
||||
mockProviderResults = mockHttpPromise.then.mostRecentCall.args[0]({data: data});
|
||||
|
||||
expect(
|
||||
mockObjectPromise.then.mostRecentCall.args[0]({
|
||||
1: mockDomainObject,
|
||||
2: mockDomainObject
|
||||
}).hits.length
|
||||
).toEqual(2);
|
||||
});
|
||||
|
||||
it("returns nothing for an empty string query", function () {
|
||||
expect(provider.query("").hits).toEqual([]);
|
||||
});
|
||||
|
||||
it("returns something when there is an ElasticSearch error", function () {
|
||||
mockProviderResults = mockHttpPromise['catch'].mostRecentCall.args[0]();
|
||||
expect(mockProviderResults).toBeDefined();
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
150
platform/search/test/providers/GenericSearchProviderSpec.js
Normal file
150
platform/search/test/providers/GenericSearchProviderSpec.js
Normal file
@@ -0,0 +1,150 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT Web includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
/*global define,describe,it,expect,beforeEach,jasmine*/
|
||||
|
||||
/**
|
||||
* SearchSpec. Created by shale on 07/31/2015.
|
||||
*/
|
||||
define(
|
||||
["../../src/providers/GenericSearchProvider"],
|
||||
function (GenericSearchProvider) {
|
||||
"use strict";
|
||||
|
||||
describe("The generic search provider ", function () {
|
||||
var mockQ,
|
||||
mockDeferred,
|
||||
mockObjectService,
|
||||
mockObjectPromise,
|
||||
mockDomainObjects,
|
||||
mockComposition,
|
||||
mockCompositionPromise,
|
||||
mockWorkerService,
|
||||
mockWorker,
|
||||
mockRoots = ['root1', 'root2'],
|
||||
provider,
|
||||
mockProviderResults;
|
||||
|
||||
beforeEach(function () {
|
||||
var i;
|
||||
|
||||
mockQ = jasmine.createSpyObj(
|
||||
"$q",
|
||||
[ "defer" ]
|
||||
);
|
||||
mockDeferred = jasmine.createSpyObj(
|
||||
"deferred",
|
||||
[ "resolve", "reject"]
|
||||
);
|
||||
mockDeferred.promise = "mock promise";
|
||||
mockQ.defer.andReturn(mockDeferred);
|
||||
|
||||
mockObjectService = jasmine.createSpyObj(
|
||||
"objectService",
|
||||
[ "getObjects" ]
|
||||
);
|
||||
mockObjectPromise = jasmine.createSpyObj(
|
||||
"promise",
|
||||
[ "then", "catch" ]
|
||||
);
|
||||
mockObjectService.getObjects.andReturn(mockObjectPromise);
|
||||
|
||||
|
||||
mockWorkerService = jasmine.createSpyObj(
|
||||
"workerService",
|
||||
[ "run" ]
|
||||
);
|
||||
mockWorker = jasmine.createSpyObj(
|
||||
"worker",
|
||||
[ "postMessage" ]
|
||||
);
|
||||
mockWorkerService.run.andReturn(mockWorker);
|
||||
|
||||
mockDomainObjects = {};
|
||||
for (i = 0; i < 4; i += 1) {
|
||||
mockDomainObjects[i] = (
|
||||
jasmine.createSpyObj(
|
||||
"domainObject",
|
||||
[ "getId", "getModel", "hasCapability", "getCapability"]
|
||||
)
|
||||
);
|
||||
mockDomainObjects[i].getId.andReturn(i);
|
||||
}
|
||||
// Give the first object children
|
||||
mockDomainObjects[0].hasCapability.andReturn(true);
|
||||
mockComposition = jasmine.createSpyObj(
|
||||
"composition",
|
||||
[ "invoke" ]
|
||||
);
|
||||
mockCompositionPromise = jasmine.createSpyObj(
|
||||
"promise",
|
||||
[ "then", "catch" ]
|
||||
);
|
||||
mockComposition.invoke.andReturn(mockCompositionPromise);
|
||||
mockDomainObjects[0].getCapability.andReturn(mockComposition);
|
||||
|
||||
provider = new GenericSearchProvider(mockQ, mockObjectService, mockWorkerService, mockRoots);
|
||||
});
|
||||
|
||||
it("indexes tree on initialization", function () {
|
||||
mockObjectPromise.then.mostRecentCall.args[0](mockDomainObjects);
|
||||
mockCompositionPromise.then.mostRecentCall.args[0](mockDomainObjects[1]);
|
||||
|
||||
expect(mockObjectService.getObjects).toHaveBeenCalled();
|
||||
expect(mockWorker.postMessage).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("sends search queries to the worker", function () {
|
||||
var timestamp = Date.now();
|
||||
provider.query(' test "query" ', timestamp, 1, 2);
|
||||
expect(mockWorker.postMessage).toHaveBeenCalledWith({
|
||||
request: "search",
|
||||
input: ' test "query" ',
|
||||
timestamp: timestamp,
|
||||
maxNumber: 1,
|
||||
timeout: 2
|
||||
});
|
||||
});
|
||||
|
||||
it("handles responses from the worker", function () {
|
||||
var timestamp = Date.now(),
|
||||
event = {
|
||||
data: {
|
||||
request: "search",
|
||||
results: {
|
||||
1: 1,
|
||||
2: 2
|
||||
},
|
||||
total: 2,
|
||||
timedOut: false,
|
||||
timestamp: timestamp
|
||||
}
|
||||
};
|
||||
|
||||
provider.query(' test "query" ', timestamp);
|
||||
mockWorker.onmessage(event);
|
||||
mockObjectPromise.then.mostRecentCall.args[0](mockDomainObjects);
|
||||
expect(mockDeferred.resolve).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
);
|
||||
8
platform/search/test/suite.json
Normal file
8
platform/search/test/suite.json
Normal file
@@ -0,0 +1,8 @@
|
||||
[
|
||||
"controllers/SearchController",
|
||||
"controllers/SearchItemController",
|
||||
"SearchAggregator",
|
||||
"providers/ElasticsearchSearchProvider",
|
||||
"providers/GenericSearchProvider",
|
||||
"workers/GenericSearchWorker"
|
||||
]
|
||||
132
platform/search/test/workers/GenericSearchWorkerSpec.js
Normal file
132
platform/search/test/workers/GenericSearchWorkerSpec.js
Normal file
@@ -0,0 +1,132 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT Web includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
/*global define,describe,it,expect,runs,waitsFor,beforeEach,jasmine,Worker*/
|
||||
|
||||
/**
|
||||
* SearchSpec. Created by shale on 07/31/2015.
|
||||
*/
|
||||
define(
|
||||
[],
|
||||
function (GenericSearchWorker) {
|
||||
"use strict";
|
||||
|
||||
describe("The generic search worker ", function () {
|
||||
// If this test fails, make sure this path is correct
|
||||
var worker = new Worker('platform/search/src/workers/GenericSearchWorker.js'),
|
||||
numObjects = 5;
|
||||
|
||||
beforeEach(function () {
|
||||
var i;
|
||||
for (i = 0; i < numObjects; i += 1) {
|
||||
worker.postMessage(
|
||||
{
|
||||
request: "index",
|
||||
id: i,
|
||||
model: {
|
||||
name: "object " + i,
|
||||
id: i,
|
||||
type: "something"
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it("searches can reach all objects", function () {
|
||||
var flag = false,
|
||||
workerOutput,
|
||||
resultsLength = 0;
|
||||
|
||||
// Search something that should return all objects
|
||||
runs(function () {
|
||||
worker.postMessage(
|
||||
{
|
||||
request: "search",
|
||||
input: "object",
|
||||
maxNumber: 100,
|
||||
timestamp: Date.now(),
|
||||
timeout: 1000
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
worker.onmessage = function (event) {
|
||||
var id;
|
||||
|
||||
workerOutput = event.data;
|
||||
for (id in workerOutput.results) {
|
||||
resultsLength += 1;
|
||||
}
|
||||
flag = true;
|
||||
};
|
||||
|
||||
waitsFor(function () {
|
||||
return flag;
|
||||
}, "The worker should be searching", 1000);
|
||||
|
||||
runs(function () {
|
||||
expect(workerOutput).toBeDefined();
|
||||
expect(resultsLength).toEqual(numObjects);
|
||||
});
|
||||
});
|
||||
|
||||
it("searches return only matches", function () {
|
||||
var flag = false,
|
||||
workerOutput,
|
||||
resultsLength = 0;
|
||||
|
||||
// Search something that should return 1 object
|
||||
runs(function () {
|
||||
worker.postMessage(
|
||||
{
|
||||
request: "search",
|
||||
input: "2",
|
||||
maxNumber: 100,
|
||||
timestamp: Date.now(),
|
||||
timeout: 1000
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
worker.onmessage = function (event) {
|
||||
var id;
|
||||
|
||||
workerOutput = event.data;
|
||||
for (id in workerOutput.results) {
|
||||
resultsLength += 1;
|
||||
}
|
||||
flag = true;
|
||||
};
|
||||
|
||||
waitsFor(function () {
|
||||
return flag;
|
||||
}, "The worker should be searching", 1000);
|
||||
|
||||
runs(function () {
|
||||
expect(workerOutput).toBeDefined();
|
||||
expect(resultsLength).toEqual(1);
|
||||
expect(workerOutput.results[2]).toBeDefined();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
Reference in New Issue
Block a user