Add manually-converted classes
I don’t know why the codemod ignored these files 🧐
This commit is contained in:
parent
577e85b007
commit
cd11cd290c
|
@ -1,6 +1,6 @@
|
|||
import ApplicationAdapter from './application';
|
||||
|
||||
export default class Agent extends ApplicationAdapter {
|
||||
export default class AgentAdapter extends ApplicationAdapter {
|
||||
pathForType = () => 'agent/members';
|
||||
|
||||
urlForFindRecord() {
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import Watchable from './watchable';
|
||||
import addToPath from 'nomad-ui/utils/add-to-path';
|
||||
|
||||
export default Watchable.extend({
|
||||
stop: adapterAction('/stop'),
|
||||
export default class AllocationAdapter extends Watchable {
|
||||
stop = adapterAction('/stop');
|
||||
|
||||
restart(allocation, taskName) {
|
||||
const prefix = `${this.host || '/'}${this.urlPrefix()}`;
|
||||
|
@ -10,22 +10,20 @@ export default Watchable.extend({
|
|||
return this.ajax(url, 'PUT', {
|
||||
data: taskName && { TaskName: taskName },
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
ls(model, path) {
|
||||
return this.token
|
||||
.authorizedRequest(`/v1/client/fs/ls/${model.id}?path=${encodeURIComponent(path)}`)
|
||||
.then(handleFSResponse);
|
||||
},
|
||||
}
|
||||
|
||||
stat(model, path) {
|
||||
return this.token
|
||||
.authorizedRequest(
|
||||
`/v1/client/fs/stat/${model.id}?path=${encodeURIComponent(path)}`
|
||||
)
|
||||
.authorizedRequest(`/v1/client/fs/stat/${model.id}?path=${encodeURIComponent(path)}`)
|
||||
.then(handleFSResponse);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async function handleFSResponse(response) {
|
||||
if (response.ok) {
|
||||
|
|
|
@ -9,7 +9,7 @@ import classic from 'ember-classic-decorator';
|
|||
export const namespace = 'v1';
|
||||
|
||||
@classic
|
||||
export default class Application extends RESTAdapter {
|
||||
export default class ApplicationAdapter extends RESTAdapter {
|
||||
namespace = namespace;
|
||||
|
||||
@service system;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import Watchable from './watchable';
|
||||
|
||||
export default class Deployment extends Watchable {
|
||||
export default class DeploymentAdapter extends Watchable {
|
||||
promote(deployment) {
|
||||
const id = deployment.get('id');
|
||||
const url = urlForAction(this.urlForFindRecord(id, 'deployment'), '/promote');
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import Watchable from './watchable';
|
||||
|
||||
export default class JobSummary extends Watchable {
|
||||
export default class JobSummaryAdapter extends Watchable {
|
||||
urlForFindRecord(id, type, hash) {
|
||||
const [name, namespace] = JSON.parse(id);
|
||||
let url = super.urlForFindRecord(name, 'job', hash) + '/summary';
|
||||
|
|
|
@ -1,27 +1,27 @@
|
|||
import WatchableNamespaceIDs from './watchable-namespace-ids';
|
||||
import addToPath from 'nomad-ui/utils/add-to-path';
|
||||
|
||||
export default WatchableNamespaceIDs.extend({
|
||||
relationshipFallbackLinks: Object.freeze({
|
||||
export default class JobAdapter extends WatchableNamespaceIDs {
|
||||
relationshipFallbackLinks = Object.freeze({
|
||||
summary: '/summary',
|
||||
}),
|
||||
});
|
||||
|
||||
fetchRawDefinition(job) {
|
||||
const url = this.urlForFindRecord(job.get('id'), 'job');
|
||||
return this.ajax(url, 'GET');
|
||||
},
|
||||
}
|
||||
|
||||
forcePeriodic(job) {
|
||||
if (job.get('periodic')) {
|
||||
const url = addToPath(this.urlForFindRecord(job.get('id'), 'job'), '/periodic/force');
|
||||
return this.ajax(url, 'POST');
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
stop(job) {
|
||||
const url = this.urlForFindRecord(job.get('id'), 'job');
|
||||
return this.ajax(url, 'DELETE');
|
||||
},
|
||||
}
|
||||
|
||||
parse(spec) {
|
||||
const url = addToPath(this.urlForFindAll('job'), '/parse');
|
||||
|
@ -31,7 +31,7 @@ export default WatchableNamespaceIDs.extend({
|
|||
Canonicalize: true,
|
||||
},
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
plan(job) {
|
||||
const jobId = job.get('id') || job.get('_idBeforeSaving');
|
||||
|
@ -48,7 +48,7 @@ export default WatchableNamespaceIDs.extend({
|
|||
store.pushPayload('job-plan', { jobPlans: [json] });
|
||||
return store.peekRecord('job-plan', jobId);
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
// Running a job doesn't follow REST create semantics so it's easier to
|
||||
// treat it as an action.
|
||||
|
@ -58,7 +58,7 @@ export default WatchableNamespaceIDs.extend({
|
|||
Job: job.get('_newDefinitionJSON'),
|
||||
},
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
update(job) {
|
||||
const jobId = job.get('id') || job.get('_idBeforeSaving');
|
||||
|
@ -68,5 +68,5 @@ export default WatchableNamespaceIDs.extend({
|
|||
Job: job.get('_newDefinitionJSON'),
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import ApplicationAdapter from './application';
|
||||
import codesForError from '../utils/codes-for-error';
|
||||
|
||||
export default class Namespace extends ApplicationAdapter {
|
||||
export default class NamespaceAdapter extends ApplicationAdapter {
|
||||
findRecord(store, modelClass, id) {
|
||||
return super.findRecord(...arguments).catch(error => {
|
||||
const errorCodes = codesForError(error);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import Watchable from './watchable';
|
||||
import addToPath from 'nomad-ui/utils/add-to-path';
|
||||
|
||||
export default class Node extends Watchable {
|
||||
export default class NodeAdapter extends Watchable {
|
||||
setEligible(node) {
|
||||
return this.setEligibility(node, true);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import Watchable from './watchable';
|
||||
|
||||
export default Watchable.extend({
|
||||
queryParamsToAttrs: Object.freeze({
|
||||
export default class PluginAdapter extends Watchable {
|
||||
queryParamsToAttrs = Object.freeze({
|
||||
type: 'type',
|
||||
}),
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { default as ApplicationAdapter, namespace } from './application';
|
||||
|
||||
export default class Policy extends ApplicationAdapter {
|
||||
export default class PolicyAdapter extends ApplicationAdapter {
|
||||
namespace = namespace + '/acl';
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { inject as service } from '@ember/service';
|
||||
import { default as ApplicationAdapter, namespace } from './application';
|
||||
|
||||
export default class Token extends ApplicationAdapter {
|
||||
export default class TokenAdapter extends ApplicationAdapter {
|
||||
@service store;
|
||||
|
||||
namespace = namespace + '/acl';
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import WatchableNamespaceIDs from './watchable-namespace-ids';
|
||||
|
||||
export default WatchableNamespaceIDs.extend({
|
||||
queryParamsToAttrs: Object.freeze({
|
||||
export default class VolumeAdapter extends WatchableNamespaceIDs {
|
||||
queryParamsToAttrs = Object.freeze({
|
||||
type: 'type',
|
||||
plugin_id: 'plugin.id',
|
||||
}),
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,45 +1,45 @@
|
|||
import { computed } from '@ember/object';
|
||||
import DistributionBar from './distribution-bar';
|
||||
|
||||
export default DistributionBar.extend({
|
||||
layoutName: 'components/distribution-bar',
|
||||
export default class AllocationStatusBar extends DistributionBar {
|
||||
layoutName = 'components/distribution-bar';
|
||||
|
||||
allocationContainer: null,
|
||||
allocationContainer = null;
|
||||
|
||||
'data-test-allocation-status-bar': true,
|
||||
'data-test-allocation-status-bar' = true;
|
||||
|
||||
data: computed(
|
||||
'allocationContainer.{queuedAllocs,completeAllocs,failedAllocs,runningAllocs,startingAllocs}',
|
||||
function() {
|
||||
if (!this.allocationContainer) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const allocs = this.allocationContainer.getProperties(
|
||||
'queuedAllocs',
|
||||
'completeAllocs',
|
||||
'failedAllocs',
|
||||
'runningAllocs',
|
||||
'startingAllocs',
|
||||
'lostAllocs'
|
||||
);
|
||||
return [
|
||||
{ label: 'Queued', value: allocs.queuedAllocs, className: 'queued' },
|
||||
{
|
||||
label: 'Starting',
|
||||
value: allocs.startingAllocs,
|
||||
className: 'starting',
|
||||
layers: 2,
|
||||
},
|
||||
{ label: 'Running', value: allocs.runningAllocs, className: 'running' },
|
||||
{
|
||||
label: 'Complete',
|
||||
value: allocs.completeAllocs,
|
||||
className: 'complete',
|
||||
},
|
||||
{ label: 'Failed', value: allocs.failedAllocs, className: 'failed' },
|
||||
{ label: 'Lost', value: allocs.lostAllocs, className: 'lost' },
|
||||
];
|
||||
@computed(
|
||||
'allocationContainer.{queuedAllocs,completeAllocs,failedAllocs,runningAllocs,startingAllocs}'
|
||||
)
|
||||
get data() {
|
||||
if (!this.allocationContainer) {
|
||||
return [];
|
||||
}
|
||||
),
|
||||
});
|
||||
|
||||
const allocs = this.allocationContainer.getProperties(
|
||||
'queuedAllocs',
|
||||
'completeAllocs',
|
||||
'failedAllocs',
|
||||
'runningAllocs',
|
||||
'startingAllocs',
|
||||
'lostAllocs'
|
||||
);
|
||||
return [
|
||||
{ label: 'Queued', value: allocs.queuedAllocs, className: 'queued' },
|
||||
{
|
||||
label: 'Starting',
|
||||
value: allocs.startingAllocs,
|
||||
className: 'starting',
|
||||
layers: 2,
|
||||
},
|
||||
{ label: 'Running', value: allocs.runningAllocs, className: 'running' },
|
||||
{
|
||||
label: 'Complete',
|
||||
value: allocs.completeAllocs,
|
||||
className: 'complete',
|
||||
},
|
||||
{ label: 'Failed', value: allocs.failedAllocs, className: 'failed' },
|
||||
{ label: 'Lost', value: allocs.lostAllocs, className: 'lost' },
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/* eslint-disable ember/no-observers */
|
||||
import Component from '@ember/component';
|
||||
import { computed, observer, set } from '@ember/object';
|
||||
import { computed, set } from '@ember/object';
|
||||
import { observes } from '@ember-decorators/object';
|
||||
import { run } from '@ember/runloop';
|
||||
import { assign } from '@ember/polyfills';
|
||||
import { guidFor } from '@ember/object/internals';
|
||||
|
@ -9,22 +10,25 @@ import d3 from 'd3-selection';
|
|||
import 'd3-transition';
|
||||
import WindowResizable from '../mixins/window-resizable';
|
||||
import styleStringProperty from '../utils/properties/style-string';
|
||||
import { classNames, classNameBindings } from '@ember-decorators/component';
|
||||
import classic from 'ember-classic-decorator';
|
||||
|
||||
const sumAggregate = (total, val) => total + val;
|
||||
|
||||
export default Component.extend(WindowResizable, {
|
||||
classNames: ['chart', 'distribution-bar'],
|
||||
classNameBindings: ['isNarrow:is-narrow'],
|
||||
@classic
|
||||
@classNames('chart', 'distribution-bar')
|
||||
@classNameBindings('isNarrow:is-narrow')
|
||||
export default class DistributionBar extends Component.extend(WindowResizable) {
|
||||
chart = null;
|
||||
data = null;
|
||||
activeDatum = null;
|
||||
isNarrow = false;
|
||||
|
||||
chart: null,
|
||||
data: null,
|
||||
activeDatum: null,
|
||||
isNarrow: false,
|
||||
@styleStringProperty('tooltipPosition') tooltipStyle;
|
||||
maskId = null;
|
||||
|
||||
tooltipStyle: styleStringProperty('tooltipPosition'),
|
||||
maskId: null,
|
||||
|
||||
_data: computed('data', function() {
|
||||
@computed('data')
|
||||
get _data() {
|
||||
const data = copy(this.data, true);
|
||||
const sum = data.mapBy('value').reduce(sumAggregate, 0);
|
||||
|
||||
|
@ -41,7 +45,7 @@ export default Component.extend(WindowResizable, {
|
|||
.mapBy('value')
|
||||
.reduce(sumAggregate, 0) / sum,
|
||||
}));
|
||||
}),
|
||||
}
|
||||
|
||||
didInsertElement() {
|
||||
const svg = this.element.querySelector('svg');
|
||||
|
@ -63,15 +67,16 @@ export default Component.extend(WindowResizable, {
|
|||
});
|
||||
|
||||
this.renderChart();
|
||||
},
|
||||
}
|
||||
|
||||
didUpdateAttrs() {
|
||||
this.renderChart();
|
||||
},
|
||||
}
|
||||
|
||||
updateChart: observer('_data.@each.{value,label,className}', function() {
|
||||
@observes('_data.@each.{value,label,className}')
|
||||
updateChart() {
|
||||
this.renderChart();
|
||||
}),
|
||||
}
|
||||
|
||||
// prettier-ignore
|
||||
/* eslint-disable */
|
||||
|
@ -166,10 +171,10 @@ export default Component.extend(WindowResizable, {
|
|||
.attr('height', '6px')
|
||||
.attr('y', '50%');
|
||||
}
|
||||
},
|
||||
}
|
||||
/* eslint-enable */
|
||||
|
||||
windowResizeHandler() {
|
||||
run.once(this, this.renderChart);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,16 +1,19 @@
|
|||
import Component from '@ember/component';
|
||||
import { inject as service } from '@ember/service';
|
||||
import { computed } from '@ember/object';
|
||||
import { action, computed } from '@ember/object';
|
||||
import { filterBy, mapBy, or, sort } from '@ember/object/computed';
|
||||
import generateExecUrl from 'nomad-ui/utils/generate-exec-url';
|
||||
import openExecUrl from 'nomad-ui/utils/open-exec-url';
|
||||
import classic from 'ember-classic-decorator';
|
||||
|
||||
export default Component.extend({
|
||||
router: service(),
|
||||
@classic
|
||||
export default class TaskGroupParent extends Component {
|
||||
@service router;
|
||||
|
||||
isOpen: or('clickedOpen', 'currentRouteIsThisTaskGroup'),
|
||||
@or('clickedOpen', 'currentRouteIsThisTaskGroup') isOpen;
|
||||
|
||||
currentRouteIsThisTaskGroup: computed('router.currentRoute', function() {
|
||||
@computed('router.currentRoute')
|
||||
get currentRouteIsThisTaskGroup() {
|
||||
const route = this.router.currentRoute;
|
||||
|
||||
if (route.name.includes('task-group')) {
|
||||
|
@ -24,58 +27,60 @@ export default Component.extend({
|
|||
} else {
|
||||
return false;
|
||||
}
|
||||
}),
|
||||
}
|
||||
|
||||
hasPendingAllocations: computed('taskGroup.allocations.@each.clientStatus', function() {
|
||||
@computed('taskGroup.allocations.@each.clientStatus')
|
||||
get hasPendingAllocations() {
|
||||
return this.taskGroup.allocations.any(allocation => allocation.clientStatus === 'pending');
|
||||
}),
|
||||
}
|
||||
|
||||
allocationTaskStatesRecordArrays: mapBy('taskGroup.allocations', 'states'),
|
||||
allocationTaskStates: computed('allocationTaskStatesRecordArrays.[]', function() {
|
||||
@mapBy('taskGroup.allocations', 'states') allocationTaskStatesRecordArrays;
|
||||
@computed('allocationTaskStatesRecordArrays.[]')
|
||||
get allocationTaskStates() {
|
||||
const flattenRecordArrays = (accumulator, recordArray) =>
|
||||
accumulator.concat(recordArray.toArray());
|
||||
return this.allocationTaskStatesRecordArrays.reduce(flattenRecordArrays, []);
|
||||
}),
|
||||
}
|
||||
|
||||
activeTaskStates: filterBy('allocationTaskStates', 'isActive'),
|
||||
@filterBy('allocationTaskStates', 'isActive') activeTaskStates;
|
||||
|
||||
activeTasks: mapBy('activeTaskStates', 'task'),
|
||||
activeTaskGroups: mapBy('activeTasks', 'taskGroup'),
|
||||
@mapBy('activeTaskStates', 'task') activeTasks;
|
||||
@mapBy('activeTasks', 'taskGroup') activeTaskGroups;
|
||||
|
||||
tasksWithRunningStates: computed(
|
||||
@computed(
|
||||
'taskGroup.name',
|
||||
'activeTaskStates.@each.name',
|
||||
'activeTasks.@each.name',
|
||||
'activeTaskGroups.@each.name',
|
||||
function() {
|
||||
const activeTaskStateNames = this.activeTaskStates
|
||||
.filter(taskState => {
|
||||
return taskState.task && taskState.task.taskGroup.name === this.taskGroup.name;
|
||||
})
|
||||
.mapBy('name');
|
||||
'activeTaskGroups.@each.name'
|
||||
)
|
||||
get tasksWithRunningStates() {
|
||||
const activeTaskStateNames = this.activeTaskStates
|
||||
.filter(taskState => {
|
||||
return taskState.task && taskState.task.taskGroup.name === this.taskGroup.name;
|
||||
})
|
||||
.mapBy('name');
|
||||
|
||||
return this.taskGroup.tasks.filter(task => activeTaskStateNames.includes(task.name));
|
||||
}
|
||||
),
|
||||
return this.taskGroup.tasks.filter(task => activeTaskStateNames.includes(task.name));
|
||||
}
|
||||
|
||||
taskSorting: Object.freeze(['name']),
|
||||
sortedTasks: sort('tasksWithRunningStates', 'taskSorting'),
|
||||
taskSorting = Object.freeze(['name']);
|
||||
@sort('tasksWithRunningStates', 'taskSorting') sortedTasks;
|
||||
|
||||
clickedOpen: false,
|
||||
clickedOpen = false;
|
||||
|
||||
actions: {
|
||||
toggleOpen() {
|
||||
this.toggleProperty('clickedOpen');
|
||||
},
|
||||
@action
|
||||
toggleOpen() {
|
||||
this.toggleProperty('clickedOpen');
|
||||
}
|
||||
|
||||
openInNewWindow(job, taskGroup, task) {
|
||||
let url = generateExecUrl(this.router, {
|
||||
job,
|
||||
taskGroup,
|
||||
task,
|
||||
});
|
||||
@action
|
||||
openInNewWindow(job, taskGroup, task) {
|
||||
let url = generateExecUrl(this.router, {
|
||||
job,
|
||||
taskGroup,
|
||||
task,
|
||||
});
|
||||
|
||||
openExecUrl(url);
|
||||
},
|
||||
},
|
||||
});
|
||||
openExecUrl(url);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/* eslint-disable ember/no-observers */
|
||||
import Component from '@ember/component';
|
||||
import { computed, observer } from '@ember/object';
|
||||
import { computed } from '@ember/object';
|
||||
import { observes } from '@ember-decorators/object';
|
||||
import { computed as overridable } from 'ember-overridable-computed';
|
||||
import { guidFor } from '@ember/object/internals';
|
||||
import { run } from '@ember/runloop';
|
||||
|
@ -13,6 +14,8 @@ import d3Format from 'd3-format';
|
|||
import d3TimeFormat from 'd3-time-format';
|
||||
import WindowResizable from 'nomad-ui/mixins/window-resizable';
|
||||
import styleStringProperty from 'nomad-ui/utils/properties/style-string';
|
||||
import { classNames } from '@ember-decorators/component';
|
||||
import classic from 'ember-classic-decorator';
|
||||
|
||||
// Returns a new array with the specified number of points linearly
|
||||
// distributed across the bounds
|
||||
|
@ -28,68 +31,73 @@ const lerp = ([low, high], numPoints) => {
|
|||
// Round a number or an array of numbers
|
||||
const nice = val => (val instanceof Array ? val.map(nice) : Math.round(val));
|
||||
|
||||
export default Component.extend(WindowResizable, {
|
||||
classNames: ['chart', 'line-chart'],
|
||||
|
||||
@classic
|
||||
@classNames('chart', 'line-chart')
|
||||
export default class LineChart extends Component.extend(WindowResizable) {
|
||||
// Public API
|
||||
|
||||
data: null,
|
||||
xProp: null,
|
||||
yProp: null,
|
||||
timeseries: false,
|
||||
chartClass: 'is-primary',
|
||||
data = null;
|
||||
xProp = null;
|
||||
yProp = null;
|
||||
timeseries = false;
|
||||
chartClass = 'is-primary';
|
||||
|
||||
title: 'Line Chart',
|
||||
description: null,
|
||||
title = 'Line Chart';
|
||||
description = null;
|
||||
|
||||
// Private Properties
|
||||
|
||||
width: 0,
|
||||
height: 0,
|
||||
width = 0;
|
||||
height = 0;
|
||||
|
||||
isActive: false,
|
||||
isActive = false;
|
||||
|
||||
fillId: computed(function() {
|
||||
@computed()
|
||||
get fillId() {
|
||||
return `line-chart-fill-${guidFor(this)}`;
|
||||
}),
|
||||
}
|
||||
|
||||
maskId: computed(function() {
|
||||
@computed()
|
||||
get maskId() {
|
||||
return `line-chart-mask-${guidFor(this)}`;
|
||||
}),
|
||||
}
|
||||
|
||||
activeDatum: null,
|
||||
activeDatum = null;
|
||||
|
||||
activeDatumLabel: computed('activeDatum', function() {
|
||||
@computed('activeDatum')
|
||||
get activeDatumLabel() {
|
||||
const datum = this.activeDatum;
|
||||
|
||||
if (!datum) return;
|
||||
if (!datum) return undefined;
|
||||
|
||||
const x = datum[this.xProp];
|
||||
return this.xFormat(this.timeseries)(x);
|
||||
}),
|
||||
}
|
||||
|
||||
activeDatumValue: computed('activeDatum', function() {
|
||||
@computed('activeDatum')
|
||||
get activeDatumValue() {
|
||||
const datum = this.activeDatum;
|
||||
|
||||
if (!datum) return;
|
||||
if (!datum) return undefined;
|
||||
|
||||
const y = datum[this.yProp];
|
||||
return this.yFormat()(y);
|
||||
}),
|
||||
}
|
||||
|
||||
// Overridable functions that retrurn formatter functions
|
||||
xFormat(timeseries) {
|
||||
return timeseries ? d3TimeFormat.timeFormat('%b') : d3Format.format(',');
|
||||
},
|
||||
}
|
||||
|
||||
yFormat() {
|
||||
return d3Format.format(',.2~r');
|
||||
},
|
||||
}
|
||||
|
||||
tooltipPosition: null,
|
||||
tooltipStyle: styleStringProperty('tooltipPosition'),
|
||||
tooltipPosition = null;
|
||||
@styleStringProperty('tooltipPosition') tooltipStyle;
|
||||
|
||||
xScale: computed('data.[]', 'xProp', 'timeseries', 'yAxisOffset', function() {
|
||||
@computed('data.[]', 'xProp', 'timeseries', 'yAxisOffset')
|
||||
get xScale() {
|
||||
const xProp = this.xProp;
|
||||
const scale = this.timeseries ? d3Scale.scaleTime() : d3Scale.scaleLinear();
|
||||
const data = this.data;
|
||||
|
@ -99,25 +107,28 @@ export default Component.extend(WindowResizable, {
|
|||
scale.rangeRound([10, this.yAxisOffset]).domain(domain);
|
||||
|
||||
return scale;
|
||||
}),
|
||||
}
|
||||
|
||||
xRange: computed('data.[]', 'xFormat', 'xProp', 'timeseries', function() {
|
||||
@computed('data.[]', 'xFormat', 'xProp', 'timeseries')
|
||||
get xRange() {
|
||||
const { xProp, timeseries, data } = this;
|
||||
const range = d3Array.extent(data, d => d[xProp]);
|
||||
const formatter = this.xFormat(timeseries);
|
||||
|
||||
return range.map(formatter);
|
||||
}),
|
||||
}
|
||||
|
||||
yRange: computed('data.[]', 'yFormat', 'yProp', function() {
|
||||
@computed('data.[]', 'yFormat', 'yProp')
|
||||
get yRange() {
|
||||
const yProp = this.yProp;
|
||||
const range = d3Array.extent(this.data, d => d[yProp]);
|
||||
const formatter = this.yFormat();
|
||||
|
||||
return range.map(formatter);
|
||||
}),
|
||||
}
|
||||
|
||||
yScale: computed('data.[]', 'yProp', 'xAxisOffset', function() {
|
||||
@computed('data.[]', 'yProp', 'xAxisOffset')
|
||||
get yScale() {
|
||||
const yProp = this.yProp;
|
||||
let max = d3Array.max(this.data, d => d[yProp]) || 1;
|
||||
if (max > 1) {
|
||||
|
@ -128,9 +139,10 @@ export default Component.extend(WindowResizable, {
|
|||
.scaleLinear()
|
||||
.rangeRound([this.xAxisOffset, 10])
|
||||
.domain([0, max]);
|
||||
}),
|
||||
}
|
||||
|
||||
xAxis: computed('xScale', function() {
|
||||
@computed('xScale')
|
||||
get xAxis() {
|
||||
const formatter = this.xFormat(this.timeseries);
|
||||
|
||||
return d3Axis
|
||||
|
@ -138,17 +150,19 @@ export default Component.extend(WindowResizable, {
|
|||
.scale(this.xScale)
|
||||
.ticks(5)
|
||||
.tickFormat(formatter);
|
||||
}),
|
||||
}
|
||||
|
||||
yTicks: computed('xAxisOffset', function() {
|
||||
@computed('xAxisOffset')
|
||||
get yTicks() {
|
||||
const height = this.xAxisOffset;
|
||||
const tickCount = Math.ceil(height / 120) * 2 + 1;
|
||||
const domain = this.yScale.domain();
|
||||
const ticks = lerp(domain, tickCount);
|
||||
return domain[1] - domain[0] > 1 ? nice(ticks) : ticks;
|
||||
}),
|
||||
}
|
||||
|
||||
yAxis: computed('yScale', function() {
|
||||
@computed('yScale')
|
||||
get yAxis() {
|
||||
const formatter = this.yFormat();
|
||||
|
||||
return d3Axis
|
||||
|
@ -156,9 +170,10 @@ export default Component.extend(WindowResizable, {
|
|||
.scale(this.yScale)
|
||||
.tickValues(this.yTicks)
|
||||
.tickFormat(formatter);
|
||||
}),
|
||||
}
|
||||
|
||||
yGridlines: computed('yScale', function() {
|
||||
@computed('yScale')
|
||||
get yGridlines() {
|
||||
// The first gridline overlaps the x-axis, so remove it
|
||||
const [, ...ticks] = this.yTicks;
|
||||
|
||||
|
@ -168,33 +183,38 @@ export default Component.extend(WindowResizable, {
|
|||
.tickValues(ticks)
|
||||
.tickSize(-this.yAxisOffset)
|
||||
.tickFormat('');
|
||||
}),
|
||||
}
|
||||
|
||||
xAxisHeight: computed(function() {
|
||||
@computed()
|
||||
get xAxisHeight() {
|
||||
// Avoid divide by zero errors by always having a height
|
||||
if (!this.element) return 1;
|
||||
|
||||
const axis = this.element.querySelector('.x-axis');
|
||||
return axis && axis.getBBox().height;
|
||||
}),
|
||||
}
|
||||
|
||||
yAxisWidth: computed(function() {
|
||||
@computed()
|
||||
get yAxisWidth() {
|
||||
// Avoid divide by zero errors by always having a width
|
||||
if (!this.element) return 1;
|
||||
|
||||
const axis = this.element.querySelector('.y-axis');
|
||||
return axis && axis.getBBox().width;
|
||||
}),
|
||||
}
|
||||
|
||||
xAxisOffset: overridable('height', 'xAxisHeight', function() {
|
||||
@overridable('height', 'xAxisHeight', function() {
|
||||
return this.height - this.xAxisHeight;
|
||||
}),
|
||||
})
|
||||
xAxisOffset;
|
||||
|
||||
yAxisOffset: computed('width', 'yAxisWidth', function() {
|
||||
@computed('width', 'yAxisWidth')
|
||||
get yAxisOffset() {
|
||||
return this.width - this.yAxisWidth;
|
||||
}),
|
||||
}
|
||||
|
||||
line: computed('data.[]', 'xScale', 'yScale', function() {
|
||||
@computed('data.[]', 'xScale', 'yScale')
|
||||
get line() {
|
||||
const { xScale, yScale, xProp, yProp } = this;
|
||||
|
||||
const line = d3Shape
|
||||
|
@ -204,9 +224,10 @@ export default Component.extend(WindowResizable, {
|
|||
.y(d => yScale(d[yProp]));
|
||||
|
||||
return line(this.data);
|
||||
}),
|
||||
}
|
||||
|
||||
area: computed('data.[]', 'xScale', 'yScale', function() {
|
||||
@computed('data.[]', 'xScale', 'yScale')
|
||||
get area() {
|
||||
const { xScale, yScale, xProp, yProp } = this;
|
||||
|
||||
const area = d3Shape
|
||||
|
@ -217,7 +238,7 @@ export default Component.extend(WindowResizable, {
|
|||
.y1(d => yScale(d[yProp]));
|
||||
|
||||
return area(this.data);
|
||||
}),
|
||||
}
|
||||
|
||||
didInsertElement() {
|
||||
this.updateDimensions();
|
||||
|
@ -243,11 +264,11 @@ export default Component.extend(WindowResizable, {
|
|||
run.schedule('afterRender', this, () => this.set('isActive', false));
|
||||
this.set('activeDatum', null);
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
didUpdateAttrs() {
|
||||
this.renderChart();
|
||||
},
|
||||
}
|
||||
|
||||
updateActiveDatum(mouseX) {
|
||||
const { xScale, xProp, yScale, yProp, data } = this;
|
||||
|
@ -278,11 +299,12 @@ export default Component.extend(WindowResizable, {
|
|||
left: xScale(datum[xProp]),
|
||||
top: yScale(datum[yProp]) - 10,
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
updateChart: observer('data.[]', function() {
|
||||
@observes('data.[]')
|
||||
updateChart() {
|
||||
this.renderChart();
|
||||
}),
|
||||
}
|
||||
|
||||
// The renderChart method should only ever be responsible for runtime calculations
|
||||
// and appending d3 created elements to the DOM (such as axes).
|
||||
|
@ -308,7 +330,7 @@ export default Component.extend(WindowResizable, {
|
|||
this.updateActiveDatum(this.latestMouseX);
|
||||
}
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
mountD3Elements() {
|
||||
if (!this.isDestroyed && !this.isDestroying) {
|
||||
|
@ -316,11 +338,11 @@ export default Component.extend(WindowResizable, {
|
|||
d3.select(this.element.querySelector('.y-axis')).call(this.yAxis);
|
||||
d3.select(this.element.querySelector('.y-gridlines')).call(this.yGridlines);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
windowResizeHandler() {
|
||||
run.once(this, this.updateDimensions);
|
||||
},
|
||||
}
|
||||
|
||||
updateDimensions() {
|
||||
const $svg = this.element.querySelector('svg');
|
||||
|
@ -329,5 +351,5 @@ export default Component.extend(WindowResizable, {
|
|||
|
||||
this.setProperties({ width, height });
|
||||
this.renderChart();
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import Component from '@ember/component';
|
||||
import { inject as service } from '@ember/service';
|
||||
|
||||
export default Component.extend({
|
||||
userSettings: service(),
|
||||
export default class PageSizeSelect extends Component {
|
||||
@service userSettings;
|
||||
|
||||
tagName: '',
|
||||
pageSizeOptions: Object.freeze([10, 25, 50]),
|
||||
tagName = '';
|
||||
pageSizeOptions = Object.freeze([10, 25, 50]);
|
||||
|
||||
onChange() {},
|
||||
});
|
||||
onChange() {}
|
||||
}
|
||||
|
|
|
@ -1,58 +1,68 @@
|
|||
/* eslint-disable ember/no-observers */
|
||||
import Controller from '@ember/controller';
|
||||
import { inject as service } from '@ember/service';
|
||||
import { computed, observer } from '@ember/object';
|
||||
import { action, computed } from '@ember/object';
|
||||
import { observes } from '@ember-decorators/object';
|
||||
import { computed as overridable } from 'ember-overridable-computed';
|
||||
import { alias } from '@ember/object/computed';
|
||||
import { task } from 'ember-concurrency';
|
||||
import Sortable from 'nomad-ui/mixins/sortable';
|
||||
import { lazyClick } from 'nomad-ui/helpers/lazy-click';
|
||||
import { watchRecord } from 'nomad-ui/utils/properties/watch';
|
||||
import classic from 'ember-classic-decorator';
|
||||
|
||||
export default Controller.extend(Sortable, {
|
||||
token: service(),
|
||||
@classic
|
||||
export default class IndexController extends Controller.extend(Sortable) {
|
||||
@service token;
|
||||
|
||||
queryParams: {
|
||||
sortProperty: 'sort',
|
||||
sortDescending: 'desc',
|
||||
},
|
||||
queryParams = [
|
||||
{
|
||||
sortProperty: 'sort',
|
||||
},
|
||||
{
|
||||
sortDescending: 'desc',
|
||||
},
|
||||
];
|
||||
|
||||
sortProperty: 'name',
|
||||
sortDescending: false,
|
||||
sortProperty = 'name';
|
||||
sortDescending = false;
|
||||
|
||||
listToSort: alias('model.states'),
|
||||
sortedStates: alias('listSorted'),
|
||||
@alias('model.states') listToSort;
|
||||
@alias('listSorted') sortedStates;
|
||||
|
||||
// Set in the route
|
||||
preempter: null,
|
||||
preempter = null;
|
||||
|
||||
error: overridable(() => {
|
||||
@overridable(function() {
|
||||
// { title, description }
|
||||
return null;
|
||||
}),
|
||||
})
|
||||
error;
|
||||
|
||||
network: alias('model.allocatedResources.networks.firstObject'),
|
||||
@alias('model.allocatedResources.networks.firstObject') network;
|
||||
|
||||
services: computed('model.taskGroup.services.@each.name', function() {
|
||||
@computed('model.taskGroup.services.@each.name')
|
||||
get services() {
|
||||
return this.get('model.taskGroup.services').sortBy('name');
|
||||
}),
|
||||
}
|
||||
|
||||
onDismiss() {
|
||||
this.set('error', null);
|
||||
},
|
||||
}
|
||||
|
||||
watchNext: watchRecord('allocation'),
|
||||
@watchRecord('allocation') watchNext;
|
||||
|
||||
observeWatchNext: observer('model.nextAllocation.clientStatus', function() {
|
||||
@observes('model.nextAllocation.clientStatus')
|
||||
observeWatchNext() {
|
||||
const nextAllocation = this.model.nextAllocation;
|
||||
if (nextAllocation && nextAllocation.content) {
|
||||
this.watchNext.perform(nextAllocation);
|
||||
} else {
|
||||
this.watchNext.cancelAll();
|
||||
}
|
||||
}),
|
||||
}
|
||||
|
||||
stopAllocation: task(function*() {
|
||||
@task(function*() {
|
||||
try {
|
||||
yield this.model.stop();
|
||||
// Eagerly update the allocation clientStatus to avoid flickering
|
||||
|
@ -63,9 +73,10 @@ export default Controller.extend(Sortable, {
|
|||
description: 'Your ACL token does not grant allocation lifecycle permissions.',
|
||||
});
|
||||
}
|
||||
}),
|
||||
})
|
||||
stopAllocation;
|
||||
|
||||
restartAllocation: task(function*() {
|
||||
@task(function*() {
|
||||
try {
|
||||
yield this.model.restart();
|
||||
} catch (err) {
|
||||
|
@ -74,15 +85,16 @@ export default Controller.extend(Sortable, {
|
|||
description: 'Your ACL token does not grant allocation lifecycle permissions.',
|
||||
});
|
||||
}
|
||||
}),
|
||||
})
|
||||
restartAllocation;
|
||||
|
||||
actions: {
|
||||
gotoTask(allocation, task) {
|
||||
this.transitionToRoute('allocations.allocation.task', task);
|
||||
},
|
||||
@action
|
||||
gotoTask(allocation, task) {
|
||||
this.transitionToRoute('allocations.allocation.task', task);
|
||||
}
|
||||
|
||||
taskClick(allocation, task, event) {
|
||||
lazyClick([() => this.send('gotoTask', allocation, task), event]);
|
||||
},
|
||||
},
|
||||
});
|
||||
@action
|
||||
taskClick(allocation, task, event) {
|
||||
lazyClick([() => this.send('gotoTask', allocation, task), event]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,84 +1,99 @@
|
|||
/* eslint-disable ember/no-observers */
|
||||
import { alias } from '@ember/object/computed';
|
||||
import Controller from '@ember/controller';
|
||||
import { computed, observer } from '@ember/object';
|
||||
import { action, computed } from '@ember/object';
|
||||
import { observes } from '@ember-decorators/object';
|
||||
import { task } from 'ember-concurrency';
|
||||
import Sortable from 'nomad-ui/mixins/sortable';
|
||||
import Searchable from 'nomad-ui/mixins/searchable';
|
||||
import messageFromAdapterError from 'nomad-ui/utils/message-from-adapter-error';
|
||||
import classic from 'ember-classic-decorator';
|
||||
|
||||
export default Controller.extend(Sortable, Searchable, {
|
||||
queryParams: {
|
||||
currentPage: 'page',
|
||||
searchTerm: 'search',
|
||||
sortProperty: 'sort',
|
||||
sortDescending: 'desc',
|
||||
onlyPreemptions: 'preemptions',
|
||||
},
|
||||
@classic
|
||||
export default class ClientController extends Controller.extend(Sortable, Searchable) {
|
||||
queryParams = [
|
||||
{
|
||||
currentPage: 'page',
|
||||
},
|
||||
{
|
||||
searchTerm: 'search',
|
||||
},
|
||||
{
|
||||
sortProperty: 'sort',
|
||||
},
|
||||
{
|
||||
sortDescending: 'desc',
|
||||
},
|
||||
{
|
||||
onlyPreemptions: 'preemptions',
|
||||
},
|
||||
];
|
||||
|
||||
// Set in the route
|
||||
flagAsDraining: false,
|
||||
flagAsDraining = false;
|
||||
|
||||
currentPage: 1,
|
||||
pageSize: 8,
|
||||
currentPage = 1;
|
||||
pageSize = 8;
|
||||
|
||||
sortProperty: 'modifyIndex',
|
||||
sortDescending: true,
|
||||
sortProperty = 'modifyIndex';
|
||||
sortDescending = true;
|
||||
|
||||
searchProps: computed(function() {
|
||||
@computed()
|
||||
get searchProps() {
|
||||
return ['shortId', 'name'];
|
||||
}),
|
||||
}
|
||||
|
||||
onlyPreemptions: false,
|
||||
onlyPreemptions = false;
|
||||
|
||||
visibleAllocations: computed(
|
||||
'model.allocations.[]',
|
||||
'preemptions.[]',
|
||||
'onlyPreemptions',
|
||||
function() {
|
||||
return this.onlyPreemptions ? this.preemptions : this.model.allocations;
|
||||
}
|
||||
),
|
||||
@computed('model.allocations.[]', 'preemptions.[]', 'onlyPreemptions')
|
||||
get visibleAllocations() {
|
||||
return this.onlyPreemptions ? this.preemptions : this.model.allocations;
|
||||
}
|
||||
|
||||
listToSort: alias('visibleAllocations'),
|
||||
listToSearch: alias('listSorted'),
|
||||
sortedAllocations: alias('listSearched'),
|
||||
@alias('visibleAllocations') listToSort;
|
||||
@alias('listSorted') listToSearch;
|
||||
@alias('listSearched') sortedAllocations;
|
||||
|
||||
eligibilityError: null,
|
||||
stopDrainError: null,
|
||||
drainError: null,
|
||||
showDrainNotification: false,
|
||||
showDrainUpdateNotification: false,
|
||||
showDrainStoppedNotification: false,
|
||||
eligibilityError = null;
|
||||
stopDrainError = null;
|
||||
drainError = null;
|
||||
showDrainNotification = false;
|
||||
showDrainUpdateNotification = false;
|
||||
showDrainStoppedNotification = false;
|
||||
|
||||
preemptions: computed('model.allocations.@each.wasPreempted', function() {
|
||||
@computed('model.allocations.@each.wasPreempted')
|
||||
get preemptions() {
|
||||
return this.model.allocations.filterBy('wasPreempted');
|
||||
}),
|
||||
}
|
||||
|
||||
sortedEvents: computed('model.events.@each.time', function() {
|
||||
@computed('model.events.@each.time')
|
||||
get sortedEvents() {
|
||||
return this.get('model.events')
|
||||
.sortBy('time')
|
||||
.reverse();
|
||||
}),
|
||||
}
|
||||
|
||||
sortedDrivers: computed('model.drivers.@each.name', function() {
|
||||
@computed('model.drivers.@each.name')
|
||||
get sortedDrivers() {
|
||||
return this.get('model.drivers').sortBy('name');
|
||||
}),
|
||||
}
|
||||
|
||||
sortedHostVolumes: computed('model.hostVolumes.@each.name', function() {
|
||||
@computed('model.hostVolumes.@each.name')
|
||||
get sortedHostVolumes() {
|
||||
return this.model.hostVolumes.sortBy('name');
|
||||
}),
|
||||
}
|
||||
|
||||
setEligibility: task(function*(value) {
|
||||
@(task(function*(value) {
|
||||
try {
|
||||
yield value ? this.model.setEligible() : this.model.setIneligible();
|
||||
} catch (err) {
|
||||
const error = messageFromAdapterError(err) || 'Could not set eligibility';
|
||||
this.set('eligibilityError', error);
|
||||
}
|
||||
}).drop(),
|
||||
}).drop())
|
||||
setEligibility;
|
||||
|
||||
stopDrain: task(function*() {
|
||||
@(task(function*() {
|
||||
try {
|
||||
this.set('flagAsDraining', false);
|
||||
yield this.model.cancelDrain();
|
||||
|
@ -88,9 +103,10 @@ export default Controller.extend(Sortable, Searchable, {
|
|||
const error = messageFromAdapterError(err) || 'Could not stop drain';
|
||||
this.set('stopDrainError', error);
|
||||
}
|
||||
}).drop(),
|
||||
}).drop())
|
||||
stopDrain;
|
||||
|
||||
forceDrain: task(function*() {
|
||||
@(task(function*() {
|
||||
try {
|
||||
yield this.model.forceDrain({
|
||||
IgnoreSystemJobs: this.model.drainStrategy.ignoreSystemJobs,
|
||||
|
@ -99,32 +115,36 @@ export default Controller.extend(Sortable, Searchable, {
|
|||
const error = messageFromAdapterError(err) || 'Could not force drain';
|
||||
this.set('drainError', error);
|
||||
}
|
||||
}).drop(),
|
||||
}).drop())
|
||||
forceDrain;
|
||||
|
||||
triggerDrainNotification: observer('model.isDraining', function() {
|
||||
@observes('model.isDraining')
|
||||
triggerDrainNotification() {
|
||||
if (!this.model.isDraining && this.flagAsDraining) {
|
||||
this.set('showDrainNotification', true);
|
||||
}
|
||||
|
||||
this.set('flagAsDraining', this.model.isDraining);
|
||||
}),
|
||||
}
|
||||
|
||||
actions: {
|
||||
gotoAllocation(allocation) {
|
||||
this.transitionToRoute('allocations.allocation', allocation);
|
||||
},
|
||||
@action
|
||||
gotoAllocation(allocation) {
|
||||
this.transitionToRoute('allocations.allocation', allocation);
|
||||
}
|
||||
|
||||
setPreemptionFilter(value) {
|
||||
this.set('onlyPreemptions', value);
|
||||
},
|
||||
@action
|
||||
setPreemptionFilter(value) {
|
||||
this.set('onlyPreemptions', value);
|
||||
}
|
||||
|
||||
drainNotify(isUpdating) {
|
||||
this.set('showDrainUpdateNotification', isUpdating);
|
||||
},
|
||||
@action
|
||||
drainNotify(isUpdating) {
|
||||
this.set('showDrainUpdateNotification', isUpdating);
|
||||
}
|
||||
|
||||
drainError(err) {
|
||||
const error = messageFromAdapterError(err) || 'Could not run drain';
|
||||
this.set('drainError', error);
|
||||
},
|
||||
},
|
||||
});
|
||||
@action
|
||||
drainError(err) {
|
||||
const error = messageFromAdapterError(err) || 'Could not run drain';
|
||||
this.set('drainError', error);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,36 +1,39 @@
|
|||
import { inject as service } from '@ember/service';
|
||||
import Controller from '@ember/controller';
|
||||
import { computed } from '@ember/object';
|
||||
import { action, computed } from '@ember/object';
|
||||
import { alias, mapBy, sort, uniq } from '@ember/object/computed';
|
||||
import escapeTaskName from 'nomad-ui/utils/escape-task-name';
|
||||
import ExecCommandEditorXtermAdapter from 'nomad-ui/utils/classes/exec-command-editor-xterm-adapter';
|
||||
import ExecSocketXtermAdapter from 'nomad-ui/utils/classes/exec-socket-xterm-adapter';
|
||||
import localStorageProperty from 'nomad-ui/utils/properties/local-storage';
|
||||
import classic from 'ember-classic-decorator';
|
||||
|
||||
const ANSI_UI_GRAY_400 = '\x1b[38;2;142;150;163m';
|
||||
const ANSI_WHITE = '\x1b[0m';
|
||||
|
||||
export default Controller.extend({
|
||||
sockets: service(),
|
||||
system: service(),
|
||||
token: service(),
|
||||
@classic
|
||||
export default class ExecController extends Controller {
|
||||
@service sockets;
|
||||
@service system;
|
||||
@service token;
|
||||
|
||||
queryParams: ['allocation'],
|
||||
queryParams = ['allocation'];
|
||||
|
||||
command: localStorageProperty('nomadExecCommand', '/bin/bash'),
|
||||
socketOpen: false,
|
||||
@localStorageProperty('nomadExecCommand', '/bin/bash') command;
|
||||
socketOpen = false;
|
||||
|
||||
pendingAndRunningAllocations: computed('model.allocations.@each.clientStatus', function() {
|
||||
@computed('model.allocations.@each.clientStatus')
|
||||
get pendingAndRunningAllocations() {
|
||||
return this.model.allocations.filter(
|
||||
allocation => allocation.clientStatus === 'pending' || allocation.clientStatus === 'running'
|
||||
);
|
||||
}),
|
||||
}
|
||||
|
||||
pendingAndRunningTaskGroups: mapBy('pendingAndRunningAllocations', 'taskGroup'),
|
||||
uniquePendingAndRunningTaskGroups: uniq('pendingAndRunningTaskGroups'),
|
||||
@mapBy('pendingAndRunningAllocations', 'taskGroup') pendingAndRunningTaskGroups;
|
||||
@uniq('pendingAndRunningTaskGroups') uniquePendingAndRunningTaskGroups;
|
||||
|
||||
taskGroupSorting: Object.freeze(['name']),
|
||||
sortedTaskGroups: sort('uniquePendingAndRunningTaskGroups', 'taskGroupSorting'),
|
||||
taskGroupSorting = Object.freeze(['name']);
|
||||
@sort('uniquePendingAndRunningTaskGroups', 'taskGroupSorting') sortedTaskGroups;
|
||||
|
||||
setUpTerminal(Terminal) {
|
||||
this.terminal = new Terminal({ fontFamily: 'monospace', fontWeight: '400' });
|
||||
|
@ -38,86 +41,85 @@ export default Controller.extend({
|
|||
|
||||
this.terminal.write(ANSI_UI_GRAY_400);
|
||||
this.terminal.writeln('Select a task to start your session.');
|
||||
},
|
||||
}
|
||||
|
||||
allocations: alias('model.allocations'),
|
||||
@alias('model.allocations') allocations;
|
||||
|
||||
taskState: computed(
|
||||
@computed(
|
||||
'allocations.{[],@each.isActive}',
|
||||
'allocationShortId',
|
||||
'taskName',
|
||||
'taskGroupName',
|
||||
'allocation',
|
||||
'allocation.states.@each.{name,isRunning}',
|
||||
function() {
|
||||
if (!this.allocations) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let allocation;
|
||||
|
||||
if (this.allocationShortId) {
|
||||
allocation = this.allocations.findBy('shortId', this.allocationShortId);
|
||||
} else {
|
||||
allocation = this.allocations.find(allocation =>
|
||||
allocation.states
|
||||
.filterBy('isActive')
|
||||
.mapBy('name')
|
||||
.includes(this.taskName)
|
||||
);
|
||||
}
|
||||
|
||||
if (allocation) {
|
||||
return allocation.states.find(state => state.name === this.taskName);
|
||||
}
|
||||
|
||||
return;
|
||||
'allocation.states.@each.{name,isRunning}'
|
||||
)
|
||||
get taskState() {
|
||||
if (!this.allocations) {
|
||||
return false;
|
||||
}
|
||||
),
|
||||
|
||||
actions: {
|
||||
setTaskProperties({ allocationShortId, taskName, taskGroupName }) {
|
||||
this.setProperties({
|
||||
allocationShortId,
|
||||
taskName,
|
||||
taskGroupName,
|
||||
});
|
||||
let allocation;
|
||||
|
||||
if (this.taskState) {
|
||||
this.terminal.write(ANSI_UI_GRAY_400);
|
||||
this.terminal.writeln('');
|
||||
if (this.allocationShortId) {
|
||||
allocation = this.allocations.findBy('shortId', this.allocationShortId);
|
||||
} else {
|
||||
allocation = this.allocations.find(allocation =>
|
||||
allocation.states
|
||||
.filterBy('isActive')
|
||||
.mapBy('name')
|
||||
.includes(this.taskName)
|
||||
);
|
||||
}
|
||||
|
||||
if (!allocationShortId) {
|
||||
this.terminal.writeln(
|
||||
'Multiple instances of this task are running. The allocation below was selected by random draw.'
|
||||
);
|
||||
this.terminal.writeln('');
|
||||
}
|
||||
if (allocation) {
|
||||
return allocation.states.find(state => state.name === this.taskName);
|
||||
}
|
||||
|
||||
this.terminal.writeln('Customize your command, then hit ‘return’ to run.');
|
||||
this.terminal.writeln('');
|
||||
this.terminal.write(
|
||||
`$ nomad alloc exec -i -t -task ${escapeTaskName(taskName)} ${
|
||||
this.taskState.allocation.shortId
|
||||
} `
|
||||
);
|
||||
|
||||
this.terminal.write(ANSI_WHITE);
|
||||
|
||||
this.terminal.write(this.command);
|
||||
|
||||
if (this.commandEditorAdapter) {
|
||||
this.commandEditorAdapter.destroy();
|
||||
}
|
||||
|
||||
this.commandEditorAdapter = new ExecCommandEditorXtermAdapter(
|
||||
this.terminal,
|
||||
this.openAndConnectSocket.bind(this),
|
||||
this.command
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@action
|
||||
setTaskProperties({ allocationShortId, taskName, taskGroupName }) {
|
||||
this.setProperties({
|
||||
allocationShortId,
|
||||
taskName,
|
||||
taskGroupName,
|
||||
});
|
||||
|
||||
if (this.taskState) {
|
||||
this.terminal.write(ANSI_UI_GRAY_400);
|
||||
this.terminal.writeln('');
|
||||
|
||||
if (!allocationShortId) {
|
||||
this.terminal.writeln(
|
||||
'Multiple instances of this task are running. The allocation below was selected by random draw.'
|
||||
);
|
||||
this.terminal.writeln('');
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
this.terminal.writeln('Customize your command, then hit ‘return’ to run.');
|
||||
this.terminal.writeln('');
|
||||
this.terminal.write(
|
||||
`$ nomad alloc exec -i -t -task ${escapeTaskName(taskName)} ${
|
||||
this.taskState.allocation.shortId
|
||||
} `
|
||||
);
|
||||
|
||||
this.terminal.write(ANSI_WHITE);
|
||||
|
||||
this.terminal.write(this.command);
|
||||
|
||||
if (this.commandEditorAdapter) {
|
||||
this.commandEditorAdapter.destroy();
|
||||
}
|
||||
|
||||
this.commandEditorAdapter = new ExecCommandEditorXtermAdapter(
|
||||
this.terminal,
|
||||
this.openAndConnectSocket.bind(this),
|
||||
this.command
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
openAndConnectSocket(command) {
|
||||
if (this.taskState) {
|
||||
|
@ -129,5 +131,5 @@ export default Controller.extend({
|
|||
} else {
|
||||
this.terminal.writeln(`Failed to open a socket because task ${this.taskName} is not active.`);
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,66 +3,69 @@ import { reads } from '@ember/object/computed';
|
|||
import Controller from '@ember/controller';
|
||||
import { getOwner } from '@ember/application';
|
||||
import { alias } from '@ember/object/computed';
|
||||
import { action } from '@ember/object';
|
||||
import classic from 'ember-classic-decorator';
|
||||
|
||||
export default Controller.extend({
|
||||
token: service(),
|
||||
system: service(),
|
||||
store: service(),
|
||||
@classic
|
||||
export default class Tokens extends Controller {
|
||||
@service token;
|
||||
@service system;
|
||||
@service store;
|
||||
|
||||
secret: reads('token.secret'),
|
||||
@reads('token.secret') secret;
|
||||
|
||||
tokenIsValid: false,
|
||||
tokenIsInvalid: false,
|
||||
tokenRecord: alias('token.selfToken'),
|
||||
tokenIsValid = false;
|
||||
tokenIsInvalid = false;
|
||||
@alias('token.selfToken') tokenRecord;
|
||||
|
||||
resetStore() {
|
||||
this.store.unloadAll();
|
||||
},
|
||||
}
|
||||
|
||||
actions: {
|
||||
clearTokenProperties() {
|
||||
this.token.setProperties({
|
||||
secret: undefined,
|
||||
});
|
||||
this.setProperties({
|
||||
tokenIsValid: false,
|
||||
tokenIsInvalid: false,
|
||||
});
|
||||
this.resetStore();
|
||||
this.token.reset();
|
||||
},
|
||||
@action
|
||||
clearTokenProperties() {
|
||||
this.token.setProperties({
|
||||
secret: undefined,
|
||||
});
|
||||
this.setProperties({
|
||||
tokenIsValid: false,
|
||||
tokenIsInvalid: false,
|
||||
});
|
||||
this.resetStore();
|
||||
this.token.reset();
|
||||
}
|
||||
|
||||
verifyToken() {
|
||||
const { secret } = this;
|
||||
const TokenAdapter = getOwner(this).lookup('adapter:token');
|
||||
@action
|
||||
verifyToken() {
|
||||
const { secret } = this;
|
||||
const TokenAdapter = getOwner(this).lookup('adapter:token');
|
||||
|
||||
this.set('token.secret', secret);
|
||||
this.set('token.secret', secret);
|
||||
|
||||
TokenAdapter.findSelf().then(
|
||||
() => {
|
||||
// Clear out all data to ensure only data the new token is privileged to
|
||||
// see is shown
|
||||
this.system.reset();
|
||||
this.resetStore();
|
||||
TokenAdapter.findSelf().then(
|
||||
() => {
|
||||
// Clear out all data to ensure only data the new token is privileged to
|
||||
// see is shown
|
||||
this.system.reset();
|
||||
this.resetStore();
|
||||
|
||||
// Refetch the token and associated policies
|
||||
this.get('token.fetchSelfTokenAndPolicies')
|
||||
.perform()
|
||||
.catch();
|
||||
// Refetch the token and associated policies
|
||||
this.get('token.fetchSelfTokenAndPolicies')
|
||||
.perform()
|
||||
.catch();
|
||||
|
||||
this.setProperties({
|
||||
tokenIsValid: true,
|
||||
tokenIsInvalid: false,
|
||||
});
|
||||
},
|
||||
() => {
|
||||
this.set('token.secret', undefined);
|
||||
this.setProperties({
|
||||
tokenIsValid: false,
|
||||
tokenIsInvalid: true,
|
||||
});
|
||||
}
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
||||
this.setProperties({
|
||||
tokenIsValid: true,
|
||||
tokenIsInvalid: false,
|
||||
});
|
||||
},
|
||||
() => {
|
||||
this.set('token.secret', undefined);
|
||||
this.setProperties({
|
||||
tokenIsValid: false,
|
||||
tokenIsInvalid: true,
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,24 +3,27 @@ import { next } from '@ember/runloop';
|
|||
import Route from '@ember/routing/route';
|
||||
import { AbortError } from '@ember-data/adapter/error';
|
||||
import RSVP from 'rsvp';
|
||||
import { action } from '@ember/object';
|
||||
import classic from 'ember-classic-decorator';
|
||||
|
||||
export default Route.extend({
|
||||
config: service(),
|
||||
system: service(),
|
||||
store: service(),
|
||||
token: service(),
|
||||
@classic
|
||||
export default class ApplicationRoute extends Route {
|
||||
@service config;
|
||||
@service system;
|
||||
@service store;
|
||||
@service token;
|
||||
|
||||
queryParams: {
|
||||
queryParams = {
|
||||
region: {
|
||||
refreshModel: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
resetController(controller, isExiting) {
|
||||
if (isExiting) {
|
||||
controller.set('error', null);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
beforeModel(transition) {
|
||||
const fetchSelfTokenAndPolicies = this.get('token.fetchSelfTokenAndPolicies')
|
||||
|
@ -51,13 +54,13 @@ export default Route.extend({
|
|||
|
||||
return promises;
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
// Model is being used as a way to transfer the provided region
|
||||
// query param to update the controller state.
|
||||
model(params) {
|
||||
return params.region;
|
||||
},
|
||||
}
|
||||
|
||||
setupController(controller, model) {
|
||||
const queryParam = model;
|
||||
|
@ -68,24 +71,25 @@ export default Route.extend({
|
|||
});
|
||||
}
|
||||
|
||||
return this._super(...arguments);
|
||||
},
|
||||
return super.setupController(...arguments);
|
||||
}
|
||||
|
||||
actions: {
|
||||
didTransition() {
|
||||
if (!this.get('config.isTest')) {
|
||||
window.scrollTo(0, 0);
|
||||
}
|
||||
},
|
||||
@action
|
||||
didTransition() {
|
||||
if (!this.get('config.isTest')) {
|
||||
window.scrollTo(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
willTransition() {
|
||||
this.controllerFor('application').set('error', null);
|
||||
},
|
||||
@action
|
||||
willTransition() {
|
||||
this.controllerFor('application').set('error', null);
|
||||
}
|
||||
|
||||
error(error) {
|
||||
if (!(error instanceof AbortError)) {
|
||||
this.controllerFor('application').set('error', error);
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
@action
|
||||
error(error) {
|
||||
if (!(error instanceof AbortError)) {
|
||||
this.controllerFor('application').set('error', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,26 +3,28 @@ import Route from '@ember/routing/route';
|
|||
import RSVP from 'rsvp';
|
||||
import WithForbiddenState from 'nomad-ui/mixins/with-forbidden-state';
|
||||
import notifyForbidden from 'nomad-ui/utils/notify-forbidden';
|
||||
import classic from 'ember-classic-decorator';
|
||||
|
||||
export default Route.extend(WithForbiddenState, {
|
||||
store: service(),
|
||||
system: service(),
|
||||
@classic
|
||||
export default class ClientsRoute extends Route.extend(WithForbiddenState) {
|
||||
@service store;
|
||||
@service system;
|
||||
|
||||
breadcrumbs: Object.freeze([
|
||||
breadcrumbs = Object.freeze([
|
||||
{
|
||||
label: 'Clients',
|
||||
args: ['clients.index'],
|
||||
},
|
||||
]),
|
||||
]);
|
||||
|
||||
beforeModel() {
|
||||
return this.get('system.leader');
|
||||
},
|
||||
}
|
||||
|
||||
model() {
|
||||
return RSVP.hash({
|
||||
nodes: this.store.findAll('node'),
|
||||
agents: this.store.findAll('agent'),
|
||||
}).catch(notifyForbidden(this));
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,17 +3,17 @@ import Route from '@ember/routing/route';
|
|||
import WithForbiddenState from 'nomad-ui/mixins/with-forbidden-state';
|
||||
import notifyForbidden from 'nomad-ui/utils/notify-forbidden';
|
||||
|
||||
export default Route.extend(WithForbiddenState, {
|
||||
store: service(),
|
||||
export default class PluginsRoute extends Route.extend(WithForbiddenState) {
|
||||
@service store;
|
||||
|
||||
breadcrumbs: Object.freeze([
|
||||
breadcrumbs = Object.freeze([
|
||||
{
|
||||
label: 'Storage',
|
||||
args: ['csi.index'],
|
||||
},
|
||||
]),
|
||||
]);
|
||||
|
||||
model() {
|
||||
return this.store.query('plugin', { type: 'csi' }).catch(notifyForbidden(this));
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,23 +2,25 @@ import { inject as service } from '@ember/service';
|
|||
import Route from '@ember/routing/route';
|
||||
import WithForbiddenState from 'nomad-ui/mixins/with-forbidden-state';
|
||||
import notifyForbidden from 'nomad-ui/utils/notify-forbidden';
|
||||
import classic from 'ember-classic-decorator';
|
||||
|
||||
export default Route.extend(WithForbiddenState, {
|
||||
system: service(),
|
||||
store: service(),
|
||||
@classic
|
||||
export default class VolumesRoute extends Route.extend(WithForbiddenState) {
|
||||
@service system;
|
||||
@service store;
|
||||
|
||||
breadcrumbs: Object.freeze([
|
||||
breadcrumbs = Object.freeze([
|
||||
{
|
||||
label: 'Storage',
|
||||
args: ['csi.index'],
|
||||
},
|
||||
]),
|
||||
]);
|
||||
|
||||
queryParams: {
|
||||
queryParams = {
|
||||
volumeNamespace: {
|
||||
refreshModel: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
beforeModel(transition) {
|
||||
return this.get('system.namespaces').then(namespaces => {
|
||||
|
@ -27,7 +29,7 @@ export default Route.extend(WithForbiddenState, {
|
|||
|
||||
return namespaces;
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
model() {
|
||||
return this.store
|
||||
|
@ -37,5 +39,5 @@ export default Route.extend(WithForbiddenState, {
|
|||
return volumes;
|
||||
})
|
||||
.catch(notifyForbidden(this));
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,14 +4,16 @@ import notifyError from 'nomad-ui/utils/notify-error';
|
|||
import { collect } from '@ember/object/computed';
|
||||
import WithWatchers from 'nomad-ui/mixins/with-watchers';
|
||||
import { watchRecord, watchRelationship } from 'nomad-ui/utils/properties/watch';
|
||||
import classic from 'ember-classic-decorator';
|
||||
|
||||
export default Route.extend(WithWatchers, {
|
||||
store: service(),
|
||||
token: service(),
|
||||
@classic
|
||||
export default class ExecRoute extends Route.extend(WithWatchers) {
|
||||
@service store;
|
||||
@service token;
|
||||
|
||||
serialize(model) {
|
||||
return { job_name: model.get('plainId') };
|
||||
},
|
||||
}
|
||||
|
||||
model(params, transition) {
|
||||
const namespace = transition.to.queryParams.namespace || this.get('system.activeNamespace.id');
|
||||
|
@ -28,22 +30,22 @@ export default Route.extend(WithWatchers, {
|
|||
const xtermImport = import('xterm').then(module => module.Terminal);
|
||||
|
||||
return Promise.all([jobPromise, xtermImport]);
|
||||
},
|
||||
}
|
||||
|
||||
setupController(controller, [job, Terminal]) {
|
||||
this._super(controller, job);
|
||||
super.setupController(controller, job);
|
||||
controller.setUpTerminal(Terminal);
|
||||
},
|
||||
}
|
||||
|
||||
startWatchers(controller, model) {
|
||||
if (model) {
|
||||
controller.set('watcher', this.watch.perform(model));
|
||||
controller.set('watchAllocations', this.watchAllocations.perform(model));
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
watch: watchRecord('job'),
|
||||
watchAllocations: watchRelationship('allocations'),
|
||||
@watchRecord('job') watch;
|
||||
@watchRelationship('allocations') watchAllocations;
|
||||
|
||||
watchers: collect('watch', 'watchAllocations'),
|
||||
});
|
||||
@collect('watch', 'watchAllocations') watchers;
|
||||
}
|
||||
|
|
|
@ -2,23 +2,26 @@ import { inject as service } from '@ember/service';
|
|||
import Route from '@ember/routing/route';
|
||||
import WithForbiddenState from 'nomad-ui/mixins/with-forbidden-state';
|
||||
import notifyForbidden from 'nomad-ui/utils/notify-forbidden';
|
||||
import { action } from '@ember/object';
|
||||
import classic from 'ember-classic-decorator';
|
||||
|
||||
export default Route.extend(WithForbiddenState, {
|
||||
system: service(),
|
||||
store: service(),
|
||||
@classic
|
||||
export default class JobsRoute extends Route.extend(WithForbiddenState) {
|
||||
@service store;
|
||||
@service system;
|
||||
|
||||
breadcrumbs: Object.freeze([
|
||||
breadcrumbs = Object.freeze([
|
||||
{
|
||||
label: 'Jobs',
|
||||
args: ['jobs.index'],
|
||||
},
|
||||
]),
|
||||
]);
|
||||
|
||||
queryParams: {
|
||||
queryParams = {
|
||||
jobNamespace: {
|
||||
refreshModel: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
beforeModel(transition) {
|
||||
return this.get('system.namespaces').then(namespaces => {
|
||||
|
@ -27,15 +30,14 @@ export default Route.extend(WithForbiddenState, {
|
|||
|
||||
return namespaces;
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
model() {
|
||||
return this.store.findAll('job', { reload: true }).catch(notifyForbidden(this));
|
||||
},
|
||||
}
|
||||
|
||||
actions: {
|
||||
refreshRoute() {
|
||||
this.refresh();
|
||||
},
|
||||
},
|
||||
});
|
||||
@action
|
||||
refreshRoute() {
|
||||
this.refresh();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,33 +1,35 @@
|
|||
import Route from '@ember/routing/route';
|
||||
import { inject as service } from '@ember/service';
|
||||
import classic from 'ember-classic-decorator';
|
||||
|
||||
export default Route.extend({
|
||||
can: service(),
|
||||
store: service(),
|
||||
system: service(),
|
||||
@classic
|
||||
export default class RunRoute extends Route {
|
||||
@service can;
|
||||
@service store;
|
||||
@service system;
|
||||
|
||||
breadcrumbs: Object.freeze([
|
||||
breadcrumbs = Object.freeze([
|
||||
{
|
||||
label: 'Run',
|
||||
args: ['jobs.run'],
|
||||
},
|
||||
]),
|
||||
]);
|
||||
|
||||
beforeModel() {
|
||||
if (this.can.cannot('run job')) {
|
||||
this.transitionTo('jobs');
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
model() {
|
||||
return this.store.createRecord('job', {
|
||||
namespace: this.get('system.activeNamespace'),
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
resetController(controller, isExiting) {
|
||||
if (isExiting) {
|
||||
controller.model.deleteRecord();
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,26 +3,28 @@ import Route from '@ember/routing/route';
|
|||
import RSVP from 'rsvp';
|
||||
import WithForbiddenState from 'nomad-ui/mixins/with-forbidden-state';
|
||||
import notifyForbidden from 'nomad-ui/utils/notify-forbidden';
|
||||
import classic from 'ember-classic-decorator';
|
||||
|
||||
export default Route.extend(WithForbiddenState, {
|
||||
store: service(),
|
||||
system: service(),
|
||||
@classic
|
||||
export default class ServersRoute extends Route.extend(WithForbiddenState) {
|
||||
@service store;
|
||||
@service system;
|
||||
|
||||
breadcrumbs: Object.freeze([
|
||||
breadcrumbs = Object.freeze([
|
||||
{
|
||||
label: 'Servers',
|
||||
args: ['servers.index'],
|
||||
},
|
||||
]),
|
||||
]);
|
||||
|
||||
beforeModel() {
|
||||
return this.get('system.leader');
|
||||
},
|
||||
}
|
||||
|
||||
model() {
|
||||
return RSVP.hash({
|
||||
nodes: this.store.findAll('node'),
|
||||
agents: this.store.findAll('agent'),
|
||||
}).catch(notifyForbidden(this));
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import ApplicationSerializer from './application';
|
||||
import AdapterError from '@ember-data/adapter/error';
|
||||
|
||||
export default ApplicationSerializer.extend({
|
||||
attrs: {
|
||||
export default class AgentSerializer extends ApplicationSerializer {
|
||||
attrs = {
|
||||
datacenter: 'dc',
|
||||
address: 'Addr',
|
||||
serfPort: 'Port',
|
||||
},
|
||||
};
|
||||
|
||||
normalize(typeHash, hash) {
|
||||
if (!hash) {
|
||||
|
@ -24,14 +24,14 @@ export default ApplicationSerializer.extend({
|
|||
hash.Region = hash.Tags && hash.Tags.region;
|
||||
hash.RpcPort = hash.Tags && hash.Tags.port;
|
||||
|
||||
return this._super(typeHash, hash);
|
||||
},
|
||||
return super.normalize(typeHash, hash);
|
||||
}
|
||||
|
||||
normalizeResponse(store, typeClass, hash, ...args) {
|
||||
return this._super(store, typeClass, hash.Members || [], ...args);
|
||||
},
|
||||
return super.normalizeResponse(store, typeClass, hash.Members || [], ...args);
|
||||
}
|
||||
|
||||
normalizeSingleResponse(store, typeClass, hash, id, ...args) {
|
||||
return this._super(store, typeClass, hash.findBy('Name', id), id, ...args);
|
||||
},
|
||||
});
|
||||
return super.normalizeSingleResponse(store, typeClass, hash.findBy('Name', id), id, ...args);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,13 +8,13 @@ const taskGroupFromJob = (job, taskGroupName) => {
|
|||
return taskGroup ? taskGroup : null;
|
||||
};
|
||||
|
||||
export default ApplicationSerializer.extend({
|
||||
system: service(),
|
||||
export default class AllocationSerializer extends ApplicationSerializer {
|
||||
@service system;
|
||||
|
||||
attrs: {
|
||||
attrs = {
|
||||
taskGroupName: 'TaskGroup',
|
||||
states: 'TaskStates',
|
||||
},
|
||||
};
|
||||
|
||||
normalize(typeHash, hash) {
|
||||
// Transform the map-based TaskStates object into an array-based
|
||||
|
@ -63,6 +63,6 @@ export default ApplicationSerializer.extend({
|
|||
// The Job definition for an allocation is only included in findRecord responses.
|
||||
hash.AllocationTaskGroup = !hash.Job ? null : taskGroupFromJob(hash.Job, hash.TaskGroup);
|
||||
|
||||
return this._super(typeHash, hash);
|
||||
},
|
||||
});
|
||||
return super.normalize(typeHash, hash);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
import { get } from '@ember/object';
|
||||
import { assign } from '@ember/polyfills';
|
||||
import ApplicationSerializer from './application';
|
||||
import classic from 'ember-classic-decorator';
|
||||
|
||||
export default ApplicationSerializer.extend({
|
||||
attrs: {
|
||||
@classic
|
||||
export default class DeploymentSerializer extends ApplicationSerializer {
|
||||
attrs = {
|
||||
versionNumber: 'JobVersion',
|
||||
},
|
||||
};
|
||||
|
||||
normalize(typeHash, hash) {
|
||||
if (hash) {
|
||||
|
@ -29,8 +31,8 @@ export default ApplicationSerializer.extend({
|
|||
hash.JobID = hash.JobForLatestID = JSON.stringify([hash.JobID, hash.Namespace]);
|
||||
}
|
||||
|
||||
return this._super(typeHash, hash);
|
||||
},
|
||||
return super.normalize(typeHash, hash);
|
||||
}
|
||||
|
||||
extractRelationships(modelClass, hash) {
|
||||
const namespace = this.store.adapterFor(modelClass.modelName).get('namespace');
|
||||
|
@ -44,7 +46,7 @@ export default ApplicationSerializer.extend({
|
|||
},
|
||||
},
|
||||
},
|
||||
this._super(modelClass, hash)
|
||||
super.extractRelationships(modelClass, hash)
|
||||
);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import { assign } from '@ember/polyfills';
|
||||
import ApplicationSerializer from './application';
|
||||
|
||||
export default ApplicationSerializer.extend({
|
||||
attrs: {
|
||||
export default class JobVersionSerializer extends ApplicationSerializer {
|
||||
attrs = {
|
||||
number: 'Version',
|
||||
},
|
||||
};
|
||||
|
||||
normalizeFindHasManyResponse(store, modelClass, hash, id, requestType) {
|
||||
const zippedVersions = hash.Versions.map((version, index) =>
|
||||
|
@ -16,6 +16,13 @@ export default ApplicationSerializer.extend({
|
|||
SubmitTimeNanos: version.SubmitTime % 1000000,
|
||||
})
|
||||
);
|
||||
return this._super(store, modelClass, zippedVersions, hash, id, requestType);
|
||||
},
|
||||
});
|
||||
return super.normalizeFindHasManyResponse(
|
||||
store,
|
||||
modelClass,
|
||||
zippedVersions,
|
||||
hash,
|
||||
id,
|
||||
requestType
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,10 +2,10 @@ import { assign } from '@ember/polyfills';
|
|||
import ApplicationSerializer from './application';
|
||||
import queryString from 'query-string';
|
||||
|
||||
export default ApplicationSerializer.extend({
|
||||
attrs: {
|
||||
export default class JobSerializer extends ApplicationSerializer {
|
||||
attrs = {
|
||||
parameterized: 'ParameterizedJob',
|
||||
},
|
||||
};
|
||||
|
||||
normalize(typeHash, hash) {
|
||||
hash.NamespaceID = hash.Namespace;
|
||||
|
@ -45,8 +45,8 @@ export default ApplicationSerializer.extend({
|
|||
});
|
||||
}
|
||||
|
||||
return this._super(typeHash, hash);
|
||||
},
|
||||
return super.normalize(typeHash, hash);
|
||||
}
|
||||
|
||||
extractRelationships(modelClass, hash) {
|
||||
const namespace =
|
||||
|
@ -58,7 +58,7 @@ export default ApplicationSerializer.extend({
|
|||
.buildURL(modelName, hash.ID, hash, 'findRecord')
|
||||
.split('?');
|
||||
|
||||
return assign(this._super(...arguments), {
|
||||
return assign(super.extractRelationships(...arguments), {
|
||||
allocations: {
|
||||
links: {
|
||||
related: buildURL(`${jobURL}/allocations`, { namespace }),
|
||||
|
@ -85,8 +85,8 @@ export default ApplicationSerializer.extend({
|
|||
},
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function buildURL(path, queryParams) {
|
||||
const qpString = queryString.stringify(queryParams);
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import ApplicationSerializer from './application';
|
||||
import isIp from 'is-ip';
|
||||
|
||||
export default ApplicationSerializer.extend({
|
||||
attrs: {
|
||||
export default class NetworkSerializer extends ApplicationSerializer {
|
||||
attrs = {
|
||||
cidr: 'CIDR',
|
||||
ip: 'IP',
|
||||
mbits: 'MBits',
|
||||
},
|
||||
};
|
||||
|
||||
normalize(typeHash, hash) {
|
||||
const ip = hash.IP;
|
||||
|
@ -31,6 +31,6 @@ export default ApplicationSerializer.extend({
|
|||
|
||||
hash.Ports = reservedPorts.concat(dynamicPorts).sortBy('name');
|
||||
|
||||
return this._super(...arguments);
|
||||
},
|
||||
});
|
||||
return super.normalize(...arguments);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import ApplicationSerializer from './application';
|
||||
|
||||
export default ApplicationSerializer.extend({
|
||||
attrs: {
|
||||
export default class NodeEventSerializer extends ApplicationSerializer {
|
||||
attrs = {
|
||||
time: 'Timestamp',
|
||||
},
|
||||
});
|
||||
};
|
||||
}
|
||||
|
|
|
@ -2,13 +2,13 @@ import { assign } from '@ember/polyfills';
|
|||
import { inject as service } from '@ember/service';
|
||||
import ApplicationSerializer from './application';
|
||||
|
||||
export default ApplicationSerializer.extend({
|
||||
config: service(),
|
||||
export default class NodeSerializer extends ApplicationSerializer {
|
||||
@service config;
|
||||
|
||||
attrs: {
|
||||
attrs = {
|
||||
isDraining: 'Drain',
|
||||
httpAddr: 'HTTPAddr',
|
||||
},
|
||||
};
|
||||
|
||||
normalize(modelClass, hash) {
|
||||
// Transform map-based objects into array-based fragment lists
|
||||
|
@ -20,8 +20,8 @@ export default ApplicationSerializer.extend({
|
|||
const hostVolumes = hash.HostVolumes || {};
|
||||
hash.HostVolumes = Object.keys(hostVolumes).map(key => hostVolumes[key]);
|
||||
|
||||
return this._super(modelClass, hash);
|
||||
},
|
||||
return super.normalize(modelClass, hash);
|
||||
}
|
||||
|
||||
extractRelationships(modelClass, hash) {
|
||||
const { modelName } = modelClass;
|
||||
|
@ -36,5 +36,5 @@ export default ApplicationSerializer.extend({
|
|||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import ApplicationSerializer from './application';
|
||||
|
||||
export default ApplicationSerializer.extend({
|
||||
attrs: {
|
||||
export default class ResourcesSerializer extends ApplicationSerializer {
|
||||
attrs = {
|
||||
cpu: 'CPU',
|
||||
memory: 'MemoryMB',
|
||||
disk: 'DiskMB',
|
||||
iops: 'IOPS',
|
||||
},
|
||||
});
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
import ApplicationSerializer from './application';
|
||||
|
||||
export default ApplicationSerializer.extend({
|
||||
attrs: {
|
||||
export default class ServiceSerializer extends ApplicationSerializer {
|
||||
attrs = {
|
||||
connect: 'Connect',
|
||||
},
|
||||
};
|
||||
|
||||
normalize(typeHash, hash) {
|
||||
if (!hash.Tags) {
|
||||
hash.Tags = [];
|
||||
}
|
||||
|
||||
return this._super(typeHash, hash);
|
||||
},
|
||||
});
|
||||
return super.normalize(typeHash, hash);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import ApplicationSerializer from './application';
|
||||
|
||||
export default ApplicationSerializer.extend({
|
||||
attrs: {
|
||||
export default class TaskEventSerializer extends ApplicationSerializer {
|
||||
attrs = {
|
||||
message: 'DisplayMessage',
|
||||
},
|
||||
};
|
||||
|
||||
normalize(typeHash, hash) {
|
||||
// Time is in the form of nanoseconds since epoch, but JS dates
|
||||
|
@ -13,6 +13,6 @@ export default ApplicationSerializer.extend({
|
|||
hash.TimeNanos = hash.Time % 1000000;
|
||||
hash.Time = Math.floor(hash.Time / 1000000);
|
||||
|
||||
return this._super(typeHash, hash);
|
||||
},
|
||||
});
|
||||
return super.normalize(typeHash, hash);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
import { copy } from 'ember-copy';
|
||||
import ApplicationSerializer from './application';
|
||||
|
||||
export default ApplicationSerializer.extend({
|
||||
primaryKey: 'AccessorID',
|
||||
export default class TokenSerializer extends ApplicationSerializer {
|
||||
primaryKey = 'AccessorID';
|
||||
|
||||
attrs: {
|
||||
attrs = {
|
||||
secret: 'SecretID',
|
||||
},
|
||||
};
|
||||
|
||||
normalize(typeHash, hash) {
|
||||
hash.PolicyIDs = hash.Policies;
|
||||
hash.PolicyNames = copy(hash.Policies);
|
||||
return this._super(typeHash, hash);
|
||||
},
|
||||
});
|
||||
return super.normalize(typeHash, hash);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import { set, get } from '@ember/object';
|
||||
import ApplicationSerializer from './application';
|
||||
|
||||
export default ApplicationSerializer.extend({
|
||||
attrs: {
|
||||
export default class VolumeSerializer extends ApplicationSerializer {
|
||||
attrs = {
|
||||
externalId: 'ExternalID',
|
||||
},
|
||||
};
|
||||
|
||||
embeddedRelationships: Object.freeze(['writeAllocations', 'readAllocations']),
|
||||
embeddedRelationships = Object.freeze(['writeAllocations', 'readAllocations']);
|
||||
|
||||
// Volumes treat Allocations as embedded records. Ember has an
|
||||
// EmbeddedRecords mixin, but it assumes an application is using
|
||||
|
@ -35,15 +35,15 @@ export default ApplicationSerializer.extend({
|
|||
hash.ReadAllocations = Object.keys(readAllocs).map(bindIDToAlloc(readAllocs));
|
||||
hash.WriteAllocations = Object.keys(writeAllocs).map(bindIDToAlloc(writeAllocs));
|
||||
|
||||
const normalizedHash = this._super(typeHash, hash);
|
||||
const normalizedHash = super.normalize(typeHash, hash);
|
||||
return this.extractEmbeddedRecords(this, this.store, typeHash, normalizedHash);
|
||||
},
|
||||
}
|
||||
|
||||
keyForRelationship(attr, relationshipType) {
|
||||
//Embedded relationship attributes don't end in IDs
|
||||
if (this.embeddedRelationships.includes(attr)) return attr.capitalize();
|
||||
return this._super(attr, relationshipType);
|
||||
},
|
||||
return super.keyForRelationship(attr, relationshipType);
|
||||
}
|
||||
|
||||
// Convert the embedded relationship arrays into JSONAPI included records
|
||||
extractEmbeddedRecords(serializer, store, typeHash, partial) {
|
||||
|
@ -84,7 +84,7 @@ export default ApplicationSerializer.extend({
|
|||
});
|
||||
|
||||
return partial;
|
||||
},
|
||||
}
|
||||
|
||||
normalizeEmbeddedRelationship(store, relationshipMeta, relationshipHash) {
|
||||
const modelName = relationshipMeta.type;
|
||||
|
@ -92,5 +92,5 @@ export default ApplicationSerializer.extend({
|
|||
const serializer = store.serializerFor(modelName);
|
||||
|
||||
return serializer.normalize(modelClass, relationshipHash, null);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,19 +4,22 @@ import TextDecoder from 'nomad-ui/utils/classes/text-decoder';
|
|||
import { decode } from 'nomad-ui/utils/stream-frames';
|
||||
import AbstractLogger from './abstract-logger';
|
||||
import { fetchFailure } from './log';
|
||||
import classic from 'ember-classic-decorator';
|
||||
|
||||
export default EmberObject.extend(AbstractLogger, {
|
||||
reader: null,
|
||||
@classic
|
||||
export default class StreamLogger extends EmberObject.extend(AbstractLogger) {
|
||||
reader = null;
|
||||
|
||||
additionalParams: computed(function() {
|
||||
@computed()
|
||||
get additionalParams() {
|
||||
return {
|
||||
follow: true,
|
||||
};
|
||||
}),
|
||||
}
|
||||
|
||||
start() {
|
||||
return this.poll.perform();
|
||||
},
|
||||
}
|
||||
|
||||
stop() {
|
||||
const reader = this.reader;
|
||||
|
@ -24,9 +27,9 @@ export default EmberObject.extend(AbstractLogger, {
|
|||
reader.cancel();
|
||||
}
|
||||
return this.poll.cancelAll();
|
||||
},
|
||||
}
|
||||
|
||||
poll: task(function*() {
|
||||
@task(function*() {
|
||||
const url = this.fullUrl;
|
||||
const logFetch = this.logFetch;
|
||||
|
||||
|
@ -81,8 +84,11 @@ export default EmberObject.extend(AbstractLogger, {
|
|||
}
|
||||
});
|
||||
}
|
||||
}),
|
||||
}).reopenClass({
|
||||
})
|
||||
poll;
|
||||
}
|
||||
|
||||
StreamLogger.reopenClass({
|
||||
isSupported: !!window.ReadableStream && !isSafari(),
|
||||
});
|
||||
|
||||
|
|
|
@ -2,6 +2,6 @@ import AdapterError from '@ember-data/adapter/error';
|
|||
|
||||
export const NO_LEADER = 'No cluster leader';
|
||||
|
||||
export default AdapterError.extend({
|
||||
message: NO_LEADER,
|
||||
});
|
||||
export default class NoLeaderError extends AdapterError {
|
||||
message = NO_LEADER;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue