diff --git a/ui/app/components/job-page/parts/evaluations.js b/ui/app/components/job-page/parts/evaluations.js
new file mode 100644
index 000000000..33f6054a7
--- /dev/null
+++ b/ui/app/components/job-page/parts/evaluations.js
@@ -0,0 +1,12 @@
+import Component from '@ember/component';
+import { computed } from '@ember/object';
+
+export default Component.extend({
+ job: null,
+
+ classNames: ['boxed-section'],
+
+ sortedEvaluations: computed('job.evaluations.@each.modifyIndex', function() {
+ return (this.get('job.evaluations') || []).sortBy('modifyIndex').reverse();
+ }),
+});
diff --git a/ui/app/components/job-page/parts/placement-failures.js b/ui/app/components/job-page/parts/placement-failures.js
new file mode 100644
index 000000000..7df4236d8
--- /dev/null
+++ b/ui/app/components/job-page/parts/placement-failures.js
@@ -0,0 +1,6 @@
+import Component from '@ember/component';
+
+export default Component.extend({
+ job: null,
+ tagName: '',
+});
diff --git a/ui/app/components/job-page/parts/running-deployment.js b/ui/app/components/job-page/parts/running-deployment.js
new file mode 100644
index 000000000..7df4236d8
--- /dev/null
+++ b/ui/app/components/job-page/parts/running-deployment.js
@@ -0,0 +1,6 @@
+import Component from '@ember/component';
+
+export default Component.extend({
+ job: null,
+ tagName: '',
+});
diff --git a/ui/app/components/job-page/parts/summary.js b/ui/app/components/job-page/parts/summary.js
new file mode 100644
index 000000000..0ff44fc5a
--- /dev/null
+++ b/ui/app/components/job-page/parts/summary.js
@@ -0,0 +1,7 @@
+import Component from '@ember/component';
+
+export default Component.extend({
+ job: null,
+
+ classNames: ['boxed-section'],
+});
diff --git a/ui/app/components/job-page/parts/task-groups.js b/ui/app/components/job-page/parts/task-groups.js
new file mode 100644
index 000000000..a1829c33b
--- /dev/null
+++ b/ui/app/components/job-page/parts/task-groups.js
@@ -0,0 +1,23 @@
+import Component from '@ember/component';
+import { computed } from '@ember/object';
+import { alias } from '@ember/object/computed';
+import Sortable from 'nomad-ui/mixins/sortable';
+
+export default Component.extend(Sortable, {
+ job: null,
+
+ classNames: ['boxed-section'],
+
+ // Provide a value that is bound to a query param
+ sortProperty: null,
+ sortDescending: null,
+
+ gotoTaskGroup() {},
+
+ taskGroups: computed('job.taskGroups.[]', function() {
+ return this.get('job.taskGroups') || [];
+ }),
+
+ listToSort: alias('taskGroups'),
+ sortedTaskGroups: alias('listSorted'),
+});
diff --git a/ui/app/templates/components/job-page/parts/body.hbs b/ui/app/templates/components/job-page/parts/body.hbs
new file mode 100644
index 000000000..12c339ce4
--- /dev/null
+++ b/ui/app/templates/components/job-page/parts/body.hbs
@@ -0,0 +1,6 @@
+{{#gutter-menu class="page-body" onNamespaceChange=onNamespaceChange}}
+ {{partial "jobs/job/subnav"}}
+
+{{/gutter-menu}}
diff --git a/ui/app/templates/components/job-page/parts/evaluations.hbs b/ui/app/templates/components/job-page/parts/evaluations.hbs
new file mode 100644
index 000000000..f49a6f10b
--- /dev/null
+++ b/ui/app/templates/components/job-page/parts/evaluations.hbs
@@ -0,0 +1,38 @@
+
+ Evaluations
+
+
+ {{#if sortedEvaluations.length}}
+ {{#list-table source=sortedEvaluations as |t|}}
+ {{#t.head}}
+
ID |
+
Priority |
+
Triggered By |
+
Status |
+
Placement Failures |
+ {{/t.head}}
+ {{#t.body as |row|}}
+
+ | {{row.model.shortId}} |
+ {{row.model.priority}} |
+ {{row.model.triggeredBy}} |
+ {{row.model.status}} |
+
+ {{#if (eq row.model.status "blocked")}}
+ N/A - In Progress
+ {{else if row.model.hasPlacementFailures}}
+ True
+ {{else}}
+ False
+ {{/if}}
+ |
+
+ {{/t.body}}
+ {{/list-table}}
+ {{else}}
+
+
No Evaluations
+
This is most likely due to garbage collection.
+
+ {{/if}}
+
diff --git a/ui/app/templates/components/job-page/parts/placement-failures.hbs b/ui/app/templates/components/job-page/parts/placement-failures.hbs
new file mode 100644
index 000000000..f8bf078d0
--- /dev/null
+++ b/ui/app/templates/components/job-page/parts/placement-failures.hbs
@@ -0,0 +1,12 @@
+{{#if job.hasPlacementFailures}}
+
+
+ Placement Failures
+
+
+ {{#each job.taskGroups as |taskGroup|}}
+ {{placement-failure taskGroup=taskGroup}}
+ {{/each}}
+
+
+{{/if}}
diff --git a/ui/app/templates/components/job-page/parts/running-deployment.hbs b/ui/app/templates/components/job-page/parts/running-deployment.hbs
new file mode 100644
index 000000000..c42bb866d
--- /dev/null
+++ b/ui/app/templates/components/job-page/parts/running-deployment.hbs
@@ -0,0 +1,33 @@
+{{#if job.runningDeployment}}
+
+
+
+ Active Deployment
+ {{job.runningDeployment.shortId}}
+ {{#if job.runningDeployment.version.submitTime}}
+ {{moment-from-now job.runningDeployment.version.submitTime}}
+ {{/if}}
+
+
+ Running
+ {{#if job.runningDeployment.requiresPromotion}}
+ Deployment is running but requires promotion
+ {{/if}}
+
+
+
+ {{#job-deployment-details deployment=job.runningDeployment as |d|}}
+ {{d.metrics}}
+ {{#if isShowingDeploymentDetails}}
+ {{d.taskGroups}}
+ {{d.allocations}}
+ {{/if}}
+ {{/job-deployment-details}}
+
+
+
+{{/if}}
diff --git a/ui/app/templates/components/job-page/parts/summary.hbs b/ui/app/templates/components/job-page/parts/summary.hbs
new file mode 100644
index 000000000..f00984304
--- /dev/null
+++ b/ui/app/templates/components/job-page/parts/summary.hbs
@@ -0,0 +1,27 @@
+
+
+ {{#if job.hasChildren}}
+ Children Status {{job.totalChildren}}
+ {{else}}
+ Allocation Status {{job.totalAllocs}}
+ {{/if}}
+
+
+
+ {{#component (if job.hasChildren "children-status-bar" "allocation-status-bar")
+ allocationContainer=job
+ job=job
+ class="split-view" as |chart|}}
+
+ {{#each chart.data as |datum index|}}
+ -
+
+ {{datum.value}}
+
+ {{datum.label}}
+
+
+ {{/each}}
+
+ {{/component}}
+
diff --git a/ui/app/templates/components/job-page/parts/task-groups.hbs b/ui/app/templates/components/job-page/parts/task-groups.hbs
new file mode 100644
index 000000000..d6fbf5942
--- /dev/null
+++ b/ui/app/templates/components/job-page/parts/task-groups.hbs
@@ -0,0 +1,25 @@
+
+
+ Task Groups
+
+
+ {{#list-table
+ source=sortedTaskGroups
+ sortProperty=sortProperty
+ sortDescending=sortDescending as |t|}}
+ {{#t.head}}
+ {{#t.sort-by prop="name"}}Name{{/t.sort-by}}
+ {{#t.sort-by prop="count"}}Count{{/t.sort-by}}
+ {{#t.sort-by prop="queuedOrStartingAllocs" class="is-3"}}Allocation Status{{/t.sort-by}}
+ {{#t.sort-by prop="reservedCPU"}}Reserved CPU{{/t.sort-by}}
+ {{#t.sort-by prop="reservedMemory"}}Reserved Memory{{/t.sort-by}}
+ {{#t.sort-by prop="reservedEphemeralDisk"}}Reserved Disk{{/t.sort-by}}
+ {{/t.head}}
+ {{#t.body as |row|}}
+ {{task-group-row data-test-task-group
+ taskGroup=row.model
+ onClick=(action gotoTaskGroup row.model)}}
+ {{/t.body}}
+ {{/list-table}}
+
+