climate-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jo...@apache.org
Subject [06/28] CLIMATE-512 - Replace frontend with new Yeoman/Grunt/Bower frontend
Date Thu, 28 Aug 2014 03:07:50 GMT
http://git-wip-us.apache.org/repos/asf/climate/blob/652ea657/ocw-ui/frontend/app/js/services/EvaluationSettings.js
----------------------------------------------------------------------
diff --git a/ocw-ui/frontend/app/js/services/EvaluationSettings.js b/ocw-ui/frontend/app/js/services/EvaluationSettings.js
deleted file mode 100755
index 02b4a63..0000000
--- a/ocw-ui/frontend/app/js/services/EvaluationSettings.js
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.
-**/
-
-// EvaluationSettings gives controllers access to the user's selected evaluation settings.
-App.Services.service('evaluationSettings', function($rootScope, $http) {
-    $http.get($rootScope.baseURL + '/processing/metrics/').then(function(data) {
-        metrics_data = data['data']['metrics'];
-        metrics = [];
-
-        for (var i = 0; i < metrics_data.length; ++i) {
-            metrics.push({'name': metrics_data[i], 'select': false});
-        }
-
-        settings['metrics'] = metrics;
-    });
-
-	var settings = {
-        'metrics': [],
-		'temporal': {
-			'options': ['daily', 'monthly', 'yearly'],
-			'selected': 'yearly',
-		},
-		'spatialSelect': null,
-	};
-
-	return {
-		getSettings: function() {
-			return settings;
-		}
-	};
-});		

http://git-wip-us.apache.org/repos/asf/climate/blob/652ea657/ocw-ui/frontend/app/js/services/RegionSelectParams.js
----------------------------------------------------------------------
diff --git a/ocw-ui/frontend/app/js/services/RegionSelectParams.js b/ocw-ui/frontend/app/js/services/RegionSelectParams.js
deleted file mode 100644
index 4f36be6..0000000
--- a/ocw-ui/frontend/app/js/services/RegionSelectParams.js
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.
-**/
-
-// RegionSelectParams gives controllers access to the user selected evaluation region. 
-App.Services.service('regionSelectParams', function() {
-	var parameters = {
-		"areValid" : true,
-		"latMin"   : "",
-		"latMax"   : "",
-		"lonMin"   : "",
-		"lonMax"   : "",
-		"start"    : "",
-		"end"      : "",
-	};
-
-	return {
-		getParameters: function() {
-			return parameters;
-		},
-	};
-});

http://git-wip-us.apache.org/repos/asf/climate/blob/652ea657/ocw-ui/frontend/app/js/services/SelectedDatasetInformation.js
----------------------------------------------------------------------
diff --git a/ocw-ui/frontend/app/js/services/SelectedDatasetInformation.js b/ocw-ui/frontend/app/js/services/SelectedDatasetInformation.js
deleted file mode 100644
index 8378212..0000000
--- a/ocw-ui/frontend/app/js/services/SelectedDatasetInformation.js
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.
-**/
-
-// Service for giving controllers access to the information on datasets that 
-// the user has selected for evaluation.
-App.Services.service('selectedDatasetInformation', function() {
-	var datasets = [];
-
-	return {
-		getDatasets: function() {
-			return datasets;
-		},
-		getDatasetCount: function() {
-			return datasets.length;
-		},
-		// TODO: Define the structure of the objects that are added with addDataset.
-		addDataset: function(dataset) {
-			// All datasets need a shouldDisplay attribute that is used when rendering
-			// the overlays on the map!
-			dataset.shouldDisplay = false;
-			// The regrid attribute indicates which dataset should be used for spatial regridding
-			dataset.regrid = false;
-
-			datasets.push(dataset);
-		},
-		removeDataset: function(index) {
-			datasets.splice(index, 1);
-		},
-		clearDatasets: function() {
-			datasets.length = 0;
-		},
-	};
-});

http://git-wip-us.apache.org/repos/asf/climate/blob/652ea657/ocw-ui/frontend/app/partials/main.html
----------------------------------------------------------------------
diff --git a/ocw-ui/frontend/app/partials/main.html b/ocw-ui/frontend/app/partials/main.html
deleted file mode 100644
index f100fde..0000000
--- a/ocw-ui/frontend/app/partials/main.html
+++ /dev/null
@@ -1,261 +0,0 @@
-<!--
-Licensed to the Apache Software Foundation (ASF) under one
-or more contributor license agreements.  See the NOTICE file
-distributed with this work for additional information
-regarding copyright ownership.  The ASF licenses this file
-to you 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.
--->
-
-<!-- Modal for evaluation settings -->
-  <bootstrap-modal modal-id="evaluationSettings">
-  <div class="modal-header">
-    <button class="close">&times;</button>
-    <h3>Settings</h3>
-  </div>
-  <div class="modal-body" ng-controller="SettingsCtrl">
-    <h4>Select the metrics you would like to run.</h4>
-    <div ng-repeat="metric in settings.metrics">
-      <label><input type="checkbox" ng-model="metric.select"> {{metric.name}}</label>
-    </div>
-    <hr />
-    <h4>Select how you would like to temporally re-grid the datasets.</h4>
-    <select ng-model="settings.temporal.selected" ng-options="opt for opt in settings.temporal.options"></select>
-    <hr />
-    <h4>Select which dataset to use as the reference.</h4>
-    <select ng-model="settings.spatialSelect" ng-options="dataset as dataset.name for dataset in datasets"></select>
-    <hr />
-    <!-- Temporarily hidden for work on CLIMATE-365.-->
-    <div ng-hide=true>
-    <h4>Select a file which will define the bounds of subregions.</h4>
-    <form class="form-inline" autocomplete="off">
-      <input id="subregionFileInput" predictive-file-browser-input ng-model="settings.subregionFile" type="text" class="input-xlarge" autocomplete="off" />
-    </form>
-    </div>
-    <!--End hidden section for CLIMATE-365-->
-  </div>
-  <div class="modal-footer">
-    <a href="#" class="btn btn-warning close">Close</a>
-  </div>
-  </bootstrap-modal>
-<!-- END - Modal for evaluation settings -->
-
-  <div class="row-fluid">
-    <div class="span12">
-      <div class="row-fluid">
-        <div class="span6">
-          <!--Dataset Select Controls-->
-          <div ng-controller="DatasetSelectCtrl">
-            <div class="row-fluid">
-	            <div class="span1 offset10">
-	              <button class="btn btn-link no-color-link" ng-click="clearDatasets()" ng-disabled="shouldDisableClearButton()">
-	                <span tooltip-placement="left" tooltip-popup-delay="700" tooltip="Clear Datasets">
-	                  <i class="icon-trash icon-2x"></i>
-	                </span>
-	              </button>
-	            </div>
-	            <div class="span1">
-	              <button class="btn btn-link no-color-link" ng-click="open()">
-	                <span tooltip-placement="left" tooltip-popup-delay="700" tooltip="Add Dataset">
-	                  <i class="icon-plus icon-2x"></i>
-	                </span>
-	              </button>
-	            </div>
-            </div>
-            <!-- Modal for dataset selection -->
-            <div modal="datasetSelect" close="close()" options="opts">
-              <div class="modal-header">
-                <h3>Dataset Select</h3>
-              </div>
-              <div class="modal-body">
-                <tabset>
-                  <tab ng-repeat="tab in templates" heading="{{tab.title}}" active="tab.active" disabled="tab.disabled">
-                    <div ng-include src="tab.url"></div>
-                  </tab>
-                  <li class="pull-right">Queued Datasets: {{datasetCount.length}}</li>
-                </tabset>
-              </div>
-              <div class="modal-footer">
-                <button class="btn btn-warning cancel" ng-click="close()">Close</button>
-              </div>
-            </div>
-            <!-- END - Modal for dataset selection -->
-            <div class="row-fluid">
-              <div class="span12">
-              <hr />
-              </div>
-            </div>
-          </div>
-          <!--Dataset display-->
-          <div ng-controller="DatasetDisplayCtrl" id="datasetDiv">
-              <div ng-repeat="dataset in datasets">
-                <div class="row-fluid">
-                  <!--Data section-->
-                  <div class="span8 offset1 muted">
-                    {{dataset.name}}
-                  </div>
-                  <div class="span1 offset2">
-                    <span tooltip-placement="left" tooltip-popup-delay="700" tooltip="Remove Dataset">  
-                      <a class="no-color-link" href="#" ng-click="removeDataset($index)">
-                        <i class="icon-remove"></i>
-                      </a>
-                    </span>
-                  </div>
-                </div>
-                <!--Time Values!-->
-                <div class="row-fluid">
-                  <!--Dataset Info Section-->
-                  <div class="span9">
-                    <div class="row-fluid">
-                      <div class="span2 offset1 text-center">Start:</div>
-                      <div class="span2">
-                        <div class="span2 text-center">{{dataset.timeVals.start | ISODateToMiddleEndian}}</div>
-                      </div>
-                      <div class="span2 text-center">End:</div>
-                      <div class="span2">
-                        <div class="span2 text-center">{{dataset.timeVals.end | ISODateToMiddleEndian}}</div>
-                      </div>
-                    </div>
-                    <!--Lat/Long Values!-->
-                    <div class="row-fluid">
-                      <div class="span2 offset1 text-center">North:</div>
-                      <div class="span2 text-center">
-                        {{dataset.latlonVals.latMax | number:2}}
-                      </div>
-                      <div class="span2 text-center">West:</div>
-                      <div class="span2 text-center">
-                        {{dataset.latlonVals.lonMin | number:2}}
-                      </div>
-                    </div>
-                    <div class="row-fluid">
-                      <div class="span2 offset1 text-center">South:</div>
-                      <div class="span2 text-center">
-                        {{dataset.latlonVals.latMin | number:2}}
-                      </div>
-                      <div class="span2 text-center">East:</div>
-                      <div class="span2 text-center">
-                        {{dataset.latlonVals.lonMax | number:2}}
-                      </div>
-                    </div>
-                  </div>
-                  <!--Preview Map Section-->
-                  <div class="span3">
-                    <!--If the dataset is global we show a picture of a globe instead of the actual map-->
-                    <div ng-hide="dataset.latlonVals.lonMin == -180 && dataset.latlonVals.lonMax == 180 && 
-                                  dataset.latlonVals.latMin == -90 && dataset.latlonVals.latMax == 90" 
-                                  preview-map="dataset" index="$index"></div>
-                    <div ng-show="dataset.latlonVals.lonMin == -180 && dataset.latlonVals.lonMax == 180 &&
-                                  dataset.latlonVals.latMin == -90 && dataset.latlonVals.latMax == 90">
-                      <img src="img/globe.png" class="preview-map">
-                    </div>
-                  </div>
-                </div>
-                <div class="row-fluid">
-                  <div class="span6 offset3"><hr /></div>
-                </div>
-              </div>
-            </div>
-        </div>
-        <div class="span6">
-          <!--Map-->
-          <div class="row-fluid"  ng-controller="WorldMapCtrl">
-            <div class="span12">
-              <leaflet-map id="map"></leaflet-map>
-            </div>
-          </div>
-          
-          <!--Timeline-->
-          <div class="row-fluid">
-            <div class="span12" ng-controller="TimelineCtrl">
-              <div class="timeline"></div>
-            </div>
-          </div>
-          
-          <div class="row-fluid">
-            <div class="span12" ng-controller="ParameterSelectCtrl">
-              <div class="row-fluid">
-                <div class="span2 text-center">Start Date:</div>
-                <div class="span4">
-                  <form>
-                    <!--This styling HAD to be done inline. Using a class wouldn't work and for some -->
-                    <!--reason the input boxes refused to be 100% wide when their span size was set.-->
-                    <input ng-disabled="shouldDisableControls()" on-blur="checkParameters();" ng-model="displayParams.start" ui-date="datepickerSettings" ui-date-format="yy-mm-dd" type="text" class="text-center span4" style="width:100%" />
-                  </form>
-                </div>
-                <div class="span2 text-center">End Date:</div>
-                <div class="span4">
-                  <form>
-                    <!--This styling HAD to be done inline. Using a class wouldn't work and for some -->
-                    <!--reason the input boxes refused to be 100% wide when their span size was set.-->
-                    <input ng-disabled="shouldDisableControls()" on-blur="checkParameters();" ng-model="displayParams.end" ui-date="datepickerSettings" ui-date-format="yy-mm-dd" type="text" class="text-center span4" style="width:100%"/>
-                  </form>
-                </div>
-              </div>
-              <div class="row-fluid">
-                <div class="span2 text-center">North:</div>
-                <div class="span4">
-                  <form action="">
-                    <input ng-disabled="shouldDisableControls()" ng-model="displayParams.latMax"  on-blur="checkParameters();" type="text" class="span4 text-center" style="width:100%"/>
-                  </form>
-                </div>
-                <div class="span2 text-center">South:</div>
-                <div class="span4">
-                  <form action="">
-                    <!--This styling HAD to be done inline. Using a class wouldn't work and for some -->
-                    <!--reason the input boxes refused to be 100% wide when their span size was set.-->
-                    <input ng-disabled="shouldDisableControls()" ng-model="displayParams.latMin" on-blur="checkParameters();" type="text" class="span4 text-center" style="width:100%"/>
-                  </form>
-                </div>
-              </div>
-              <div class="row-fluid">
-                <div class="span2 text-center">East:</div>
-                <div class="span4">
-                  <form>
-                    <!--This styling HAD to be done inline. Using a class wouldn't work and for some -->
-                    <!--reason the input boxes refused to be 100% wide when their span size was set.-->
-                    <input ng-disabled="shouldDisableControls()" ng-model="displayParams.lonMax" on-blur="checkParameters();" type="text" class="span4 text-center" style="width:100%"/>
-                  </form>
-                </div>
-                <div class="span2 text-center">West:</div>
-                <div class="span4">
-                  <form>
-                    <!--This styling HAD to be done inline. Using a class wouldn't work and for some -->
-                    <!--reason the input boxes refused to be 100% wide when their span size was set.-->
-                    <input ng-disabled="shouldDisableControls()" ng-model="displayParams.lonMin" on-blur="checkParameters();"; type="text" class="span4 text-center" style="width:100%"/>
-                  </form>
-                </div>
-              </div>
-              <div class="row-fluid">
-                <div class="span2 offset6">
-                  <button class="btn btn-link no-color-link pull-right" bootstrap-modal-open="evaluationSettings">
-                    <span tooltip-placement="left" tooltip-popup-delay="700" tooltip="Settings">
-                      <span class="icon-stack">
-                        <i class="icon-check-empty icon-stack-base"></i>
-                        <i class="icon-cogs"></i>
-                      </span>
-                    </span>
-                  </button>
-                </div>
-                <div class="span4">
-                  <button ng-click="runEvaluation()" ng-disabled="shouldDisableEvaluateButton()" class="btn btn-block btn-primary">
-                    <div ng-hide="runningEval">Evaluate</div>
-                    <div ng-show="runningEval"><i class="icon-spinner icon-spin"></i></div>
-                  </button>
-                </div>
-              </div>
-            </div>
-          </div>
-        </div>
-        </div>
-    </div>
-  </div>

http://git-wip-us.apache.org/repos/asf/climate/blob/652ea657/ocw-ui/frontend/app/partials/modelSelect.html
----------------------------------------------------------------------
diff --git a/ocw-ui/frontend/app/partials/modelSelect.html b/ocw-ui/frontend/app/partials/modelSelect.html
deleted file mode 100644
index 6a28a3f..0000000
--- a/ocw-ui/frontend/app/partials/modelSelect.html
+++ /dev/null
@@ -1,86 +0,0 @@
-<!--
-Licensed to the Apache Software Foundation (ASF) under one
-or more contributor license agreements.  See the NOTICE file
-distributed with this work for additional information
-regarding copyright ownership.  The ASF licenses this file
-to you 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.
--->
-
-<div class="container">
-  <div class="row">
-    <div class="span10 offset1 columns">
-      <div class="row">
-        <div class="span10">
-          <center>
-            <form id="modelSelectorForm">
-              <input type="file" name="modelSelector">
-            </form>
-          </center>
-        </div>
-      </div>
-      <div class="row">
-        <div class="span10 offset2">
-          <form class="form-horizontal" id="parameterSelectorForm">
-            <div class="control-group">
-              <label class="control-label" for="paramSelect">Parameter Value</label>
-              <div class="controls">
-                <select id="paramSelect">
-                  <option ng-repeat="param in modelParameters">
-                    {{param.text}}
-                  </option>
-                </select>
-              </div>
-            </div>
-            <div class="control-group">
-              <label class="control-label" for="latSelect">Latitude Variable</label>
-              <div class="controls">
-                <select id="latSelect">
-                  <option ng-repeat="lat in latVariables">
-                    {{lat.text}}
-                  </option>
-                </select>
-              </div>
-            </div>
-            <div class="control-group">
-              <label class="control-label" for="lonSelect">Longitude Variable</label>
-              <div class"controls">
-                <select id="lonSelect">
-                  <option ng-repeat="lon in lonVariables">
-                    {{lon.text}}
-                  </option>
-                </select>
-              </div>
-            </div>
-            <div class="control-group">
-              <label class="control-label" for="dateTimeSelect">Date/Time Variable</label>
-              <div class="controls">
-                <select id="dateTimeSelect">
-                  <option ng-repeat="dateTime in dateTimeVariables">
-                    {{dateTime.text}}
-                  </option>
-                </select>
-              </div>
-            </div>
-            <div class="control-group">
-              <div class="controls">
-                <button type="submit" class="btn btn-warn">Cancel</button>
-                <button type="submit" class="btn">Add Model</button>
-              </div>
-            </div>
-          </form>
-        </div>
-      </div>
-    </div>
-  </div>
-</div>

http://git-wip-us.apache.org/repos/asf/climate/blob/652ea657/ocw-ui/frontend/app/partials/results.detail.html
----------------------------------------------------------------------
diff --git a/ocw-ui/frontend/app/partials/results.detail.html b/ocw-ui/frontend/app/partials/results.detail.html
deleted file mode 100644
index a5c4d7c..0000000
--- a/ocw-ui/frontend/app/partials/results.detail.html
+++ /dev/null
@@ -1,30 +0,0 @@
-<!--
-Licensed to the Apache Software Foundation (ASF) under one
-or more contributor license agreements.  See the NOTICE file
-distributed with this work for additional information
-regarding copyright ownership.  The ASF licenses this file
-to you 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.
--->
-
-<div>
-  <h2>{{result}}</h2>
-  <div class="row-fluid text-center">
-    <div class="{{alertClass}}">{{alertMessage}}</div>
-    <ul>
-      <li ng-repeat="figure in figures">
-        <img class="result-figures" ng-src="{{baseURL}}/static/eval_results/{{figure}}" alt="" />
-      </li>
-    </ul>
-  </div>
-</div>

http://git-wip-us.apache.org/repos/asf/climate/blob/652ea657/ocw-ui/frontend/app/partials/results.html
----------------------------------------------------------------------
diff --git a/ocw-ui/frontend/app/partials/results.html b/ocw-ui/frontend/app/partials/results.html
deleted file mode 100644
index a21dadc..0000000
--- a/ocw-ui/frontend/app/partials/results.html
+++ /dev/null
@@ -1,34 +0,0 @@
-<!--
-Licensed to the Apache Software Foundation (ASF) under one
-or more contributor license agreements.  See the NOTICE file
-distributed with this work for additional information
-regarding copyright ownership.  The ASF licenses this file
-to you 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.
--->
-
-<div class="row">
-  <div class="span3">
-    <div id="results-sidebar" class="pa-sidebar well well-small">
-      <ul class="nav nav-list">
-        <li id="results-sidebar-header" class="nav-header">Latest Run Results</li>
-        <li ng-repeat="result in results"
-            ng-class="{ active: $state.includes('results.detail') && $stateParams.resultId == result }">
-          <a href="#/results/{{result.replace('/', '')}}" >{{result}}</a>
-        </li>
-      </ul>
-      <div ui-view="menu"></div>
-    </div>
-  </div>
-  <div class="span9" ui-view ng-animate="{enter:'fade-enter'}"></div>
-</div>

http://git-wip-us.apache.org/repos/asf/climate/blob/652ea657/ocw-ui/frontend/app/partials/results.list.html
----------------------------------------------------------------------
diff --git a/ocw-ui/frontend/app/partials/results.list.html b/ocw-ui/frontend/app/partials/results.list.html
deleted file mode 100644
index ef1d9d7..0000000
--- a/ocw-ui/frontend/app/partials/results.list.html
+++ /dev/null
@@ -1,22 +0,0 @@
-<!--
-Licensed to the Apache Software Foundation (ASF) under one
-or more contributor license agreements.  See the NOTICE file
-distributed with this work for additional information
-regarding copyright ownership.  The ASF licenses this file
-to you 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.
--->
-
-<h4>Select one of your previous runs. If none are displayed, please return
-  to the main page and start one!</h4>
-

http://git-wip-us.apache.org/repos/asf/climate/blob/652ea657/ocw-ui/frontend/app/partials/selectObservation.html
----------------------------------------------------------------------
diff --git a/ocw-ui/frontend/app/partials/selectObservation.html b/ocw-ui/frontend/app/partials/selectObservation.html
deleted file mode 100644
index c364f75..0000000
--- a/ocw-ui/frontend/app/partials/selectObservation.html
+++ /dev/null
@@ -1,58 +0,0 @@
-<!--
-Licensed to the Apache Software Foundation (ASF) under one
-or more contributor license agreements.  See the NOTICE file
-distributed with this work for additional information
-regarding copyright ownership.  The ASF licenses this file
-to you 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.
--->
-
-<div ng-controller="ObservationSelectCtrl">
-  <form class="form-inline" autocomplete="off">
-    <input id="observationFileInput" predictive-file-browser-input ng-model="filePathInput" type="text" class="input-xlarge" autocomplete="off" />
-    <button class="btn" ng-click="uploadLocalFile()" ng-disabled="shouldDisableLoadButton()">
-      <div ng-hide="loadingFile">Parse File</div>
-      <div ng-show="loadingFile"><i class="icon-spinner icon-spin"></i></div>
-    </button>
-  </form>
-
-  <div class="row">
-    <div class="span2 text-center">
-      Evaluation Variable
-    </div>
-    <div class="span3">
-      <select ng-model="paramSelect" ng-options="param for param in params"></select>
-    </div>
-    <div class="span2 text-center">
-      Latitude Variable
-    </div>
-    <div class="span3">
-      <select ng-model="latsSelect" ng-options="lat for lat in lats"></select>
-    </div>
-    <div class="span2 text-center">
-      Longitude Variable
-    </div>
-    <div class="span3">
-      <select ng-model="lonsSelect" ng-options="lon for lon in lons"></select>
-    </div>
-    <div class="span2 text-center">
-      Date/Time Variable
-    </div>
-    <div class="span3">
-      <select ng-model="timeSelect" ng-options="time for time in times"></select>
-    </div>
-  </div>
-
-  <button class="btn btn-primary pull-left" ng-click="addDataSet()">Add Dataset</button>
-  <div class="pull-left small-alert" ng-show="fileAdded">Successfully added dataset...</div>
-</div>

http://git-wip-us.apache.org/repos/asf/climate/blob/652ea657/ocw-ui/frontend/app/partials/selectRcmed.html
----------------------------------------------------------------------
diff --git a/ocw-ui/frontend/app/partials/selectRcmed.html b/ocw-ui/frontend/app/partials/selectRcmed.html
deleted file mode 100644
index c454165..0000000
--- a/ocw-ui/frontend/app/partials/selectRcmed.html
+++ /dev/null
@@ -1,44 +0,0 @@
-<!--
-Licensed to the Apache Software Foundation (ASF) under one
-or more contributor license agreements.  See the NOTICE file
-distributed with this work for additional information
-regarding copyright ownership.  The ASF licenses this file
-to you 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.
--->
-
-<div ng-controller="RcmedSelectionCtrl">
-  <div class="row">
-    <div class="span5">
-    Select the RCMED dataset that you would like use.
-    </div>
-  </div>
-  <div class="row">
-    <div class="span4">
-      <select ng-change="dataSelectUpdated()" class="span5" ng-model="datasetSelection" ng-options="obs as obs.longname for obs in availableObs"></select>
-    </div>
-  </div>
-  <div class="row">
-    <div class="span5">
-    Select the dataset parameter that you would like to test.
-    </div>
-  </div>
-  <div class="row">
-    <div class="span4">
-      <select class="span3" ng-model="parameterSelection" ng-options="param as param.shortname for param in retrievedObsParams"></select>
-    </div>
-  </div>
-
-  <button class="btn btn-primary pull-left" ng-click="addObservation()">Add Observation</button>
-  <div class="pull-left small-alert" ng-show="fileAdded">Successfully added dataset...</div>
-</div>

http://git-wip-us.apache.org/repos/asf/climate/blob/652ea657/ocw-ui/frontend/app/robots.txt
----------------------------------------------------------------------
diff --git a/ocw-ui/frontend/app/robots.txt b/ocw-ui/frontend/app/robots.txt
new file mode 100644
index 0000000..9417495
--- /dev/null
+++ b/ocw-ui/frontend/app/robots.txt
@@ -0,0 +1,3 @@
+# robotstxt.org
+
+User-agent: *

http://git-wip-us.apache.org/repos/asf/climate/blob/652ea657/ocw-ui/frontend/app/scripts/app.js
----------------------------------------------------------------------
diff --git a/ocw-ui/frontend/app/scripts/app.js b/ocw-ui/frontend/app/scripts/app.js
new file mode 100644
index 0000000..8dca2dc
--- /dev/null
+++ b/ocw-ui/frontend/app/scripts/app.js
@@ -0,0 +1,96 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+'use strict';
+
+/**
+ * @ngdoc overview
+ * @name ocwUiApp
+ * @description
+ * # ocwUiApp
+ *
+ * Main module of the application.
+ */
+angular
+  .module('ocwUiApp', [
+    'ngAnimate',
+    'ngCookies',
+    'ngResource',
+    'ngRoute',
+    'ui.router',
+    'ui.bootstrap',
+    'ui.date',
+  ])
+  .config(['$stateProvider', '$routeProvider', '$urlRouterProvider',
+    function ($stateProvider,   $routeProvider,   $urlRouterProvider) {
+      $urlRouterProvider
+        .when('/r?id', '/results/:id')
+        .otherwise('/evaluate');
+
+      $routeProvider
+        .when('/evaluation/:id', {
+          redirectTo: '/results/:id',
+        })
+        .when('/', {
+          redirectTo: '/evaluate',
+        });
+
+      $stateProvider
+        .state('main',{
+          url: '/evaluate',
+          templateUrl: 'views/main.html',
+        })
+        .state('results', {
+          url: '/results',
+          abstract: true,
+          templateUrl: 'views/results.html',
+          controller: 'ResultCtrl'
+        })
+        .state('results.list', {
+          // parent: 'results',
+          url: '',
+          templateUrl: 'views/resultslist.html',
+        })
+        .state('results.detail', {
+          // parent: 'results',
+          url: '/{resultId}',
+          views: {
+            '': {
+              templateUrl: 'views/resultsdetail.html',
+              controller: 'ResultDetailCtrl'
+            },
+            'menu': {
+              templateProvider:
+                [ '$stateParams',
+                function ($stateParams){
+                  return '<hr><small class="muted">result ID: ' + $stateParams.resultId + '</small>';
+                }],
+            },
+          },
+        });
+    }])
+  .run(['$rootScope', '$state', '$stateParams',
+    function ($rootScope,   $state,   $stateParams) {
+      $rootScope.$state = $state;
+      $rootScope.$stateParams = $stateParams;
+      $rootScope.evalResults = '';
+      $rootScope.fillColors = ['#ff0000', '#00c90d', '#cd0074', '#f3fd00'];
+      $rootScope.surroundColors = ['#a60000', '#008209', '#8f004b', '#93a400'];
+      $rootScope.baseURL = 'http://localhost:8082';
+  }]);

http://git-wip-us.apache.org/repos/asf/climate/blob/652ea657/ocw-ui/frontend/app/scripts/controllers/datasetdisplay.js
----------------------------------------------------------------------
diff --git a/ocw-ui/frontend/app/scripts/controllers/datasetdisplay.js b/ocw-ui/frontend/app/scripts/controllers/datasetdisplay.js
new file mode 100644
index 0000000..f7d2a77
--- /dev/null
+++ b/ocw-ui/frontend/app/scripts/controllers/datasetdisplay.js
@@ -0,0 +1,43 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+'use strict';
+
+/**
+ * @ngdoc function
+ * @name ocwUiApp.controller:DatasetDisplayCtrl
+ * @description
+ * # DatasetDisplayCtrl
+ * Controller of the ocwUiApp
+ */
+angular.module('ocwUiApp')
+  .controller('DatasetDisplayCtrl', ['$rootScope', '$scope', 'selectedDatasetInformation', 
+    function($rootScope, $scope, selectedDatasetInformation) {
+	  $scope.datasets = selectedDatasetInformation.getDatasets();
+
+	  $scope.removeDataset = function($index) {
+	    selectedDatasetInformation.removeDataset($index);
+	  };
+
+	  $scope.setRegridBase = function(index) {
+        for (var i = 0; i < $scope.datasets.length; i++) {
+          $scope.datasets[i].regrid = ((i === index) ? $scope.datasets[i].regrid : false);
+        }
+	  };
+}]);

http://git-wip-us.apache.org/repos/asf/climate/blob/652ea657/ocw-ui/frontend/app/scripts/controllers/datasetselect.js
----------------------------------------------------------------------
diff --git a/ocw-ui/frontend/app/scripts/controllers/datasetselect.js b/ocw-ui/frontend/app/scripts/controllers/datasetselect.js
new file mode 100644
index 0000000..b6b52ef
--- /dev/null
+++ b/ocw-ui/frontend/app/scripts/controllers/datasetselect.js
@@ -0,0 +1,64 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+'use strict';
+
+/**
+ * @ngdoc function
+ * @name ocwUiApp.controller:DatasetSelectCtrl
+ * @description
+ * # DatasetSelectCtrl
+ * Controller of the ocwUiApp
+ */
+angular.module('ocwUiApp')
+  .controller('DatasetSelectCtrl', ['$scope', 'selectedDatasetInformation',
+    function($scope, selectedDatasetInformation) {
+      // Grab a copy of the datasets so we can display a count to the user!
+      $scope.datasetCount = selectedDatasetInformation.getDatasets();
+
+      $scope.shouldDisableClearButton = function() {
+        return (selectedDatasetInformation.getDatasetCount() === 0);
+      };
+
+      $scope.clearDatasets = function() {
+        selectedDatasetInformation.clearDatasets();
+      };
+
+      $scope.open = function () {
+        $scope.datasetSelect = true;
+      };
+
+      $scope.close = function () {
+        $scope.datasetSelect = false;
+      };
+
+      $scope.opts = {
+        backdropFade: true,
+        dialogFade: true,
+      };
+
+      $scope.templates = [
+        {title:'Local File', url: 'views/selectobservation.html'},
+        {title:'RCMED', url: 'views/selectrcmed.html'},
+        {title:'ESG', disabled: true}
+      ];
+
+      $scope.template = $scope.templates[0];
+    }
+  ]);

http://git-wip-us.apache.org/repos/asf/climate/blob/652ea657/ocw-ui/frontend/app/scripts/controllers/main.js
----------------------------------------------------------------------
diff --git a/ocw-ui/frontend/app/scripts/controllers/main.js b/ocw-ui/frontend/app/scripts/controllers/main.js
new file mode 100644
index 0000000..16008c0
--- /dev/null
+++ b/ocw-ui/frontend/app/scripts/controllers/main.js
@@ -0,0 +1,36 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+'use strict';
+
+/**
+ * @ngdoc function
+ * @name ocwUiApp.controller:MainCtrl
+ * @description
+ * # MainCtrl
+ * Controller of the ocwUiApp
+ */
+angular.module('ocwUiApp')
+  .controller('MainCtrl', function ($scope) {
+    $scope.awesomeThings = [
+      'HTML5 Boilerplate',
+      'AngularJS',
+      'Karma'
+    ];
+  });

http://git-wip-us.apache.org/repos/asf/climate/blob/652ea657/ocw-ui/frontend/app/scripts/controllers/observationselect.js
----------------------------------------------------------------------
diff --git a/ocw-ui/frontend/app/scripts/controllers/observationselect.js b/ocw-ui/frontend/app/scripts/controllers/observationselect.js
new file mode 100644
index 0000000..6dfbb57
--- /dev/null
+++ b/ocw-ui/frontend/app/scripts/controllers/observationselect.js
@@ -0,0 +1,203 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+'use strict';
+
+/**
+ * @ngdoc function
+ * @name ocwUiApp.controller:ObservationSelectCtrl
+ * @description
+ * # ObservationSelectCtrl
+ * Controller of the ocwUiApp
+ */
+angular.module('ocwUiApp')
+  .controller('ObservationSelectCtrl', ['$rootScope', '$scope', '$http', '$q', '$timeout', 'selectedDatasetInformation',
+  function($rootScope, $scope, $http, $q, $timeout, selectedDatasetInformation) {
+    // Grab a copy of the datasets so we can display a count to the user!
+    $scope.datasetCount = selectedDatasetInformation.getDatasets();
+
+    // Initalize the option arrays and default to the first element
+    $scope.params      = ['Please select a file above'];
+    $scope.paramSelect = $scope.params[0];
+    $scope.lats        = ['Please select a file above'];
+    $scope.latsSelect  = $scope.lats[0];
+    $scope.lons        = ['Please select a file above'];
+    $scope.lonsSelect  = $scope.lons[0];
+    $scope.times       = ['Please select a file above'];
+    $scope.timeSelect  = $scope.times[0];
+
+    // Grab the path leader information that the webserver is using to limit directory access.
+    $scope.pathLeader = false;
+    $http.jsonp($rootScope.baseURL + '/dir/path_leader/?callback=JSON_CALLBACK').
+      success(function(data) {
+      $scope.pathLeader = data.leader;
+    });
+
+    // Toggle load button view depending on upload state of selected files
+    $scope.loadingFile = false;
+
+    // Toggle display of a confirmation when loading a dataset
+    $scope.fileAdded = false;
+
+    $scope.latLonVals = [];
+    $scope.timeVals = [];
+    $scope.localSelectForm = {};
+
+    $scope.uploadLocalFile = function() {
+      $scope.loadingFile = true;
+
+      // TODO: Need to try to validate the input a bit. At least make sure we're not
+      // pointing at a directory perhaps?
+
+      // TODO: Two-way binding with ng-model isn't being used here because it fails to update
+      // properly with the auto-complete that we're using on the input box. So we're doing
+      // it the wrong way temporarily...
+      var input = $('#observationFileInput').val();
+
+      // If the backend is limiting directory access we need to add that leader to our path
+      // so it remains valid!
+      if ($scope.pathLeader) {
+        input = $scope.pathLeader + input
+      }
+
+      // TODO: We're not really handling the case where there is a failure here at all. 
+      // Should check for fails and allow the user to make changes.
+      //
+      // Get model variables
+      var varsPromise = $http.jsonp($rootScope.baseURL + '/lfme/list_vars/' + input + '?callback=JSON_CALLBACK');
+      // Get Lat and Lon variables
+      var latlonPromise = $http.jsonp($rootScope.baseURL + '/lfme/list_latlon/' + input + '?callback=JSON_CALLBACK');
+      // Get Time variables
+      var timesPromise = $http.jsonp($rootScope.baseURL + '/lfme/list_time/' + input + '?callback=JSON_CALLBACK');
+
+      $q.all([varsPromise, latlonPromise, timesPromise]).then(
+        // Handle success fetches!
+        function(arrayOfResults) {
+          $scope.loadingFile = false;
+
+          // Handle lat/lon results
+          var data = arrayOfResults[1].data;
+          $scope.lats = [data.lat_name];
+          $scope.lons = [data.lon_name];
+          $scope.latLonVals = [data.lat_min, data.lat_max, data.lon_min, data.lon_max];
+
+          // If there is more than one option for the user, tell them they need to pick one!
+          if ($scope.lats.length > 1) $scope.lats.splice(0, 0, 'Please select an option');
+          if ($scope.lons.length > 1) $scope.lons.splice(0, 0, 'Please select an option');
+          // Default the display to the first available option.
+          $scope.latsSelect = $scope.lats[0];
+          $scope.lonsSelect = $scope.lons[0];
+
+          // Handle time results
+          var data = arrayOfResults[2].data
+          $scope.times = [data.time_name];
+          $scope.timeVals = [data.start_time, data.end_time];
+
+          if ($scope.times.length > 1) $scope.times.splice(0, 0, 'Please select an option');
+          $scope.timeSelect = $scope.times[0];
+
+          // Handle parameter results
+          var data = arrayOfResults[0].data.variables;
+          $scope.params = (data instanceof Array) ? data : [data];
+          $scope.params = $.grep($scope.params, 
+                                 function(val) {
+                                   return ($.inArray(val, $scope.lats)  != 0 && 
+                                           $.inArray(val, $scope.lons)  != 0 && 
+                                           $.inArray(val, $scope.times) != 0);
+                                 });
+
+                                 if ($scope.params.length > 1) $scope.params.splice(0, 0, 'Please select an option');
+                                 $scope.paramSelect = $scope.params[0];
+        },
+        // Uh oh! AT LEAST on of our fetches failed
+        function(arrayOfFailure) {
+          $scope.loadingFile = false;
+
+          $scope.params      = ['Unable to load variable(s)'];
+          $scope.paramSelect = $scope.params[0];
+          $scope.lats        = ['Unable to load variable(s)'];
+          $scope.latsSelect  = $scope.lats[0];
+          $scope.lons        = ['Unable to load variable(s)'];
+          $scope.lonsSelect  = $scope.lons[0];
+          $scope.times       = ['Unable to load variable(s)'];
+          $scope.timeSelect  = $scope.times[0];
+        }
+      );
+    };
+
+    $scope.addDataSet = function() {
+      // TODO: Need to verify that all the variables selected are correct!!!
+      // TODO: We shouldn't allow different parameters to match the same variables!!
+
+      var newDataset = {};
+      var input = $('#observationFileInput').val();
+
+      // If the backend is limiting directory access we need to add that leader to our path
+      // so it remains valid!
+      if ($scope.pathLeader != 'False') {
+        input = $scope.pathLeader + input
+      }
+
+      newDataset['isObs'] = 0;
+      // Save the model path. Note that the path is effectively the "id" for the model.
+      newDataset['id'] = input;
+      // Grab the file name later for display purposes.
+      var splitFilePath = input.split('/');
+      newDataset['name'] = splitFilePath[splitFilePath.length - 1];
+      // Save the model parameter variable. We save it twice for consistency and display convenience.
+      newDataset['param'] = $scope.paramSelect;
+      newDataset['paramName'] = newDataset['param'];
+      // Save the lat/lon information
+      newDataset['lat'] = $scope.latsSelect;
+      newDataset['lon'] = $scope.lonsSelect;
+
+      newDataset['latlonVals'] = {'latMin': $scope.latLonVals[0], 'latMax': $scope.latLonVals[1],
+        'lonMin': $scope.latLonVals[2], 'lonMax': $scope.latLonVals[3]};
+        // Get the time information
+        newDataset['time'] = $scope.timeSelect;
+        newDataset['timeVals'] = {'start': $scope.timeVals[0], 'end': $scope.timeVals[1]};
+
+        selectedDatasetInformation.addDataset(newDataset);
+
+        // Reset all the fields!!
+        $scope.params = ['Please select a file above'];
+        $scope.paramSelect = $scope.params[0];
+        $scope.lats = ['Please select a file above'];
+        $scope.latsSelect = $scope.lats[0];
+        $scope.lons = ['Please select a file above'];
+        $scope.lonsSelect = $scope.lons[0];
+        $scope.times = ['Please select a file above'];
+        $scope.timeSelect = $scope.times[0];
+        $scope.latLonVals = [];
+        $scope.timeVals = [];
+
+        // Clear the input box
+        $('#observationFileInput').val('');
+
+        // Display a confirmation message for a little bit
+        $scope.fileAdded = true;
+        $timeout(function() {
+          $scope.fileAdded = false;
+        }, 2000);
+    }
+
+    $scope.shouldDisableLoadButton = function() {
+      return $scope.loadingFile;
+    }
+  }]);

