trafficcontrol-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From dewr...@apache.org
Subject [2/2] incubator-trafficcontrol git commit: adds crud apis for managing steering targets and hooks it into traffic portal
Date Tue, 11 Jul 2017 15:15:44 GMT
adds crud apis for managing steering targets and hooks it into traffic portal


Project: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/commit/d851910a
Tree: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/tree/d851910a
Diff: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/diff/d851910a

Branch: refs/heads/master
Commit: d851910a37c4689241ebce3a8ccb0a96562fd831
Parents: 7d08839
Author: Jeremy Mitchell <mitchell852@gmail.com>
Authored: Wed Jul 5 10:05:43 2017 -0600
Committer: Dewayne Richardson <dewrich@apache.org>
Committed: Tue Jul 11 09:15:49 2017 -0600

----------------------------------------------------------------------
 docs/source/development/traffic_ops.rst         |   1 +
 .../traffic_ops_api/v12/steering_target.rst     | 324 +++++++++++++++++++
 traffic_ops/app/db/seeds.sql                    |   5 +
 .../app/lib/API/DeliveryService/Steering.pm     |   4 +-
 .../lib/API/DeliveryService/SteeringTarget.pm   | 250 ++++++++++++++
 traffic_ops/app/lib/Fixtures/Type.pm            |  29 +-
 .../app/lib/Schema/Result/SteeringTarget.pm     |   6 +-
 traffic_ops/app/lib/TrafficOpsRoutes.pm         |   6 +
 traffic_ops/app/t/api/1.2/steering_target.t     |  87 +++++
 traffic_portal/app/src/app.js                   |   8 +
 .../src/common/api/DeliveryServiceService.js    |  55 +++-
 .../FormDeliveryServiceController.js            |   4 +
 .../form.deliveryService.Steering.tpl.html      |   2 +-
 .../FormDeliveryServiceTargetController.js      |  57 ++++
 .../FormEditDeliveryServiceTargetController.js  |  69 ++++
 .../form/deliveryServiceTarget/edit/index.js    |  21 ++
 .../form.deliveryServiceTarget.tpl.html         |  75 +++++
 .../modules/form/deliveryServiceTarget/index.js |  21 ++
 .../FormNewDeliveryServiceTargetController.js   |  39 +++
 .../form/deliveryServiceTarget/new/index.js     |  21 ++
 .../TableDeliveryServiceTargetsController.js    |  51 +++
 .../table/deliveryServiceTargets/index.js       |  21 ++
 .../table.deliveryServiceTargets.tpl.html       |  55 ++++
 .../targets/DeliveryServiceTargetsController.js |  24 ++
 .../targets/deliveryServiceTargets.tpl.html     |  22 ++
 .../deliveryServices/targets/edit/index.js      |  42 +++
 .../configure/deliveryServices/targets/index.js |  36 +++
 .../deliveryServices/targets/list/index.js      |  42 +++
 .../deliveryServices/targets/new/index.js       |  45 +++
 traffic_portal/app/src/styles/main.scss         |   7 +
 30 files changed, 1420 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/d851910a/docs/source/development/traffic_ops.rst
----------------------------------------------------------------------
diff --git a/docs/source/development/traffic_ops.rst b/docs/source/development/traffic_ops.rst
index faa2853..b18bc26 100644
--- a/docs/source/development/traffic_ops.rst
+++ b/docs/source/development/traffic_ops.rst
@@ -629,6 +629,7 @@ API 1.2 Reference
   traffic_ops_api/v12/server
   traffic_ops_api/v12/static_dns
   traffic_ops_api/v12/status
+  traffic_ops_api/v12/steering_target
   traffic_ops_api/v12/system
   traffic_ops_api/v12/tenant
   traffic_ops_api/v12/to_extension

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/d851910a/docs/source/development/traffic_ops_api/v12/steering_target.rst
----------------------------------------------------------------------
diff --git a/docs/source/development/traffic_ops_api/v12/steering_target.rst b/docs/source/development/traffic_ops_api/v12/steering_target.rst
new file mode 100644
index 0000000..5e72f85
--- /dev/null
+++ b/docs/source/development/traffic_ops_api/v12/steering_target.rst
@@ -0,0 +1,324 @@
+..
+..
+.. 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.
+..
+
+.. _to-api-v12-steering-targets:
+
+Steering Targets
+================
+
+.. _to-api-v12-steering-target-route:
+
+**GET /api/1.2/steering/:dsId/targets**
+
+  Get all targets for a steering delivery service.
+
+  Authentication Required: Yes
+
+  Role(s) Required: None
+
+  **Request Route Parameters**
+
+  +-------------+----------+---------------------------------------------+
+  |   Name      | Required |                Description                  |
+  +=============+==========+=============================================+
+  | ``dsId``    |   yes    | DS ID.                                      |
+  +-------------+----------+---------------------------------------------+
+
+  **Response Properties**
+
+  +----------------------+--------+-------------------------------------------------+
+  | Parameter            | Type   | Description                                     |
+  +======================+========+=================================================+
+  |``deliveryServiceId`` |  int   | DS ID                                           |
+  +----------------------+--------+-------------------------------------------------+
+  |``deliveryService``   | string | DS XML ID                                       |
+  +----------------------+--------+-------------------------------------------------+
+  |``targetId``          |  int   | Target DS ID                                    |
+  +----------------------+--------+-------------------------------------------------+
+  |``target``            | string | Target DS XML ID                                |
+  +----------------------+--------+-------------------------------------------------+
+  |``value``             |  int   | Value is weight or order depending on type      |
+  +----------------------+--------+-------------------------------------------------+
+  |``typeId``            |  int   | Steering target type ID                         |
+  +----------------------+--------+-------------------------------------------------+
+  |``type``              | string | Steering target type name                       |
+  +----------------------+--------+-------------------------------------------------+
+
+  **Response Example** ::
+
+    {
+     "response": [
+        {
+           "deliveryServiceId": 1
+           "deliveryService": "steering-ds-one",
+           "targetId": 2,
+           "target": "steering-target-one",
+           "value": 1,
+           "typeId": 35,
+           "type": "STEERING_ORDER"
+        },
+        {
+           "deliveryServiceId": 1
+           "deliveryService": "steering-ds-one",
+           "targetId": 3,
+           "target": "steering-target-two",
+           "value": 2,
+           "typeId": 35,
+           "type": "STEERING_ORDER"
+        },
+     ]
+    }
+
+|
+
+**GET /api/1.2/steering/:dsId/targets/:targetId**
+
+  Get a steering target.
+
+  Authentication Required: Yes
+
+  Role(s) Required: None
+
+  **Request Route Parameters**
+
+  +-------------+----------+---------------------------------------------+
+  |   Name      | Required |                Description                  |
+  +=============+==========+=============================================+
+  | ``dsId``    |   yes    | DS ID.                                      |
+  +-------------+----------+---------------------------------------------+
+  | ``targetId``|   yes    | DS Target ID.                               |
+  +-------------+----------+---------------------------------------------+
+
+  **Response Properties**
+
+  +----------------------+--------+-------------------------------------------------+
+  | Parameter            | Type   | Description                                     |
+  +======================+========+=================================================+
+  |``deliveryServiceId`` |  int   | DS ID                                           |
+  +----------------------+--------+-------------------------------------------------+
+  |``deliveryService``   | string | DS XML ID                                       |
+  +----------------------+--------+-------------------------------------------------+
+  |``targetId``          |  int   | Target DS ID                                    |
+  +----------------------+--------+-------------------------------------------------+
+  |``target``            | string | Target DS XML ID                                |
+  +----------------------+--------+-------------------------------------------------+
+  |``value``             |  int   | Value is weight or order depending on type      |
+  +----------------------+--------+-------------------------------------------------+
+  |``typeId``            |  int   | Steering target type ID                         |
+  +----------------------+--------+-------------------------------------------------+
+  |``type``              | string | Steering target type name                       |
+  +----------------------+--------+-------------------------------------------------+
+
+  **Response Example** ::
+
+    {
+     "response": [
+        {
+           "deliveryServiceId": 1
+           "deliveryService": "steering-ds-one",
+           "targetId": 2,
+           "target": "steering-target-one",
+           "value": 1,
+           "typeId": 35,
+           "type": "STEERING_ORDER"
+        }
+     ]
+    }
+
+|
+
+
+**PUT /api/1.2/steering/:dsId/targets/:targetId**
+
+  Update a steering target.
+
+  Authentication Required: Yes
+
+  Role(s) Required: Admin
+
+  **Request Route Parameters**
+
+  +-------------+----------+---------------------------------------------+
+  |   Name      | Required |                Description                  |
+  +=============+==========+=============================================+
+  | ``dsId``    |   yes    | DS ID.                                      |
+  +-------------+----------+---------------------------------------------+
+  | ``targetId``|   yes    | DS Target ID.                               |
+  +-------------+----------+---------------------------------------------+
+
+  **Request Properties**
+
+  +------------------------+----------+--------------------------+
+  | Parameter              | Required | Description              |
+  +========================+==========+==========================+
+  | ``deliveryServiceId``  | yes      | Steering DS ID           |
+  +------------------------+----------+--------------------------+
+  | ``targetId``           | yes      | Target DS ID             |
+  +------------------------+----------+--------------------------+
+  | ``value``              | yes      | Target value             |
+  +------------------------+----------+--------------------------+
+  | ``typeId``             | yes      | Target type ID           |
+  +------------------------+----------+--------------------------+
+
+  **Request Example** ::
+
+    {
+        "deliveryServiceId": 1
+        "targetId": 2
+        "value": 34,
+        "typeId": 46,
+    }
+
+|
+
+  **Response Properties**
+
+  +------------------------+----------+--------------------------+
+  | Parameter              | Type     | Description              |
+  +========================+==========+==========================+
+  | ``deliveryServiceId``  | int      | Steering DS ID           |
+  +------------------------+----------+--------------------------+
+  | ``targetId``           | int      | Target DS ID             |
+  +------------------------+----------+--------------------------+
+  | ``value``              | string   | Target value             |
+  +------------------------+----------+--------------------------+
+  | ``typeId``             | int      | Target type ID           |
+  +------------------------+----------+--------------------------+
+
+  **Response Example** ::
+
+	{
+		"response": {
+			"deliveryServiceId": 1,
+			"targetId": 2,
+			"value": "34",
+			"typeId": 45
+		},
+		"alerts": [
+			{
+				"level": "success",
+				"text": "Delivery service steering target update was successful."
+			}
+		]
+	}
+
+|
+
+
+**POST /api/1.2/steering/:dsId/targets**
+
+  Create a steering target.
+
+  Authentication Required: Yes
+
+  Role(s) Required: Admin
+
+  **Request Route Parameters**
+
+  +-------------+----------+---------------------------------------------+
+  |   Name      | Required |                Description                  |
+  +=============+==========+=============================================+
+  | ``dsId``    |   yes    | DS ID.                                      |
+  +-------------+----------+---------------------------------------------+
+
+  **Request Properties**
+
+  +------------------------+----------+--------------------------+
+  | Parameter              | Required | Description              |
+  +========================+==========+==========================+
+  | ``deliveryServiceId``  | yes      | Steering DS ID           |
+  +------------------------+----------+--------------------------+
+  | ``targetId``           | yes      | Target DS ID             |
+  +------------------------+----------+--------------------------+
+  | ``value``              | yes      | Target value             |
+  +------------------------+----------+--------------------------+
+  | ``typeId``             | yes      | Target type ID           |
+  +------------------------+----------+--------------------------+
+gi
+  **Request Example** ::
+
+    {
+        "deliveryServiceId": 1
+        "targetId": 6
+        "value": 22,
+        "typeId": 47,
+    }
+
+|
+
+  **Response Properties**
+
+  +------------------------+----------+--------------------------+
+  | Parameter              | Type     | Description              |
+  +========================+==========+==========================+
+  | ``deliveryServiceId``  | int      | Steering DS ID           |
+  +------------------------+----------+--------------------------+
+  | ``targetId``           | int      | Target DS ID             |
+  +------------------------+----------+--------------------------+
+  | ``value``              | string   | Target value             |
+  +------------------------+----------+--------------------------+
+  | ``typeId``             | int      | Target type ID           |
+  +------------------------+----------+--------------------------+
+
+  **Response Example** ::
+
+	{
+		"response": {
+			"deliveryServiceId": 1,
+			"targetId": 6,
+			"value": "22",
+			"typeId": 47
+		},
+		"alerts": [
+			{
+				"level": "success",
+				"text": "Delivery service target creation was successful."
+			}
+		]
+	}
+
+|
+
+**DELETE /api/1.2/steering/:dsId/targets/:targetId**
+
+  Delete a steering target.
+
+  Authentication Required: Yes
+
+  Role(s) Required:  Admin
+
+  **Request Route Parameters**
+
+  +-------------+----------+---------------------------------------------+
+  |   Name      | Required |                Description                  |
+  +=============+==========+=============================================+
+  | ``dsId``    |   yes    | DS ID.                                      |
+  +-------------+----------+---------------------------------------------+
+  | ``targetId``|   yes    | DS Target ID.                               |
+  +-------------+----------+---------------------------------------------+
+
+  **Response Example** ::
+
+    {
+          "alerts": [
+                    {
+                            "level": "success",
+                            "text": "Delivery service target delete was successful."
+                    }
+            ],
+    }
+
+|
+

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/d851910a/traffic_ops/app/db/seeds.sql
----------------------------------------------------------------------
diff --git a/traffic_ops/app/db/seeds.sql b/traffic_ops/app/db/seeds.sql
index 55fbfc5..9075f3b 100644
--- a/traffic_ops/app/db/seeds.sql
+++ b/traffic_ops/app/db/seeds.sql
@@ -223,6 +223,11 @@ insert into api_capability (http_method, route, capability) values ('GET', '/int
 insert into api_capability (http_method, route, capability) values ('GET', '/internal/api/*/steering/*', 'ds-steering-read') ON CONFLICT (http_method, route, capability) DO NOTHING; -- 97
 insert into api_capability (http_method, route, capability) values ('POST', '/internal/api/*/steering', 'ds-steering-write') ON CONFLICT (http_method, route, capability) DO NOTHING; -- 98
 insert into api_capability (http_method, route, capability) values ('PUT', '/internal/api/*/steering/*', 'ds-steering-write') ON CONFLICT (http_method, route, capability) DO NOTHING; -- 99
+insert into api_capability (http_method, route, capability) values ('GET', '/api/*/steering/*/targets', 'ds-steering-target-read') ON CONFLICT (http_method, route, capability) DO NOTHING; -- 96
+insert into api_capability (http_method, route, capability) values ('GET', '/api/*/steering/*/targets/*', 'ds-steering-target-read') ON CONFLICT (http_method, route, capability) DO NOTHING; -- 96
+insert into api_capability (http_method, route, capability) values ('POST', '/api/*/steering/*/targets', 'ds-steering-target-write') ON CONFLICT (http_method, route, capability) DO NOTHING; -- 96
+insert into api_capability (http_method, route, capability) values ('PUT', '/api/*/steering/*/targets/*', 'ds-steering-target-write') ON CONFLICT (http_method, route, capability) DO NOTHING; -- 96
+insert into api_capability (http_method, route, capability) values ('DELETE', '/api/*/steering/*/targets/*', 'ds-steering-target-write') ON CONFLICT (http_method, route, capability) DO NOTHING; -- 96
 insert into api_capability (http_method, route, capability) values ('GET', '/api/*/deliveryserviceserver', 'ds-cache-read') ON CONFLICT (http_method, route, capability) DO NOTHING; -- 103
 insert into api_capability (http_method, route, capability) values ('POST', '/api/*/deliveryservices/*/servers', 'ds-cache-write') ON CONFLICT (http_method, route, capability) DO NOTHING; -- 106
 insert into api_capability (http_method, route, capability) values ('GET', '/api/*/deliveryservices_regexes', 'ds-read') ON CONFLICT (http_method, route, capability) DO NOTHING; -- 109

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/d851910a/traffic_ops/app/lib/API/DeliveryService/Steering.pm
----------------------------------------------------------------------
diff --git a/traffic_ops/app/lib/API/DeliveryService/Steering.pm b/traffic_ops/app/lib/API/DeliveryService/Steering.pm
index a6aaa3a..cf146ff 100644
--- a/traffic_ops/app/lib/API/DeliveryService/Steering.pm
+++ b/traffic_ops/app/lib/API/DeliveryService/Steering.pm
@@ -61,7 +61,7 @@ sub find_steering {
         }
 
         my $target_id = $row->target_id;
-        
+
 
         if (! exists($steering{$row->steering_xml_id})) {
             my $ds = $self->db->resultset('Deliveryservice')->search( { xml_id => $row->steering_xml_id } )->single();
@@ -69,7 +69,7 @@ sub find_steering {
             if ($ds->type->name =~ /CLIENT_STEERING/) {
                 $client_steering = '1';
             }
-            else { 
+            else {
                 $client_steering = '0';
             }
             $steering{$row->steering_xml_id} = {"deliveryService" => $row->steering_xml_id, "clientSteering" => \$client_steering};

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/d851910a/traffic_ops/app/lib/API/DeliveryService/SteeringTarget.pm
----------------------------------------------------------------------
diff --git a/traffic_ops/app/lib/API/DeliveryService/SteeringTarget.pm b/traffic_ops/app/lib/API/DeliveryService/SteeringTarget.pm
new file mode 100644
index 0000000..a1601a6
--- /dev/null
+++ b/traffic_ops/app/lib/API/DeliveryService/SteeringTarget.pm
@@ -0,0 +1,250 @@
+package API::DeliveryService::SteeringTarget;
+#
+#
+# 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.
+#
+#
+#
+
+use UI::Utils;
+
+use Mojo::Base 'Mojolicious::Controller';
+use Data::Dumper;
+use JSON;
+use MojoPlugins::Response;
+use Validate::Tiny ':all';
+
+sub index {
+	my $self        = shift;
+	my $steering_id = $self->param('id');
+	my @data;
+
+	my %criteria;
+	$criteria{'deliveryservice'} = $steering_id;
+
+	my $steering_targets = $self->db->resultset('SteeringTarget')->search( \%criteria, { prefetch => [ 'deliveryservice', 'target', 'type' ] } );
+	while ( my $row = $steering_targets->next ) {
+		push(
+			@data, {
+				"deliveryServiceId" => $row->deliveryservice->id,
+				"deliveryService"   => $row->deliveryservice->xml_id,
+				"targetId"          => $row->target->id,
+				"target"            => $row->target->xml_id,
+				"value"             => $row->value,
+				"typeId"            => $row->type->id,
+				"type"              => $row->type->name,
+			}
+		);
+	}
+	$self->success( \@data );
+}
+
+sub show {
+	my $self        = shift;
+	my $steering_id = $self->param('id');
+	my $target_id   = $self->param('target_id');
+
+	my %criteria;
+	$criteria{'deliveryservice'} = $steering_id;
+	$criteria{'target'}          = $target_id;
+
+	my $steering_target = $self->db->resultset('SteeringTarget')->search( \%criteria, { prefetch => [ 'deliveryservice', 'target', 'type' ] } );
+	my @data;
+	while ( my $row = $steering_target->next ) {
+		push(
+			@data, {
+				"deliveryServiceId" => $row->deliveryservice->id,
+				"deliveryService"   => $row->deliveryservice->xml_id,
+				"targetId"          => $row->target->id,
+				"target"            => $row->target->xml_id,
+				"value"             => $row->value,
+				"typeId"            => $row->type->id,
+				"type"              => $row->type->name,
+			}
+		);
+	}
+	$self->success( \@data );
+}
+
+sub update {
+	my $self           = shift;
+	my $steering_ds_id = $self->param('id');
+	my $target_ds_id   = $self->param('target_id');
+	my $params         = $self->req->json;
+
+	if ( !&is_admin($self) ) {
+		return $self->forbidden();
+	}
+
+	my ( $is_valid, $result ) = $self->is_target_valid($params);
+
+	if ( !$is_valid ) {
+		return $self->alert($result);
+	}
+
+	my %criteria;
+	$criteria{'deliveryservice'} = $steering_ds_id;
+	$criteria{'target'}          = $target_ds_id;
+
+	my $steering_target = $self->db->resultset('SteeringTarget')->search( \%criteria )->single();
+	if ( !defined($steering_target) ) {
+		return $self->not_found();
+	}
+
+	my $values = {
+		deliveryservice => $params->{deliveryServiceId},
+		target          => $params->{targetId},
+		value           => $params->{value},
+		type            => $params->{typeId},
+	};
+
+	my $update = $steering_target->update($values);
+
+	if ($update) {
+
+		my $response;
+		$response->{deliveryServiceId} = $params->{deliveryServiceId};
+		$response->{targetId}          = $params->{targetId};
+		$response->{value}             = $params->{value};
+		$response->{typeId}            = $params->{typeId};
+
+		&log( $self, "Updated steering target [ " . $target_ds_id . " ] for deliveryservice: " . $steering_ds_id, "APICHANGE" );
+
+		return $self->success( $response, "Delivery service steering target update was successful." );
+	}
+	else {
+		return $self->alert("Delivery service steering target update failed.");
+	}
+
+}
+
+sub create {
+	my $self   = shift;
+	my $params = $self->req->json;
+
+	if ( !&is_admin($self) ) {
+		return $self->forbidden();
+	}
+
+	my ( $is_valid, $result ) = $self->is_target_valid($params);
+
+	if ( !$is_valid ) {
+		return $self->alert($result);
+	}
+
+	my %criteria;
+	$criteria{'deliveryservice'} = $params->{deliveryservice};
+	$criteria{'target'}          = $params->{target};
+
+	my $existing = $self->db->resultset('SteeringTarget')->search( \%criteria )->single();
+	if ( defined($existing) ) {
+		return $self->alert('Steering target already exists');
+	}
+
+	my $values = {
+		deliveryservice => $params->{deliveryServiceId},
+		target          => $params->{targetId},
+		value           => $params->{value},
+		type            => $params->{typeId},
+	};
+
+	my $insert = $self->db->resultset('SteeringTarget')->create($values)->insert();
+	if ($insert) {
+		my @response;
+		push( @response, {
+				deliveryServiceId => $insert->deliveryservice->id,
+				targetId          => $insert->target->id,
+				value           => $insert->value,
+				typeId            => $insert->type->id,
+			} );
+
+		&log( $self, "Created steering target [ '" . $params->{targetId} . "' ] for delivery service: " . $params->{deliveryServiceId}, "APICHANGE" );
+
+		return $self->success( \@response, "Delivery service target creation was successful." );
+	}
+	else {
+		return $self->alert("Delivery service target creation failed.");
+	}
+
+}
+
+sub delete {
+	my $self           = shift;
+	my $steering_ds_id = $self->param('id');
+	my $target_ds_id   = $self->param('target_id');
+
+	if ( !&is_admin($self) ) {
+		return $self->forbidden();
+	}
+
+	my $target = $self->db->resultset('SteeringTarget')->search( { deliveryservice => $steering_ds_id, target => $target_ds_id } )->single();
+	if ( !defined($target) ) {
+		return $self->not_found();
+	}
+
+	my $delete = $target->delete();
+	if ($delete) {
+
+		&log( $self, "Deleted steering target [ " . $target_ds_id . " ] for deliveryservice: " . $steering_ds_id, "APICHANGE" );
+
+		return $self->success_message("Delivery service target delete was successful.");
+	}
+	else {
+		return $self->alert("Delivery service target delete failed.");
+	}
+
+}
+
+sub is_target_valid {
+	my $self   = shift;
+	my $params = shift;
+
+	if ( !$self->is_valid_target_type( $params->{typeId} ) ) {
+		return ( 0, "Invalid target type" );
+	}
+
+	my $rules = {
+		fields => [qw/deliveryServiceId targetId value typeId/],
+
+		# Validation checks to perform
+		checks => [
+			deliveryServiceId => [ is_required("is required") ],
+			targetId          => [ is_required("is required") ],
+			value             => [ is_required("is required") ],
+			typeId            => [ is_required("is required") ],
+		]
+	};
+
+	# Validate the input against the rules
+	my $result = validate( $params, $rules );
+
+	if ( $result->{success} ) {
+		return ( 1, $result->{data} );
+	}
+	else {
+		return ( 0, $result->{error} );
+	}
+}
+
+sub is_valid_target_type {
+	my $self    = shift;
+	my $type_id = shift;
+
+	my $rs = $self->db->resultset("Type")->find( { id => $type_id } );
+	if ( defined($rs) && ( $rs->use_in_table eq "steering_target" ) ) {
+		return 1;
+	}
+	return 0;
+}
+
+1;

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/d851910a/traffic_ops/app/lib/Fixtures/Type.pm
----------------------------------------------------------------------
diff --git a/traffic_ops/app/lib/Fixtures/Type.pm b/traffic_ops/app/lib/Fixtures/Type.pm
index 5749f88..b265f70 100644
--- a/traffic_ops/app/lib/Fixtures/Type.pm
+++ b/traffic_ops/app/lib/Fixtures/Type.pm
@@ -288,7 +288,34 @@ my %definition_for = (
 			description  => 'Steering Delivery Service',
 			use_in_table => 'deliveryservice',
 		}
-	}
+	},
+	CLIENT_STEERING => {
+		new   => 'Type',
+		using => {
+			id           => 38,
+			name         => 'CLIENT_STEERING',
+			description  => 'Client-Controlled Steering Delivery Service',
+			use_in_table => 'deliveryservice',
+		}
+	},
+	STEERING_WEIGHT => {
+		new   => 'Type',
+		using => {
+			id           => 39,
+			name         => 'STEERING_WEIGHT',
+			description  => 'Weighted steering target',
+			use_in_table => 'steering_target',
+		}
+	},
+	STEERING_ORDER => {
+		new   => 'Type',
+		using => {
+			id           => 40,
+			name         => 'STEERING_ORDER',
+			description  => 'Ordered steering target',
+			use_in_table => 'steering_target',
+		}
+	},
 );
 
 sub get_definition {

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/d851910a/traffic_ops/app/lib/Schema/Result/SteeringTarget.pm
----------------------------------------------------------------------
diff --git a/traffic_ops/app/lib/Schema/Result/SteeringTarget.pm b/traffic_ops/app/lib/Schema/Result/SteeringTarget.pm
index ec67170..96ce401 100644
--- a/traffic_ops/app/lib/Schema/Result/SteeringTarget.pm
+++ b/traffic_ops/app/lib/Schema/Result/SteeringTarget.pm
@@ -103,7 +103,7 @@ __PACKAGE__->belongs_to(
   { is_deferrable => 0, on_delete => "CASCADE", on_update => "CASCADE" },
 );
 
-=head2 deliveryservice_2
+=head2 target
 
 Type: belongs_to
 
@@ -112,9 +112,9 @@ Related object: L<Schema::Result::Deliveryservice>
 =cut
 
 __PACKAGE__->belongs_to(
-  "deliveryservice_2",
+  "target",
   "Schema::Result::Deliveryservice",
-  { id => "deliveryservice" },
+  { id => "target" },
   { is_deferrable => 0, on_delete => "CASCADE", on_update => "CASCADE" },
 );
 

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/d851910a/traffic_ops/app/lib/TrafficOpsRoutes.pm
----------------------------------------------------------------------
diff --git a/traffic_ops/app/lib/TrafficOpsRoutes.pm b/traffic_ops/app/lib/TrafficOpsRoutes.pm
index 84501a4..bb4dbd8 100644
--- a/traffic_ops/app/lib/TrafficOpsRoutes.pm
+++ b/traffic_ops/app/lib/TrafficOpsRoutes.pm
@@ -530,6 +530,12 @@ sub api_routes {
 	$r->post("/internal/api/$version/steering")->over( authenticated => 1 )->to( 'Steering#add', namespace => 'API::DeliveryService' );
 	$r->put("/internal/api/$version/steering/:xml_id")->over( authenticated => 1 )->to( 'Steering#update', namespace => 'API::DeliveryService' );
 
+	$r->get("/api/$version/steering/:id/targets" => [ id => qr/\d+/ ] )->over( authenticated => 1 )->to( 'SteeringTarget#index', namespace => 'API::DeliveryService' );
+	$r->get("/api/$version/steering/:id/targets/:target_id" => [ id => qr/\d+/, target_id => qr/\d+/ ] )->over( authenticated => 1 )->to( 'SteeringTarget#show', namespace => 'API::DeliveryService' );
+	$r->post("/api/$version/steering/:id/targets" => [ id => qr/\d+/ ] )->over( authenticated => 1 )->to( 'SteeringTarget#create', namespace => 'API::DeliveryService' );
+	$r->put("/api/$version/steering/:id/targets/:target_id" => [ id => qr/\d+/, target_id => qr/\d+/ ] )->over( authenticated => 1 )->to( 'SteeringTarget#update', namespace => 'API::DeliveryService' );
+	$r->delete("/api/$version/steering/:id/targets/:target_id" => [ id => qr/\d+/, target_id => qr/\d+/ ] )->over( authenticated => 1 )->to( 'SteeringTarget#delete', namespace => 'API::DeliveryService' );
+
 	# -- DELIVERYSERVICE: SSL KEYS
 	# Support for SSL private keys, certs, and csrs
 	# gets the latest key by default unless a version query param is provided with ?version=x

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/d851910a/traffic_ops/app/t/api/1.2/steering_target.t
----------------------------------------------------------------------
diff --git a/traffic_ops/app/t/api/1.2/steering_target.t b/traffic_ops/app/t/api/1.2/steering_target.t
new file mode 100644
index 0000000..4a3607f
--- /dev/null
+++ b/traffic_ops/app/t/api/1.2/steering_target.t
@@ -0,0 +1,87 @@
+package main;
+#
+#
+# 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.
+#
+use Mojo::Base -strict;
+use Test::More;
+use Test::Mojo;
+use DBI;
+use Schema;
+use Test::TestHelper;
+use Test::MockModule;
+use Test::MockObject;
+use strict;
+use warnings;
+use JSON;
+
+BEGIN { $ENV{MOJO_MODE} = "test" }
+
+my $schema = Schema->connect_to_database;
+my $t      = Test::Mojo->new('TrafficOps');
+
+#unload data for a clean test
+Test::TestHelper->unload_core_data($schema);
+
+#load core test data
+Test::TestHelper->load_core_data($schema);
+
+ok $t->post_ok( '/api/1.1/user/login', json => { u => Test::TestHelper::ADMIN_USER, p => Test::TestHelper::ADMIN_USER_PASSWORD } )->status_is(200),
+    'Log into the admin user?';
+
+ok $t->post_ok('/api/1.2/steering/900/targets' => {Accept => 'application/json'} => json => {
+            "deliveryServiceId" => 900,
+            "targetId" => 1000,
+            "value" => 852,
+            "typeId" => 40
+        })->status_is(200)->or( sub { diag $t->tx->res->content->asset->{content}; } )
+        ->json_is( "/response/0/deliveryServiceId" => 900 )
+        ->json_is( "/response/0/targetId" => 1000 )
+        ->json_is( "/response/0/value" => 852 )
+        ->json_is( "/response/0/typeId" => 40 )
+    , 'Is the steering target created?';
+
+ok $t->get_ok("/api/1.2/steering/900/targets")->status_is(200)->or( sub { diag $t->tx->res->content->asset->{content}; } )
+        ->json_is( "/response/0/deliveryServiceId" => 900 )
+        ->json_is( "/response/0/targetId" => 1000 )
+        ->json_is( "/response/0/value" => 852 )
+        ->json_is( "/response/0/typeId" => 40 )
+    , 'Are steering targets returned?';
+
+$t->get_ok("/api/1.2/steering/900/targets/1000")->status_is(200)->or( sub { diag $t->tx->res->content->asset->{content}; } )
+    ->json_is( "/response/0/deliveryServiceId" => 900 )
+    ->json_is( "/response/0/targetId" => 1000 )
+    ->json_is( "/response/0/value" => 852 )
+    ->json_is( "/response/0/typeId" => 40 )
+    , 'Is the steering target returned?';
+
+ok $t->put_ok('/api/1.2/steering/900/targets/1000' => {Accept => 'application/json'} => json => {
+            "deliveryServiceId" => 900,
+            "targetId" => 1000,
+            "value" => 999,
+            "typeId" => 40
+        })
+        ->status_is(200)->or( sub { diag $t->tx->res->content->asset->{content}; } )
+        ->json_is( "/response/deliveryServiceId" => 900 )
+        ->json_is( "/response/targetId" => 1000 )
+        ->json_is( "/response/value" => 999 )
+        ->json_is( "/response/typeId" => 40 )
+        ->json_is( "/alerts/0/level" => "success" )
+    , 'Did the steering target update?';
+
+ok $t->delete_ok('/api/1.2/steering/900/targets/1000')->status_is(200)->or( sub { diag $t->tx->res->content->asset->{content}; } )
+    , 'Did the steering target get deleted?';
+
+ok $t->get_ok('/logout')->status_is(302)->or( sub { diag $t->tx->res->content->asset->{content}; } );
+
+done_testing();

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/d851910a/traffic_portal/app/src/app.js
----------------------------------------------------------------------
diff --git a/traffic_portal/app/src/app.js b/traffic_portal/app/src/app.js
index 546c9d1..017231f 100644
--- a/traffic_portal/app/src/app.js
+++ b/traffic_portal/app/src/app.js
@@ -144,6 +144,10 @@ var trafficPortal = angular.module('trafficPortal', [
         require('./modules/private/configure/deliveryServices/regexes/new').name,
         require('./modules/private/configure/deliveryServices/servers').name,
         require('./modules/private/configure/deliveryServices/staticDnsEntries').name,
+        require('./modules/private/configure/deliveryServices/targets').name,
+        require('./modules/private/configure/deliveryServices/targets/edit').name,
+        require('./modules/private/configure/deliveryServices/targets/list').name,
+        require('./modules/private/configure/deliveryServices/targets/new').name,
         require('./modules/private/configure/deliveryServices/users').name,
         require('./modules/private/configure/servers').name,
         require('./modules/private/configure/servers/deliveryServices').name,
@@ -191,6 +195,9 @@ var trafficPortal = angular.module('trafficPortal', [
         require('./common/modules/form/deliveryServiceRegex').name,
         require('./common/modules/form/deliveryServiceRegex/edit').name,
         require('./common/modules/form/deliveryServiceRegex/new').name,
+        require('./common/modules/form/deliveryServiceTarget').name,
+        require('./common/modules/form/deliveryServiceTarget/edit').name,
+        require('./common/modules/form/deliveryServiceTarget/new').name,
         require('./common/modules/form/deliveryServiceJob').name,
         require('./common/modules/form/deliveryServiceJob/new').name,
         require('./common/modules/form/division').name,
@@ -243,6 +250,7 @@ var trafficPortal = angular.module('trafficPortal', [
         require('./common/modules/table/deliveryServiceRegexes').name,
         require('./common/modules/table/deliveryServiceServers').name,
         require('./common/modules/table/deliveryServiceStaticDnsEntries').name,
+        require('./common/modules/table/deliveryServiceTargets').name,
         require('./common/modules/table/deliveryServiceUsers').name,
         require('./common/modules/table/divisions').name,
         require('./common/modules/table/divisionRegions').name,

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/d851910a/traffic_portal/app/src/common/api/DeliveryServiceService.js
----------------------------------------------------------------------
diff --git a/traffic_portal/app/src/common/api/DeliveryServiceService.js b/traffic_portal/app/src/common/api/DeliveryServiceService.js
index b653f06..16c5227 100644
--- a/traffic_portal/app/src/common/api/DeliveryServiceService.js
+++ b/traffic_portal/app/src/common/api/DeliveryServiceService.js
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-var DeliveryServiceService = function(Restangular, locationUtils, httpService, messageModel, ENV) {
+var DeliveryServiceService = function(Restangular, $http, $q, locationUtils, httpService, messageModel, ENV) {
 
     this.getDeliveryServices = function(queryParams) {
         return Restangular.all('deliveryservices').getList(queryParams);
@@ -68,6 +68,57 @@ var DeliveryServiceService = function(Restangular, locationUtils, httpService, m
         return Restangular.one('servers', serverId).getList('deliveryservices');
     };
 
+    this.getDeliveryServiceTargets = function(dsId) {
+        return Restangular.one('steering', dsId).getList('targets');
+    };
+
+    this.getDeliveryServiceTarget = function(dsId, targetId) {
+        return Restangular.one('steering', dsId).one('targets', targetId).get();
+    };
+
+    this.updateDeliveryServiceTarget = function(dsId, targetId, target) {
+        var request = $q.defer();
+
+        $http.put(ENV.api['root'] + "steering/" + dsId + "/targets/" + targetId, target)
+            .then(
+                function() {
+                    messageModel.setMessages([ { level: 'success', text: 'Steering target updated' } ], false);
+                    locationUtils.navigateToPath('/configure/delivery-services/' + dsId + '/targets');
+                },
+                function(fault) {
+                    messageModel.setMessages(fault.data.alerts, false);
+                }
+            );
+
+        return request.promise;
+    };
+
+    this.createDeliveryServiceTarget = function(dsId, target) {
+        return Restangular.one('steering', dsId).all('targets').post(target)
+            .then(
+                function() {
+                    messageModel.setMessages([ { level: 'success', text: 'Steering target created' } ], true);
+                    locationUtils.navigateToPath('/configure/delivery-services/' + dsId + '/targets');
+                },
+                function(fault) {
+                    messageModel.setMessages(fault.data.alerts, false);
+                }
+            );
+    };
+
+    this.deleteDeliveryServiceTarget = function(dsId, targetId) {
+        return Restangular.one('steering', dsId).one('targets', targetId).remove()
+            .then(
+                function() {
+                    messageModel.setMessages([ { level: 'success', text: 'Steering target deleted' } ], true);
+                    locationUtils.navigateToPath('/configure/delivery-services/' + dsId + '/targets');
+                },
+                function(fault) {
+                    messageModel.setMessages(fault.data.alerts, true);
+                }
+            );
+    };
+
     this.getUserDeliveryServices = function(userId) {
         return Restangular.one('users', userId).getList('deliveryservices');
     };
@@ -99,5 +150,5 @@ var DeliveryServiceService = function(Restangular, locationUtils, httpService, m
 
 };
 
-DeliveryServiceService.$inject = ['Restangular', 'locationUtils', 'httpService', 'messageModel', 'ENV'];
+DeliveryServiceService.$inject = ['Restangular', '$http', '$q', 'locationUtils', 'httpService', 'messageModel', 'ENV'];
 module.exports = DeliveryServiceService;

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/d851910a/traffic_portal/app/src/common/modules/form/deliveryService/FormDeliveryServiceController.js
----------------------------------------------------------------------
diff --git a/traffic_portal/app/src/common/modules/form/deliveryService/FormDeliveryServiceController.js b/traffic_portal/app/src/common/modules/form/deliveryService/FormDeliveryServiceController.js
index 69d0b89..08a94ed 100644
--- a/traffic_portal/app/src/common/modules/form/deliveryService/FormDeliveryServiceController.js
+++ b/traffic_portal/app/src/common/modules/form/deliveryService/FormDeliveryServiceController.js
@@ -119,6 +119,10 @@ var FormDeliveryServiceController = function(deliveryService, types, $scope, $lo
         { value: 4, label: "4 - Latch on Failover" }
     ];
 
+    $scope.viewTargets = function() {
+        $location.path($location.path() + '/targets');
+    };
+
     $scope.viewServers = function() {
         $location.path($location.path() + '/servers');
     };

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/d851910a/traffic_portal/app/src/common/modules/form/deliveryService/form.deliveryService.Steering.tpl.html
----------------------------------------------------------------------
diff --git a/traffic_portal/app/src/common/modules/form/deliveryService/form.deliveryService.Steering.tpl.html b/traffic_portal/app/src/common/modules/form/deliveryService/form.deliveryService.Steering.tpl.html
index 5f67348..3a895f7 100644
--- a/traffic_portal/app/src/common/modules/form/deliveryService/form.deliveryService.Steering.tpl.html
+++ b/traffic_portal/app/src/common/modules/form/deliveryService/form.deliveryService.Steering.tpl.html
@@ -40,7 +40,7 @@ under the License.
                     <span class="caret"></span>
                 </button>
                 <ul class="dropdown-menu-right dropdown-menu" uib-dropdown-menu>
-                    <li role="menuitem"><a ng-click="viewServers()">View Servers</a></li>
+                    <li role="menuitem"><a ng-click="viewTargets()">View Targets</a></li>
                     <li role="menuitem"><a ng-click="viewRegexes()">View Regexes</a></li>
                     <li role="menuitem"><a ng-click="viewJobs()">View Invalidate Content Jobs</a></li>
                     <li role="menuitem"><a ng-click="viewStaticDnsEntries()">View Static DNS Entries</a></li>

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/d851910a/traffic_portal/app/src/common/modules/form/deliveryServiceTarget/FormDeliveryServiceTargetController.js
----------------------------------------------------------------------
diff --git a/traffic_portal/app/src/common/modules/form/deliveryServiceTarget/FormDeliveryServiceTargetController.js b/traffic_portal/app/src/common/modules/form/deliveryServiceTarget/FormDeliveryServiceTargetController.js
new file mode 100644
index 0000000..a01526c
--- /dev/null
+++ b/traffic_portal/app/src/common/modules/form/deliveryServiceTarget/FormDeliveryServiceTargetController.js
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+
+var FormDeliveryServiceTargetController = function(deliveryService, target, $scope, formUtils, locationUtils, deliveryServiceService, typeService) {
+
+	var getDeliveryServices = function() {
+		deliveryServiceService.getDeliveryServices()
+			.then(function(result) {
+				$scope.deliveryServices = result;
+			});
+	};
+
+	var getTypes = function() {
+		typeService.getTypes({ useInTable: 'steering_target' })
+			.then(function(result) {
+				$scope.types = result;
+			});
+	};
+
+	$scope.deliveryService = deliveryService;
+
+	$scope.targetId = angular.copy(target.targetId);
+
+	$scope.target = target;
+
+	$scope.navigateToPath = locationUtils.navigateToPath;
+
+	$scope.hasError = formUtils.hasError;
+
+	$scope.hasPropertyError = formUtils.hasPropertyError;
+
+	var init = function () {
+		getDeliveryServices();
+		getTypes();
+	};
+	init();
+
+};
+
+FormDeliveryServiceTargetController.$inject = ['deliveryService', 'target', '$scope', 'formUtils', 'locationUtils', 'deliveryServiceService', 'typeService'];
+module.exports = FormDeliveryServiceTargetController;

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/d851910a/traffic_portal/app/src/common/modules/form/deliveryServiceTarget/edit/FormEditDeliveryServiceTargetController.js
----------------------------------------------------------------------
diff --git a/traffic_portal/app/src/common/modules/form/deliveryServiceTarget/edit/FormEditDeliveryServiceTargetController.js b/traffic_portal/app/src/common/modules/form/deliveryServiceTarget/edit/FormEditDeliveryServiceTargetController.js
new file mode 100644
index 0000000..2131a59
--- /dev/null
+++ b/traffic_portal/app/src/common/modules/form/deliveryServiceTarget/edit/FormEditDeliveryServiceTargetController.js
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+
+var FormEditDeliveryServiceTargetController = function(deliveryService, target, $scope, $controller, $uibModal, $anchorScroll, locationUtils, deliveryServiceService) {
+
+	// extends the FormDeliveryServiceTargetController to inherit common methods
+	angular.extend(this, $controller('FormDeliveryServiceTargetController', { deliveryService: deliveryService, target: target, $scope: $scope }));
+
+	var deleteTarget = function(target) {
+		deliveryServiceService.deleteDeliveryServiceTarget(target.deliveryServiceId, target.targetId)
+			.then(function() {
+
+			});
+	};
+
+	$scope.settings = {
+		isNew: false,
+		saveLabel: 'Update'
+	};
+
+	$scope.targetName = angular.copy(target.targetXmlId);
+
+	$scope.save = function(dsId, targetId, target) {
+		deliveryServiceService.updateDeliveryServiceTarget(dsId, targetId, target);
+	};
+
+	$scope.confirmDelete = function(target) {
+		var params = {
+			title: 'Delete Target',
+			message: 'Are you sure you want to delete the steering target?'
+		};
+		var modalInstance = $uibModal.open({
+			templateUrl: 'common/modules/dialog/confirm/dialog.confirm.tpl.html',
+			controller: 'DialogConfirmController',
+			size: 'sm',
+			resolve: {
+				params: function () {
+					return params;
+				}
+			}
+		});
+		modalInstance.result.then(function() {
+			deleteTarget(target);
+		}, function () {
+			// do nothing
+		});
+	};
+
+
+};
+
+FormEditDeliveryServiceTargetController.$inject = ['deliveryService', 'target', '$scope', '$controller', '$uibModal', '$anchorScroll', 'locationUtils', 'deliveryServiceService'];
+module.exports = FormEditDeliveryServiceTargetController;

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/d851910a/traffic_portal/app/src/common/modules/form/deliveryServiceTarget/edit/index.js
----------------------------------------------------------------------
diff --git a/traffic_portal/app/src/common/modules/form/deliveryServiceTarget/edit/index.js b/traffic_portal/app/src/common/modules/form/deliveryServiceTarget/edit/index.js
new file mode 100644
index 0000000..d9eda3c
--- /dev/null
+++ b/traffic_portal/app/src/common/modules/form/deliveryServiceTarget/edit/index.js
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+module.exports = angular.module('trafficPortal.form.deliveryServiceTarget.edit', [])
+	.controller('FormEditDeliveryServiceTargetController', require('./FormEditDeliveryServiceTargetController'));

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/d851910a/traffic_portal/app/src/common/modules/form/deliveryServiceTarget/form.deliveryServiceTarget.tpl.html
----------------------------------------------------------------------
diff --git a/traffic_portal/app/src/common/modules/form/deliveryServiceTarget/form.deliveryServiceTarget.tpl.html b/traffic_portal/app/src/common/modules/form/deliveryServiceTarget/form.deliveryServiceTarget.tpl.html
new file mode 100644
index 0000000..6a6486e
--- /dev/null
+++ b/traffic_portal/app/src/common/modules/form/deliveryServiceTarget/form.deliveryServiceTarget.tpl.html
@@ -0,0 +1,75 @@
+<!--
+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="x_panel">
+    <div class="x_title">
+        <ol class="breadcrumb pull-left">
+            <li><a ng-click="navigateToPath('/configure/delivery-services')">Delivery Services</a></li>
+            <li><a ng-click="navigateToPath('/configure/delivery-services/' + deliveryService.id + '?type=' + deliveryService.type)">{{deliveryService.xmlId}}</a></li>
+            <li><a ng-click="navigateToPath('/configure/delivery-services/' + deliveryService.id + '/targets')">Targets</a></li>
+            <li class="active">{{targetName}}</li>
+        </ol>
+        <div class="clearfix"></div>
+    </div>
+    <div class="x_content">
+        <br>
+        <form name="dsTargetForm" class="form-horizontal form-label-left" novalidate>
+            <div class="form-group" ng-class="{'has-error': hasError(dsTargetForm.deliveryServiceId), 'has-feedback': hasError(dsTargetForm.deliveryServiceId)}">
+                <label class="control-label col-md-2 col-sm-2 col-xs-12">Steering Delivery Service *</label>
+                <div class="col-md-10 col-sm-10 col-xs-12">
+                    <select id="deliveryServiceId" name="deliveryServiceId" class="form-control" ng-model="target.deliveryServiceId" ng-disabled="true" ng-options="ds.id as ds.xmlId for ds in deliveryServices">
+                        <option value="">Select...</option>
+                    </select>
+                </div>
+            </div>
+            <div class="form-group" ng-class="{'has-error': hasError(dsTargetForm.targetId), 'has-feedback': hasError(dsTargetForm.targetId)}">
+                <label class="control-label col-md-2 col-sm-2 col-xs-12">Steering Target *</label>
+                <div class="col-md-10 col-sm-10 col-xs-12">
+                    <select id="targetId" name="targetId" class="form-control" ng-model="target.targetId" ng-options="ds.id as ds.xmlId for ds in deliveryServices" required>
+                        <option value="">Select...</option>
+                    </select>
+                    <small class="input-error" ng-show="hasPropertyError(dsTargetForm.targetId, 'required')">Required</small>
+                </div>
+            </div>
+            <div class="form-group" ng-class="{'has-error': hasError(dsTargetForm.typeId), 'has-feedback': hasError(dsTargetForm.typeId)}">
+                <label class="control-label col-md-2 col-sm-2 col-xs-12">Type *</label>
+                <div class="col-md-10 col-sm-10 col-xs-12">
+                    <select id="typeId" name="typeId" class="form-control" ng-model="target.typeId" ng-options="type.id as type.name for type in types" required>
+                        <option value="">Select...</option>
+                    </select>
+                    <small class="input-error" ng-show="hasPropertyError(dsTargetForm.typeId, 'required')">Required</small>
+                </div>
+            </div>
+            <div class="form-group" ng-class="{'has-error': hasError(dsTargetForm.value), 'has-feedback': hasError(dsTargetForm.value)}">
+                <label class="control-label col-md-2 col-sm-2 col-xs-12">Value *</label>
+                <div class="col-md-10 col-sm-10 col-xs-12">
+                    <input id="value" name="value" type="text" class="form-control" ng-model="target.value" ng-required="true" ng-maxlength="3" ng-pattern="/^\d+$/" autofocus>
+                    <small class="input-error" ng-show="hasPropertyError(dsTargetForm.value, 'required')">Required</small>
+                    <small class="input-error" ng-show="hasPropertyError(dsTargetForm.value, 'maxlength')">Too Long</small>
+                    <small class="input-error" ng-show="hasPropertyError(dsTargetForm.value, 'pattern')">Number</small>
+                    <span ng-show="hasError(dsTargetForm.value)" class="form-control-feedback"><i class="fa fa-times"></i></span>
+                </div>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-danger" ng-show="!settings.isNew" ng-click="confirmDelete(target)">Delete</button>
+                <button type="button" class="btn btn-success" ng-disabled="dsTargetForm.$pristine || dsTargetForm.$invalid" ng-click="save(deliveryService.id, targetId, target)">{{settings.saveLabel}}</button>
+            </div>
+        </form>
+    </div>
+</div>

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/d851910a/traffic_portal/app/src/common/modules/form/deliveryServiceTarget/index.js
----------------------------------------------------------------------
diff --git a/traffic_portal/app/src/common/modules/form/deliveryServiceTarget/index.js b/traffic_portal/app/src/common/modules/form/deliveryServiceTarget/index.js
new file mode 100644
index 0000000..cf40b13
--- /dev/null
+++ b/traffic_portal/app/src/common/modules/form/deliveryServiceTarget/index.js
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+module.exports = angular.module('trafficPortal.form.deliveryServiceTarget', [])
+	.controller('FormDeliveryServiceTargetController', require('./FormDeliveryServiceTargetController'));

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/d851910a/traffic_portal/app/src/common/modules/form/deliveryServiceTarget/new/FormNewDeliveryServiceTargetController.js
----------------------------------------------------------------------
diff --git a/traffic_portal/app/src/common/modules/form/deliveryServiceTarget/new/FormNewDeliveryServiceTargetController.js b/traffic_portal/app/src/common/modules/form/deliveryServiceTarget/new/FormNewDeliveryServiceTargetController.js
new file mode 100644
index 0000000..581909b
--- /dev/null
+++ b/traffic_portal/app/src/common/modules/form/deliveryServiceTarget/new/FormNewDeliveryServiceTargetController.js
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+
+var FormNewDeliveryServiceTargetController = function(deliveryService, target, $scope, $controller, deliveryServiceService) {
+
+	// extends the FormDeliveryServiceTargetController to inherit common methods
+	angular.extend(this, $controller('FormDeliveryServiceTargetController', { deliveryService: deliveryService, target: target, $scope: $scope }));
+
+	$scope.targetName = 'New';
+
+	$scope.settings = {
+		isNew: true,
+		saveLabel: 'Create'
+	};
+
+	$scope.save = function(dsId, targetId, target) {
+		deliveryServiceService.createDeliveryServiceTarget(dsId, target);
+	};
+
+};
+
+FormNewDeliveryServiceTargetController.$inject = ['deliveryService', 'target', '$scope', '$controller', 'deliveryServiceService'];
+module.exports = FormNewDeliveryServiceTargetController;

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/d851910a/traffic_portal/app/src/common/modules/form/deliveryServiceTarget/new/index.js
----------------------------------------------------------------------
diff --git a/traffic_portal/app/src/common/modules/form/deliveryServiceTarget/new/index.js b/traffic_portal/app/src/common/modules/form/deliveryServiceTarget/new/index.js
new file mode 100644
index 0000000..5fe7317
--- /dev/null
+++ b/traffic_portal/app/src/common/modules/form/deliveryServiceTarget/new/index.js
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+module.exports = angular.module('trafficPortal.form.deliveryServiceTarget.new', [])
+	.controller('FormNewDeliveryServiceTargetController', require('./FormNewDeliveryServiceTargetController'));

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/d851910a/traffic_portal/app/src/common/modules/table/deliveryServiceTargets/TableDeliveryServiceTargetsController.js
----------------------------------------------------------------------
diff --git a/traffic_portal/app/src/common/modules/table/deliveryServiceTargets/TableDeliveryServiceTargetsController.js b/traffic_portal/app/src/common/modules/table/deliveryServiceTargets/TableDeliveryServiceTargetsController.js
new file mode 100644
index 0000000..2fc6b8b
--- /dev/null
+++ b/traffic_portal/app/src/common/modules/table/deliveryServiceTargets/TableDeliveryServiceTargetsController.js
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+
+var TableDeliveryServiceTargetsController = function(deliveryService, targets, $scope, $state, locationUtils, deliveryServiceService) {
+
+	$scope.deliveryService = deliveryService;
+
+	$scope.targets = targets;
+
+	$scope.editTarget = function(dsId, targetId) {
+		locationUtils.navigateToPath('/configure/delivery-services/' + dsId + '/targets/' + targetId);
+	};
+
+	$scope.createTarget = function(dsId) {
+		locationUtils.navigateToPath('/configure/delivery-services/' + dsId + '/targets/new');
+	};
+
+	$scope.refresh = function() {
+		$state.reload(); // reloads all the resolves for the view
+	};
+
+	$scope.navigateToPath = locationUtils.navigateToPath;
+
+	angular.element(document).ready(function () {
+		$('#targetsTable').dataTable({
+			"aLengthMenu": [[25, 50, 100, -1], [25, 50, 100, "All"]],
+			"iDisplayLength": 25,
+			"aaSorting": []
+		});
+	});
+
+};
+
+TableDeliveryServiceTargetsController.$inject = ['deliveryService', 'targets', '$scope', '$state', 'locationUtils', 'deliveryServiceService'];
+module.exports = TableDeliveryServiceTargetsController;

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/d851910a/traffic_portal/app/src/common/modules/table/deliveryServiceTargets/index.js
----------------------------------------------------------------------
diff --git a/traffic_portal/app/src/common/modules/table/deliveryServiceTargets/index.js b/traffic_portal/app/src/common/modules/table/deliveryServiceTargets/index.js
new file mode 100644
index 0000000..9b8fd58
--- /dev/null
+++ b/traffic_portal/app/src/common/modules/table/deliveryServiceTargets/index.js
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+module.exports = angular.module('trafficPortal.table.deliveryServiceTargets', [])
+	.controller('TableDeliveryServiceTargetsController', require('./TableDeliveryServiceTargetsController'));

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/d851910a/traffic_portal/app/src/common/modules/table/deliveryServiceTargets/table.deliveryServiceTargets.tpl.html
----------------------------------------------------------------------
diff --git a/traffic_portal/app/src/common/modules/table/deliveryServiceTargets/table.deliveryServiceTargets.tpl.html b/traffic_portal/app/src/common/modules/table/deliveryServiceTargets/table.deliveryServiceTargets.tpl.html
new file mode 100644
index 0000000..2a66178
--- /dev/null
+++ b/traffic_portal/app/src/common/modules/table/deliveryServiceTargets/table.deliveryServiceTargets.tpl.html
@@ -0,0 +1,55 @@
+<!--
+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="x_panel">
+    <div class="x_title">
+        <ol class="breadcrumb pull-left">
+            <li><a ng-click="navigateToPath('/configure/delivery-services')">Delivery Services</a></li>
+            <li><a ng-click="navigateToPath('/configure/delivery-services/' + deliveryService.id + '?type=' + deliveryService.type)">{{::deliveryService.xmlId}}</a></li>
+            <li class="active">Targets</li>
+        </ol>
+        <div class="pull-right">
+            <button class="btn btn-primary" title="Create Delivery Service Steering Target" ng-click="createTarget(deliveryService.id)"><i class="fa fa-plus"></i></button>
+            <button class="btn btn-default" title="Refresh" ng-click="refresh()"><i class="fa fa-refresh"></i></button>
+        </div>
+        <div class="clearfix"></div>
+    </div>
+    <div class="x_content">
+        <br>
+        <table id="targetsTable" class="table responsive-utilities jambo_table">
+            <thead>
+            <tr class="headings">
+                <th>deliveryService</th>
+                <th>target</th>
+                <th>type</th>
+                <th>value</th>
+            </tr>
+            </thead>
+            <tbody>
+            <tr ng-click="editTarget(deliveryService.id, target.targetId)" ng-repeat="target in ::targets">
+                <td>{{::target.deliveryService}}</td>
+                <td>{{::target.target}}</td>
+                <td>{{::target.type}}</td>
+                <td>{{::target.value}}</td>
+            </tr>
+            </tbody>
+        </table>
+    </div>
+</div>
+

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/d851910a/traffic_portal/app/src/modules/private/configure/deliveryServices/targets/DeliveryServiceTargetsController.js
----------------------------------------------------------------------
diff --git a/traffic_portal/app/src/modules/private/configure/deliveryServices/targets/DeliveryServiceTargetsController.js b/traffic_portal/app/src/modules/private/configure/deliveryServices/targets/DeliveryServiceTargetsController.js
new file mode 100644
index 0000000..62d81af
--- /dev/null
+++ b/traffic_portal/app/src/modules/private/configure/deliveryServices/targets/DeliveryServiceTargetsController.js
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+var DeliveryServiceTargetsController = function() {
+};
+
+DeliveryServiceTargetsController.$inject = [];
+module.exports = DeliveryServiceTargetsController;

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/d851910a/traffic_portal/app/src/modules/private/configure/deliveryServices/targets/deliveryServiceTargets.tpl.html
----------------------------------------------------------------------
diff --git a/traffic_portal/app/src/modules/private/configure/deliveryServices/targets/deliveryServiceTargets.tpl.html b/traffic_portal/app/src/modules/private/configure/deliveryServices/targets/deliveryServiceTargets.tpl.html
new file mode 100644
index 0000000..606b01b
--- /dev/null
+++ b/traffic_portal/app/src/modules/private/configure/deliveryServices/targets/deliveryServiceTargets.tpl.html
@@ -0,0 +1,22 @@
+<!--
+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 id="deliveryServiceTargetsContainer">
+    <div ui-view="deliveryServiceTargetsContent"></div>
+</div>

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/d851910a/traffic_portal/app/src/modules/private/configure/deliveryServices/targets/edit/index.js
----------------------------------------------------------------------
diff --git a/traffic_portal/app/src/modules/private/configure/deliveryServices/targets/edit/index.js b/traffic_portal/app/src/modules/private/configure/deliveryServices/targets/edit/index.js
new file mode 100644
index 0000000..d1e0cbc
--- /dev/null
+++ b/traffic_portal/app/src/modules/private/configure/deliveryServices/targets/edit/index.js
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+module.exports = angular.module('trafficPortal.private.configure.deliveryServices.targets.edit', [])
+	.config(function($stateProvider, $urlRouterProvider) {
+		$stateProvider
+			.state('trafficPortal.private.configure.deliveryServices.targets.edit', {
+				url: '/{targetId:[0-9]{1,8}}',
+				views: {
+					deliveryServiceTargetsContent: {
+						templateUrl: 'common/modules/form/deliveryServiceTarget/form.deliveryServiceTarget.tpl.html',
+						controller: 'FormEditDeliveryServiceTargetController',
+						resolve: {
+							deliveryService: function($stateParams, deliveryServiceService) {
+								return deliveryServiceService.getDeliveryService($stateParams.deliveryServiceId);
+							},
+							target: function(deliveryService, $stateParams, deliveryServiceService) {
+								return deliveryServiceService.getDeliveryServiceTarget(deliveryService.id, $stateParams.targetId);
+							}
+						}
+					}
+				}
+			})
+		;
+		$urlRouterProvider.otherwise('/');
+	});

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/d851910a/traffic_portal/app/src/modules/private/configure/deliveryServices/targets/index.js
----------------------------------------------------------------------
diff --git a/traffic_portal/app/src/modules/private/configure/deliveryServices/targets/index.js b/traffic_portal/app/src/modules/private/configure/deliveryServices/targets/index.js
new file mode 100644
index 0000000..85b2dbc
--- /dev/null
+++ b/traffic_portal/app/src/modules/private/configure/deliveryServices/targets/index.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.
+ */
+
+module.exports = angular.module('trafficPortal.private.configure.deliveryServices.targets', [])
+	.controller('DeliveryServiceTargetsController', require('./DeliveryServiceTargetsController'))
+	.config(function($stateProvider, $urlRouterProvider) {
+		$stateProvider
+			.state('trafficPortal.private.configure.deliveryServices.targets', {
+				url: '/{deliveryServiceId}/targets',
+				abstract: true,
+				views: {
+					deliveryServicesContent: {
+						templateUrl: 'modules/private/configure/deliveryServices/targets/deliveryServiceTargets.tpl.html',
+						controller: 'DeliveryServiceTargetsController'
+					}
+				}
+			})
+		;
+		$urlRouterProvider.otherwise('/');
+	});

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/d851910a/traffic_portal/app/src/modules/private/configure/deliveryServices/targets/list/index.js
----------------------------------------------------------------------
diff --git a/traffic_portal/app/src/modules/private/configure/deliveryServices/targets/list/index.js b/traffic_portal/app/src/modules/private/configure/deliveryServices/targets/list/index.js
new file mode 100644
index 0000000..cca0df4
--- /dev/null
+++ b/traffic_portal/app/src/modules/private/configure/deliveryServices/targets/list/index.js
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+module.exports = angular.module('trafficPortal.private.configure.deliveryServices.targets.list', [])
+	.config(function($stateProvider, $urlRouterProvider) {
+		$stateProvider
+			.state('trafficPortal.private.configure.deliveryServices.targets.list', {
+				url: '',
+				views: {
+					deliveryServiceTargetsContent: {
+						templateUrl: 'common/modules/table/deliveryServiceTargets/table.deliveryServiceTargets.tpl.html',
+						controller: 'TableDeliveryServiceTargetsController',
+						resolve: {
+							deliveryService: function($stateParams, deliveryServiceService) {
+								return deliveryServiceService.getDeliveryService($stateParams.deliveryServiceId);
+							},
+							targets: function($stateParams, deliveryServiceService) {
+								return deliveryServiceService.getDeliveryServiceTargets($stateParams.deliveryServiceId);
+							}
+						}
+					}
+				}
+			})
+		;
+		$urlRouterProvider.otherwise('/');
+	});

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/d851910a/traffic_portal/app/src/modules/private/configure/deliveryServices/targets/new/index.js
----------------------------------------------------------------------
diff --git a/traffic_portal/app/src/modules/private/configure/deliveryServices/targets/new/index.js b/traffic_portal/app/src/modules/private/configure/deliveryServices/targets/new/index.js
new file mode 100644
index 0000000..1bbed10
--- /dev/null
+++ b/traffic_portal/app/src/modules/private/configure/deliveryServices/targets/new/index.js
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+module.exports = angular.module('trafficPortal.private.configure.deliveryServices.targets.new', [])
+	.config(function($stateProvider, $urlRouterProvider) {
+		$stateProvider
+			.state('trafficPortal.private.configure.deliveryServices.targets.new', {
+				url: '/new',
+				views: {
+					deliveryServiceTargetsContent: {
+						templateUrl: 'common/modules/form/deliveryServiceTarget/form.deliveryServiceTarget.tpl.html',
+						controller: 'FormNewDeliveryServiceTargetController',
+						resolve: {
+							deliveryService: function($stateParams, deliveryServiceService) {
+								return deliveryServiceService.getDeliveryService($stateParams.deliveryServiceId);
+							},
+							target: function(deliveryService) {
+								return {
+									deliveryServiceId: deliveryService.id,
+									targetId: 0
+								};
+							}
+						}
+					}
+				}
+			})
+		;
+		$urlRouterProvider.otherwise('/');
+	});

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/d851910a/traffic_portal/app/src/styles/main.scss
----------------------------------------------------------------------
diff --git a/traffic_portal/app/src/styles/main.scss b/traffic_portal/app/src/styles/main.scss
index 752f7bd..fe5538a 100755
--- a/traffic_portal/app/src/styles/main.scss
+++ b/traffic_portal/app/src/styles/main.scss
@@ -146,6 +146,13 @@ body.nav-sm .container.body .main-content {
 
 }
 
+td {
+  .table-btn {
+    padding-top: 0;
+    padding-bottom: 0;
+  }
+}
+
 @media(min-width:992px) {
   body.nav-md .container.body .main-content {
     margin-left: 230px;


Mime
View raw message