http://git-wip-us.apache.org/repos/asf/climate/blob/652ea657/ocw-ui/frontend/app/scripts/controllers/parameterselect.js
----------------------------------------------------------------------
diff --git a/ocw-ui/frontend/app/scripts/controllers/parameterselect.js b/ocw-ui/frontend/app/scripts/controllers/parameterselect.js
new file mode 100644
index 0000000..cad97e0
--- /dev/null
+++ b/ocw-ui/frontend/app/scripts/controllers/parameterselect.js
@@ -0,0 +1,275 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+'use strict';
+
+/**
+ * @ngdoc function
+ * @name ocwUiApp.controller:ParameterSelectCtrl
+ * @description
+ * # ParameterSelectCtrl
+ * Controller of the ocwUiApp
+ */
+angular.module('ocwUiApp')
+.controller('ParameterSelectCtrl', ['$rootScope', '$scope', '$http', '$timeout', 
+						   'selectedDatasetInformation', 'regionSelectParams', 'evaluationSettings', 
+  function($rootScope, $scope, $http, $timeout, selectedDatasetInformation, regionSelectParams, evaluationSettings) {
+    $scope.datasets = selectedDatasetInformation.getDatasets();
+
+    // The min/max lat/lon values from the selected datasets
+    $scope.latMin = -90;
+    $scope.latMax = 90;
+    $scope.lonMin = -180;
+    $scope.lonMax = 180;
+    $scope.start = "1900-01-01 00:00:00";
+    $scope.end = "2030-01-01 00:00:00";
+
+    // The min/max lat/lon values that are displayed
+    $scope.displayParams = regionSelectParams.getParameters();
+
+    $scope.runningEval = false;
+
+    // Flag for toggling re-grid controls based on whether or not the user has selected a grid
+    // base from the selected datasets. By default we have no datasets so we don't need to show
+    // the controls!
+    $scope.areInUserRegridState = false;
+
+    // Initialization for the lat/lon grid step sliders
+    // TODO There has to be a better way of dealing with this. Perhaps a directive??
+    $scope.latSliderVal = 0;
+    $scope.lonSliderVal = 0;
+
+    // Settings for jQuery datepicker directives!
+    $scope.datepickerSettings = {
+      changeMonth: true,
+      changeYear: true,
+    };
+
+    $scope.shouldDisableControls = function() {
+      return (selectedDatasetInformation.getDatasetCount() < 2);
+    }
+
+    $scope.shouldDisableEvaluateButton = function() {
+      return ($scope.shouldDisableControls() || $scope.runningEval);
+    }
+
+    $scope.shouldDisableResultsView = function() {
+      var res = false;
+
+      if ($rootScope.evalResults == "")
+        res = true;
+
+      return res;
+    }
+
+    $scope.runEvaluation = function() {
+      $scope.runningEval = true;
+
+      var data = {}
+      var settings = evaluationSettings.getSettings()
+
+      // Set dataset information
+
+      // Grab the reference dataset information
+      var ref_ds = settings.spatialSelect;
+
+      if (ref_ds == null) {
+        ref_ds = $scope.datasets[0];
+      }
+
+      data['reference_dataset'] = null;
+      data['target_datasets'] = [];
+
+      // Parse all the dataset information and generate the necessary objects for the backend
+      for (var i = 0; i < $scope.datasets.length; i++) {
+        var dataset = {}
+        dataset['dataset_info'] = {}
+
+        if ($scope.datasets[i].isObs == 0) {
+          dataset['data_source_id'] = 1;
+          dataset['dataset_info']['dataset_id'] = $scope.datasets[i]['id'];
+          dataset['dataset_info']['var_name'] = $scope.datasets[i]['param'];
+          dataset['dataset_info']['lat_name'] = $scope.datasets[i]['lat'];
+          dataset['dataset_info']['lon_name'] = $scope.datasets[i]['lon'];
+          dataset['dataset_info']['time_name'] = $scope.datasets[i]['time'];
+          dataset['dataset_info']['name'] = $scope.datasets[i]['name'];
+        } else {
+          dataset['data_source_id'] = 2;
+          dataset['dataset_info']['dataset_id'] = $scope.datasets[i]['datasetId'];
+          dataset['dataset_info']['parameter_id'] = $scope.datasets[i]['param'];
+          dataset['dataset_info']['name'] = $scope.datasets[i]['name'];
+        }
+
+        if ($scope.datasets[i].id === ref_ds.id) {
+          data['reference_dataset'] = dataset;
+        } else {
+          data['target_datasets'].push(dataset);
+        }
+      }
+
+      // TODO: These should be use customizable
+      // Set the spatial rebin grid steps
+      data['spatial_rebin_lat_step'] = 1;
+      data['spatial_rebin_lon_step'] = 1;
+
+      // Determine the temporal resolution to use when doing a temporal rebin. The
+      // value is used to determine the timedelta in days to use.
+      var temporal_res = settings.temporal.selected;
+
+      if (temporal_res == 'daily') {
+        data['temporal_resolution'] = 1;
+      } else if (temporal_res == 'monthly') {
+        data['temporal_resolution'] = 30;
+      } else if (temporal_res == 'yearly') {
+        data['temporal_resolution'] = 365;
+      } else if (temporal_res == 'full') {
+        data['temporal_resolution'] = 999;
+      } else {
+        // Default to monthly just in case
+        data['temporal_resolution'] = 30;
+      }
+
+      // Load the Metrics for the evaluation
+      data['metrics'] = []
+      var metrics = settings.metrics
+      for (var i = 0; i < metrics.length; i++) {
+        var metric = metrics[i];
+
+        if (metric.select) {
+          data['metrics'].push(metric.name)
+        }
+      }
+
+      // Set the bound values for the evaluation
+      data['start_time'] =  $scope.displayParams.start + " 00:00:00",
+      data['end_time'] = $scope.displayParams.end + " 00:00:00",
+      data['lat_min'] = $scope.displayParams.latMin,
+      data['lat_max'] = $scope.displayParams.latMax,
+      data['lon_min'] = $scope.displayParams.lonMin,
+      data['lon_max'] = $scope.displayParams.lonMax,
+
+      $http.post($rootScope.baseURL + '/processing/run_evaluation/', data).
+      success(function(data) {
+        var evalWorkDir = data['eval_work_dir'];
+
+        $scope.runningEval = false;
+
+        $timeout(function() {
+          if (evalWorkDir !== undefined) {
+            window.location = "#/results/" + evalWorkDir;
+          } else {
+            window.location = "#/results";
+          }
+        }, 100);
+        
+      }).error(function() {
+        $scope.runningEval = false;
+      });
+    };
+
+    // Check the Parameter selection boxes after the user has changed input to ensure that valid
+    // values were entered
+    $scope.checkParameters = function() {
+      if (parseFloat($scope.displayParams.latMin) < parseFloat($scope.latMin))
+        $scope.displayParams.latMin = $scope.latMin;
+
+      if (parseFloat($scope.displayParams.latMax) > parseFloat($scope.latMax))
+        $scope.displayParams.latMax = $scope.latMax;
+
+      if (parseFloat($scope.displayParams.lonMin) < parseFloat($scope.lonMin)) 
+        $scope.displayParams.lonMin = $scope.lonMin;
+
+      if (parseFloat($scope.displayParams.lonMax) > parseFloat($scope.lonMax)) 
+        $scope.displayParams.lonMax = $scope.lonMax;
+
+      if ($scope.displayParams.start < $scope.start) 
+        $scope.displayParams.start = $scope.start;
+
+      if ($scope.displayParams.end > $scope.end)
+        $scope.displayParams.end = $scope.end;
+
+          $scope.displayParams.latMin = $scope.truncateFloat($scope.displayParams.latMin);
+          $scope.displayParams.latMax = $scope.truncateFloat($scope.displayParams.latMax);
+          $scope.displayParams.lonMin = $scope.truncateFloat($scope.displayParams.lonMin);
+          $scope.displayParams.lonMax = $scope.truncateFloat($scope.displayParams.lonMax);
+
+      $scope.$apply();
+      $rootScope.$broadcast('redrawOverlays', []);
+    }
+
+    $scope.unwatchDatasets = $scope.$watch('datasets', 
+      function() { 
+        var numDatasets = $scope.datasets.length;
+        $scope.displayParams.areValid = false;
+        $scope.areInUserRegridState = false;
+
+        if (numDatasets) {
+          var latMin        = -90,
+            latMax        = 90,
+            lonMin        = -180,
+            lonMax        = 180,
+            start         = "1900-01-01 00:00:00",
+            end           = "2030-01-01 00:00:00",
+            datasetRegrid = false;
+          // Get the valid lat/lon range in the selected datasets.
+          for (var i = 0; i < numDatasets; i++) {
+            var curDataset = $scope.datasets[i];
+    
+            latMin = (curDataset['latlonVals']['latMin'] > latMin) ? curDataset['latlonVals']['latMin'] : latMin;
+            latMax = (curDataset['latlonVals']['latMax'] < latMax) ? curDataset['latlonVals']['latMax'] : latMax;
+            lonMin = (curDataset['latlonVals']['lonMin'] > lonMin) ? curDataset['latlonVals']['lonMin'] : lonMin;
+            lonMax = (curDataset['latlonVals']['lonMax'] < lonMax) ? curDataset['latlonVals']['lonMax'] : lonMax;
+            start = (curDataset['timeVals']['start'] > start) ? curDataset['timeVals']['start'] : start;
+            end = (curDataset['timeVals']['end'] < end) ? curDataset['timeVals']['end'] : end;
+
+            datasetRegrid = datasetRegrid || curDataset.regrid;
+
+          }
+
+          $scope.areInUserRegridState = !datasetRegrid
+        }
+
+        // Update the display parameters with the new valid overlap that we've found!
+        $scope.displayParams.latMin = $scope.truncateFloat(latMin);
+        $scope.displayParams.latMax = $scope.truncateFloat(latMax);
+        $scope.displayParams.lonMin = $scope.truncateFloat(lonMin);
+        $scope.displayParams.lonMax = $scope.truncateFloat(lonMax);
+        $scope.displayParams.start = (typeof start == 'undefined') ? "" : start.split(" ")[0];
+        $scope.displayParams.end = (typeof end == 'undefined') ? "" : end.split(" ")[0];
+
+        // Update the local store values!
+        $scope.latMin = latMin;
+        $scope.latMax = latMax;
+        $scope.lonMin = lonMin;
+        $scope.lonMax = lonMax;
+        $scope.start = (typeof start == 'undefined') ? "" : start.split(" ")[0];
+        $scope.end = (typeof end == 'undefined') ? "" : end.split(" ")[0];
+
+        $scope.displayParams.areValid = true;
+        $rootScope.$broadcast('redrawOverlays', []);
+      }, true);
+
+      $scope.truncateFloat = function(floatVal) {
+          if (floatVal > 0) {
+              return Math.floor(floatVal);
+          } else {
+              return Math.ceil(floatVal);
+          }
+      };
+  }]);

http://git-wip-us.apache.org/repos/asf/climate/blob/652ea657/ocw-ui/frontend/app/scripts/controllers/rcmedselection.js
----------------------------------------------------------------------
diff --git a/ocw-ui/frontend/app/scripts/controllers/rcmedselection.js b/ocw-ui/frontend/app/scripts/controllers/rcmedselection.js
new file mode 100644
index 0000000..a3b3801
--- /dev/null
+++ b/ocw-ui/frontend/app/scripts/controllers/rcmedselection.js
@@ -0,0 +1,144 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+'use strict';
+
+/**
+ * @ngdoc function
+ * @name ocwUiApp.controller:RcmedSelectionCtrl
+ * @description
+ * # RcmedSelectionCtrl
+ * Controller of the ocwUiApp
+ */
+angular.module('ocwUiApp')
+  .controller('RcmedSelectionCtrl', ['$rootScope', '$scope', '$http', '$timeout', 'selectedDatasetInformation',
+    function($rootScope, $scope, $http, $timeout, selectedDatasetInformation) {
+      // Grab a copy of the datasets so we can display a count to the user!
+      $scope.datasetCount = selectedDatasetInformation.getDatasets();
+      $scope.fileAdded = false;
+
+      $scope.getObservations = function() {
+        $http.jsonp($rootScope.baseURL + '/rcmed/datasets/?callback=JSON_CALLBACK').
+          success(function(data) {
+            $scope.availableObs = data;
+            $scope.availableObs.splice(0, 0, {longname: 'Please select an option'});
+            $scope.datasetSelection = $scope.availableObs[0];
+          }).
+          error(function(data) {
+            $scope.availableObs = ["Unable to query RCMED"]
+          });
+      };
+
+      $scope.getObservationBounds = function() {
+        $scope.observationBounds = {};
+
+        $http.get($rootScope.baseURL + '/rcmed/parameters/bounds/')
+          .success(function(data) {
+              $scope.observationBounds = data;
+              $scope.observationBounds['default'] = {
+                  'start': '1900-01-01 00:00:00',
+                  'end': '2050-01-01 00:00:00',
+                  'latMin': -90,
+                  'latMax': 89,
+                  'lonMin': -180,
+                  'lonMax': 179,
+              };
+          })
+          .error(function(data) {
+              $scope.observationBounds['default'] = {
+                  'start': '1900-01-01 00:00:00',
+                  'end': '2050-01-01 00:00:00',
+                  'latMin': -90,
+                  'latMax': 89,
+                  'lonMin': -180,
+                  'lonMax': 179,
+              };
+          });
+      };
+
+      $scope.getBoundsByParameterId = function(parameterId) {
+        if (parameterId in $scope.observationBounds) {
+          return $scope.observationBounds[parameterId];
+        } else {
+          return $scope.observationBounds['default'];
+        }
+      };
+
+      $scope.dataSelectUpdated = function() {
+        var urlString = $rootScope.baseURL + '/rcmed/parameters/?dataset=' +
+                        $scope.datasetSelection["shortname"] +
+                        "&callback=JSON_CALLBACK";
+        $http.jsonp(urlString)
+          .success(function(data) {
+            $scope.retrievedObsParams = data;
+            if ($scope.retrievedObsParams.length > 1)
+              $scope.retrievedObsParams.splice(0, 0, {shortname: 'Please select a parameter'});
+            $scope.parameterSelection = $scope.retrievedObsParams[0];
+          });
+      };
+
+      $scope.addObservation = function() {
+        var newDataset = {};
+
+        newDataset['isObs'] = 1;
+        // Save the dataset id (the important part) and name (for display purposes)
+        newDataset['datasetId'] = $scope.datasetSelection['dataset_id'];
+        newDataset['name'] = $scope.datasetSelection['longname'];
+        // Save the parameter id (the important part) and name (for display purposes)
+        newDataset['id']    = $scope.parameterSelection['parameter_id'];
+        newDataset['param'] = $scope.parameterSelection['parameter_id'];
+        newDataset['paramName'] = $scope.parameterSelection['longname'];
+
+        var bounds = $scope.getBoundsByParameterId(newDataset['id']);
+        newDataset['latlonVals'] = {
+          'latMin': bounds['lat_min'],
+          'latMax': bounds['lat_max'],
+          'lonMin': bounds['lon_min'],
+          'lonMax': bounds['lon_max'],
+        };
+        newDataset['timeVals'] = {
+          'start': bounds['start_date'],
+          'end': bounds['end_date'],
+        };
+
+        // Set some defaults for lat/lon/time variable names. This just helps
+        // us display stuff later.
+        newDataset['lat'] = "N/A";
+        newDataset['lon'] = "N/A";
+        newDataset['time'] = "N/A";
+
+        selectedDatasetInformation.addDataset(newDataset);
+
+        // Clear the user selections by requery-ing RCMED. This is really hacky, but it works for now...
+        $scope.availableObs = [];
+        $scope.retrievedObsParams = [];
+        $scope.getObservations();
+
+        // Display a confirmation message for a little bit
+        $scope.fileAdded = true;
+        $timeout(function() {
+          $scope.fileAdded = false;
+        }, 2000);
+      };
+
+      // Grab the available observations from RCMED
+      $scope.getObservations();
+      $scope.getObservationBounds();
+    }
+  ]);

http://git-wip-us.apache.org/repos/asf/climate/blob/652ea657/ocw-ui/frontend/app/scripts/controllers/result.js
----------------------------------------------------------------------
diff --git a/ocw-ui/frontend/app/scripts/controllers/result.js b/ocw-ui/frontend/app/scripts/controllers/result.js
new file mode 100644
index 0000000..39b94b9
--- /dev/null
+++ b/ocw-ui/frontend/app/scripts/controllers/result.js
@@ -0,0 +1,47 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+'use strict';
+
+/**
+ * @ngdoc function
+ * @name ocwUiApp.controller:ResultCtrl
+ * @description
+ * # ResultCtrl
+ * Controller of the ocwUiApp
+ */
+angular.module('ocwUiApp')
+.controller('ResultCtrl', ['$rootScope', '$scope', '$http',
+function($rootScope, $scope, $http) {
+
+    $scope.results = [];
+
+    // Get all evaluation directories
+    $http.jsonp($rootScope.baseURL + '/dir/results/?callback=JSON_CALLBACK')
+    .success(function(data) {
+      data = data['listing']
+
+      var cacheDirIndex = data.indexOf("/cache");
+      if (cacheDirIndex > -1) {
+        data.split(cacheDirIndex, 1)
+      }
+
+      $scope.results = data.sort().reverse();
+    });
+}]);

http://git-wip-us.apache.org/repos/asf/climate/blob/652ea657/ocw-ui/frontend/app/scripts/controllers/resultdetail.js
----------------------------------------------------------------------
diff --git a/ocw-ui/frontend/app/scripts/controllers/resultdetail.js b/ocw-ui/frontend/app/scripts/controllers/resultdetail.js
new file mode 100644
index 0000000..952516c
--- /dev/null
+++ b/ocw-ui/frontend/app/scripts/controllers/resultdetail.js
@@ -0,0 +1,46 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+'use strict';
+
+/**
+ * @ngdoc function
+ * @name ocwUiApp.controller:ResultDetailCtrl
+ * @description
+ * # ResultDetailCtrl
+ * Controller of the ocwUiApp
+ */
+angular.module('ocwUiApp')
+.controller('ResultDetailCtrl', ['$rootScope', '$scope', '$http', '$stateParams',
+function($rootScope, $scope, $http, $stateParams) {
+	$scope.result = $stateParams.resultId;
+	
+	$http.jsonp($rootScope.baseURL + '/dir/results/' + $scope.result + '?callback=JSON_CALLBACK')
+	.success(function(data) {
+		data = data['listing'];
+
+		if (data.length < 1) {
+			$scope.figures = null;
+			$scope.alertMessage = "No results found.";
+			$scope.alertClass = "alert alert-danger";
+		} else {
+			$scope.figures = data;
+		}
+	});
+}]);

http://git-wip-us.apache.org/repos/asf/climate/blob/652ea657/ocw-ui/frontend/app/scripts/controllers/settings.js
----------------------------------------------------------------------
diff --git a/ocw-ui/frontend/app/scripts/controllers/settings.js b/ocw-ui/frontend/app/scripts/controllers/settings.js
new file mode 100644
index 0000000..ca62fd8
--- /dev/null
+++ b/ocw-ui/frontend/app/scripts/controllers/settings.js
@@ -0,0 +1,34 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+'use strict';
+
+/**
+ * @ngdoc function
+ * @name ocwUiApp.controller:SettingsCtrl
+ * @description
+ * # SettingsCtrl
+ * Controller of the ocwUiApp
+ */
+angular.module('ocwUiApp')
+.controller('SettingsCtrl', ['$scope', 'evaluationSettings', 'selectedDatasetInformation',
+function($scope, evaluationSettings, selectedDatasetInformation) {
+	$scope.settings = evaluationSettings.getSettings();
+	$scope.datasets = selectedDatasetInformation.getDatasets();
+}]);

http://git-wip-us.apache.org/repos/asf/climate/blob/652ea657/ocw-ui/frontend/app/scripts/controllers/timeline.js
----------------------------------------------------------------------
diff --git a/ocw-ui/frontend/app/scripts/controllers/timeline.js b/ocw-ui/frontend/app/scripts/controllers/timeline.js
new file mode 100644
index 0000000..2546ede
--- /dev/null
+++ b/ocw-ui/frontend/app/scripts/controllers/timeline.js
@@ -0,0 +1,103 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+'use strict';
+
+/**
+ * @ngdoc function
+ * @name ocwUiApp.controller:TimelineCtrl
+ * @description
+ * # TimelineCtrl
+ * Controller of the ocwUiApp
+ */
+angular.module('ocwUiApp')
+.controller('TimelineCtrl', ['$rootScope', '$scope', 'selectedDatasetInformation', 'regionSelectParams',
+function($rootScope, $scope, selectedDatasetInformation, regionSelectParams) {
+	$scope.datasets = selectedDatasetInformation.getDatasets();
+	$scope.regionParams = regionSelectParams.getParameters();
+
+	$scope.updateTimeline = function() {
+ 		// Clear timeline data if it exists
+ 		if ("timeline" in $rootScope) {
+ 			$rootScope.timeline.deleteAllItems();
+ 		}
+
+		// Don't process if no datasets have been added
+		if ($scope.datasets.length == 0 || !("timeline" in $rootScope))
+			return;
+ 		
+		// Create DataTable to add data to timeline
+		var data = new google.visualization.DataTable();
+		data.addColumn('datetime', 'start');
+		data.addColumn('datetime', 'end');
+		data.addColumn('string', 'content');
+
+		// Loop through datasets and find the overlapping start/end time range
+		var start = $scope.datasets[0].timeVals.start;
+		var end = $scope.datasets[0].timeVals.end;
+		for (var i = 0; i < $scope.datasets.length; i++) {
+			var possibleNewStart = $scope.datasets[i].timeVals.start;
+			var possibleNewEnd = $scope.datasets[i].timeVals.end;
+
+			start = (possibleNewStart > start) ? possibleNewStart : start;
+			end = (possibleNewEnd < end) ? possibleNewEnd : end;
+		}
+
+		// Set the timeline extent to the overlapping time range
+		//
+		// NOTE: The month value substring is expected to be 0-based (hence the -1)
+		$rootScope.timeline.setVisibleChartRange(new Date(start.substr(0, 4), start.substr(5, 2) - 1, start.substr(8, 2)),
+												 new Date(end.substr(0, 4), end.substr(5, 2) - 1, end.substr(8, 2)));
+
+		// Add user selected bounds to timeline
+		if ($scope.regionParams.areValid) {
+
+			var userStart 	= $scope.regionParams.start;
+			var userEnd 	= $scope.regionParams.end;
+
+			// Add color to user selected bounds
+			var style = 'background-color: #000000; border: 2px solid;';
+			var ocwBar = '<div class="ocw-bar timeline-event-range" style="' + style + '"></div>';
+			
+			// Add row to DataTable: object with start and end date
+			// note: subtract one from month since indexes from 0 to 11
+			data.addRow([new Date(userStart.substr(0,4), userStart.substr(5,2)-1, userStart.substr(8,2)), 
+						new Date(userEnd.substr(0,4), userEnd.substr(5,2)-1, userEnd.substr(8,2)),
+						ocwBar ]);
+		}
+		
+		var options = {
+				"width": "100%",
+				"showCurrentTime": false,
+				"moveable": false,
+				"zoomable": false,
+		};
+		
+		// Draw timeline with data (DataTable) and options (a name-value map) 
+		$rootScope.timeline.draw(data, options);
+	};
+
+	$scope.$on('redrawOverlays', function(event, parameters) {
+		$scope.updateTimeline();
+	});
+
+	$scope.$watch('datasets', function() {
+		$scope.updateTimeline();
+	}, true);
+}]);

http://git-wip-us.apache.org/repos/asf/climate/blob/652ea657/ocw-ui/frontend/app/scripts/controllers/worldmap.js
----------------------------------------------------------------------
diff --git a/ocw-ui/frontend/app/scripts/controllers/worldmap.js b/ocw-ui/frontend/app/scripts/controllers/worldmap.js
new file mode 100644
index 0000000..0d28d6c
--- /dev/null
+++ b/ocw-ui/frontend/app/scripts/controllers/worldmap.js
@@ -0,0 +1,104 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+'use strict';
+
+/**
+ * @ngdoc function
+ * @name ocwUiApp.controller:WorldMapCtrl
+ * @description
+ * # WorldMapCtrl
+ * Controller of the ocwUiApp
+ */
+angular.module('ocwUiApp')
+.controller('WorldMapCtrl', ['$rootScope', '$scope', 'selectedDatasetInformation', 'regionSelectParams',
+function($rootScope, $scope, selectedDatasetInformation, regionSelectParams) {
+	$scope.datasets = selectedDatasetInformation.getDatasets();
+	$scope.regionParams = regionSelectParams.getParameters();
+
+	$scope.updateMap = function() {
+ 		// Clear Group of layers from map if it exists
+ 		if ("rectangleGroup" in $rootScope) {
+ 			$rootScope.rectangleGroup.clearLayers();
+ 		}
+
+		// Don't process if we don't have any datasets added or if the map doesn't exist!!
+		if ($scope.datasets.length == 0 || !("map" in $rootScope))
+			return;
+ 		
+		// Create a group that we'll draw overlays to
+		$rootScope.rectangleGroup = L.layerGroup();
+		// Add rectangle Group to map
+		$rootScope.rectangleGroup.addTo($rootScope.map);
+
+		// Calculate the overlap region and set the map to show the new overlap
+		var latMin = -90,
+			latMax = 90,
+			lonMin = -180,
+			lonMax = 180;
+
+		// Get the valid lat/lon range in the selected datasets.
+		for (var i = 0; i < selectedDatasetInformation.getDatasetCount(); i++) {
+			var curDataset = $scope.datasets[i];
+
+			latMin = (curDataset['latlonVals']['latMin'] > latMin) ? curDataset['latlonVals']['latMin'] : latMin;
+			latMax = (curDataset['latlonVals']['latMax'] < latMax) ? curDataset['latlonVals']['latMax'] : latMax;
+			lonMin = (curDataset['latlonVals']['lonMin'] > lonMin) ? curDataset['latlonVals']['lonMin'] : lonMin;
+			lonMax = (curDataset['latlonVals']['lonMax'] < lonMax) ? curDataset['latlonVals']['lonMax'] : lonMax;
+		}
+
+		var overlapBounds = [[latMax, lonMin], [latMin, lonMax]];
+		$rootScope.map.fitBounds(overlapBounds, {padding: [0, 0]});
+
+		// Draw border around overlap region
+		var overlapBorder = L.rectangle(overlapBounds, {
+			color: '#000000',
+			opacity: 1.0,
+			fill: false,
+			weight: 2,
+			dashArray: "10 10",
+		});
+
+		$rootScope.rectangleGroup.addLayer(overlapBorder);
+
+		// Draw user selected region
+		if ($scope.regionParams.areValid) {
+
+			var bounds = [[$scope.regionParams.latMax, $scope.regionParams.lonMin],
+						  [$scope.regionParams.latMin, $scope.regionParams.lonMax]];
+
+			var polygon = L.rectangle(bounds, {
+				color: '#000000',
+				opacity: .3,
+				stroke: false,
+				fill: true,
+			});
+
+			$rootScope.rectangleGroup.addLayer(polygon);
+		}
+	};
+
+	$scope.$on('redrawOverlays', function(event, parameters) {
+		$scope.updateMap();
+	});
+
+	$scope.$watch('datasets', function() {
+		$scope.updateMap();
+	}, true);
+}]);

http://git-wip-us.apache.org/repos/asf/climate/blob/652ea657/ocw-ui/frontend/app/scripts/directives/bootstrapmodal.js
----------------------------------------------------------------------
diff --git a/ocw-ui/frontend/app/scripts/directives/bootstrapmodal.js b/ocw-ui/frontend/app/scripts/directives/bootstrapmodal.js
new file mode 100644
index 0000000..26d0a46
--- /dev/null
+++ b/ocw-ui/frontend/app/scripts/directives/bootstrapmodal.js
@@ -0,0 +1,79 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+'use strict';
+
+/**
+ * @ngdoc directive
+ * @name ocwUiApp.directive:bootstrapModal
+ * @description
+ * # bootstrapModal
+ */
+angular.module('ocwUiApp')
+.directive('bootstrapModal', function($timeout) {
+	var link = function(scope, elem, attrs) {
+		var escapeEvent;
+		var openModal;
+		var closeModal;
+
+		escapeEvent = function(e) {
+			if (e.which == 27)
+				closeModal();
+		}
+
+		openModal = function(event, toggleBackground, toggleKeyboardEscape) {
+			// Grab the current modal tag based on the modalId attribute in the bootstrapModal tag
+			var modal = $('#' + attrs.modalId);
+
+			// Make all the modal's children of class "close" call the appropriate function for closing!
+			$('.close', modal).bind('click', closeModal);
+
+			modal.modal({
+				show: true,
+				backdrop: toggleBackground,
+				keyboard: toggleKeyboardEscape,
+			});
+		};
+
+		closeModal = function(event) {
+			$('#' + attrs.modalId).modal('hide');
+			
+		};
+
+		// We need to bind the close and open modal events so outside elements can trigger the modal.
+		// This has to wait until the template has been fully inserted, so just wait a bit of time
+		// before we set them. I'm sure there's a better way of handling this...
+		$timeout(function() {
+			$('#' + attrs.modalId).
+				bind('modalOpen', openModal).
+				bind('modalClose', closeModal);
+		}, 100);
+	};
+
+	return {
+		link: link,
+		replace: true,
+		restrict: 'E',
+		scope: {
+			modalId: '@' 
+		},
+		template: '<div id="{{modalId}}" class="modal hide fade" tabindex="-1"><div ng-transclude></div></div>',
+		transclude: true
+	};
+});

http://git-wip-us.apache.org/repos/asf/climate/blob/652ea657/ocw-ui/frontend/app/scripts/directives/bootstrapmodalopen.js
----------------------------------------------------------------------
diff --git a/ocw-ui/frontend/app/scripts/directives/bootstrapmodalopen.js b/ocw-ui/frontend/app/scripts/directives/bootstrapmodalopen.js
new file mode 100644
index 0000000..dca4005
--- /dev/null
+++ b/ocw-ui/frontend/app/scripts/directives/bootstrapmodalopen.js
@@ -0,0 +1,43 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+'use strict';
+
+/**
+ * @ngdoc directive
+ * @name ocwUiApp.directive:bootstrapModalOpen
+ * @description
+ * # bootstrapModalOpen
+ */
+angular.module('ocwUiApp')
+.directive('bootstrapModalOpen', function() {
+	return {
+		restrict: 'A',
+		link: function(scope, elem, attrs) {
+			// Default to showing the background if the user didn't specify a value for this.
+			var hasBackground = (attrs.background === undefined ? true : (attrs.background == "true"));
+			// Enable keyboard closing of modal with escape key.
+			var hasKeyboardEscape = (attrs.keyboard === undefined ? true : (attrs.keyboard == "true"));
+
+			$(elem).bind('click', function() {
+				$('#' + attrs.bootstrapModalOpen).trigger('modalOpen', [hasBackground, hasKeyboardEscape]);
+			});
+		}
+	};
+});

http://git-wip-us.apache.org/repos/asf/climate/blob/652ea657/ocw-ui/frontend/app/scripts/directives/leafletmap.js
----------------------------------------------------------------------
diff --git a/ocw-ui/frontend/app/scripts/directives/leafletmap.js b/ocw-ui/frontend/app/scripts/directives/leafletmap.js
new file mode 100644
index 0000000..9b0a6eb
--- /dev/null
+++ b/ocw-ui/frontend/app/scripts/directives/leafletmap.js
@@ -0,0 +1,46 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+'use strict';
+
+/**
+ * @ngdoc directive
+ * @name ocwUiApp.directive:leafletMap
+ * @description
+ * # leafletMap
+ */
+angular.module('ocwUiApp')
+.directive('leafletMap', function($rootScope) {
+	return {
+		restrict: 'E',
+		replace: true,
+		template: '<div></div>',
+		link: function(scope, element, attrs) {
+			$rootScope.map = L.map(attrs.id, {
+				center: [40, 0],
+				zoom: 2,
+				scrollWheelZoom: false,
+				attributionControl: false,
+				worldCopyJump: true,
+			});
+
+			L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {}).addTo($rootScope.map);
+		}
+	};
+});


Mime
View raw message