Merge pull request #5544 from hashicorp/f-ui-ember-v3
UI: Ember 2.18 → 3.4 Take two
This commit is contained in:
commit
d57aeeddd7
|
@ -87,6 +87,11 @@ rkt-*
|
|||
/ui/testem.log
|
||||
.ignore
|
||||
|
||||
# ember-try
|
||||
/ui/.node_modules.ember-try/
|
||||
/ui/bower.json.ember-try
|
||||
/ui/package.json.ember-try
|
||||
|
||||
# generated routes file
|
||||
command/agent/bindata_assetfs.go
|
||||
|
||||
|
|
|
@ -71,13 +71,14 @@ before_install:
|
|||
- if [[ "$TRAVIS_OS_NAME" == "osx" ]] && [[ -z "$SKIP_NOMAD_TESTS" ]]; then sudo -E bash ./scripts/travis-mac-priv.sh ; fi
|
||||
- if [[ "$TRAVIS_OS_NAME" == "linux" ]] && [[ -z "$SKIP_NOMAD_TESTS" ]]; then sudo -E bash ./scripts/travis-linux.sh ; fi
|
||||
- if [[ "$TRAVIS_OS_NAME" == "linux" ]] && [[ "$RUN_STATIC_CHECKS" ]]; then sudo -E bash ./scripts/vagrant-linux-priv-protoc.sh; fi
|
||||
- if [[ "$RUN_UI_TESTS" ]]; then curl -o- -L https://yarnpkg.com/install.sh | bash -s -- --version 1.0.1 ; fi
|
||||
- if [[ "$RUN_UI_TESTS" ]]; then curl -o- -L https://yarnpkg.com/install.sh | bash -s -- --version 1.15.2 ; fi
|
||||
- if [[ "$RUN_UI_TESTS" ]]; then export PATH="$HOME/.yarn/bin:$PATH" ; fi
|
||||
- echo "Travis Node Version" && node -v
|
||||
|
||||
install:
|
||||
- if [[ -z "$SKIP_NOMAD_TESTS" ]] || [[ "$RUN_STATIC_CHECKS" ]]; then make deps; fi
|
||||
- if [[ "$RUN_STATIC_CHECKS" ]]; then make lint-deps ; fi
|
||||
- if [[ "$RUN_UI_TESTS" ]]; then . $HOME/.nvm/nvm.sh && cd ui && nvm use && cd .. ; fi
|
||||
- if [[ "$RUN_UI_TESTS" ]]; then . $HOME/.nvm/nvm.sh && cd ui && nvm install && nvm use && cd .. ; fi
|
||||
|
||||
script:
|
||||
- sudo -E "PATH=$PATH" GOTESTSUM_JUNITFILE=/tmp/results.xml make travis
|
||||
|
|
|
@ -9,12 +9,12 @@ export NVM_DIR="/home/vagrant/.nvm"
|
|||
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" # This loads nvm
|
||||
|
||||
# Install Node, Ember CLI, and Phantom for UI development
|
||||
nvm install 8.11.2
|
||||
nvm alias default 8.11.2
|
||||
nvm install 10
|
||||
nvm alias default 10
|
||||
npm install -g ember-cli
|
||||
|
||||
# Install Yarn for front-end dependency management
|
||||
curl -o- -L https://yarnpkg.com/install.sh | bash -s -- --version 1.7.0
|
||||
curl -o- -L https://yarnpkg.com/install.sh | bash -s -- --version 1.15.2
|
||||
|
||||
# Install Chrome for running tests (in headless mode)
|
||||
wget -qO- - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add -
|
||||
|
|
|
@ -1 +1,22 @@
|
|||
mirage/
|
||||
|
||||
# unconventional js
|
||||
/blueprints/*/files/
|
||||
/vendor/
|
||||
|
||||
# compiled output
|
||||
/dist/
|
||||
/tmp/
|
||||
|
||||
# dependencies
|
||||
/bower_components/
|
||||
/node_modules/
|
||||
|
||||
# misc
|
||||
/coverage/
|
||||
!.*
|
||||
|
||||
# ember-try
|
||||
/.node_modules.ember-try/
|
||||
/bower.json.ember-try
|
||||
/package.json.ember-try
|
||||
|
|
|
@ -8,11 +8,8 @@ module.exports = {
|
|||
},
|
||||
extends: 'eslint:recommended',
|
||||
parserOptions: {
|
||||
ecmaVersion: 2017,
|
||||
ecmaVersion: 2018,
|
||||
sourceType: 'module',
|
||||
ecmaFeatures: {
|
||||
experimentalObjectRestSpread: true,
|
||||
},
|
||||
},
|
||||
rules: {
|
||||
indent: ['error', 2, { SwitchCase: 1 }],
|
||||
|
@ -26,4 +23,26 @@ module.exports = {
|
|||
},
|
||||
],
|
||||
},
|
||||
overrides: [
|
||||
// node files
|
||||
{
|
||||
files: [
|
||||
'.eslintrc.js',
|
||||
'.template-lintrc.js',
|
||||
'ember-cli-build.js',
|
||||
'testem.js',
|
||||
'blueprints/*/index.js',
|
||||
'config/**/*.js',
|
||||
'lib/*/index.js',
|
||||
],
|
||||
parserOptions: {
|
||||
sourceType: 'script',
|
||||
ecmaVersion: 2015,
|
||||
},
|
||||
env: {
|
||||
browser: false,
|
||||
node: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
'use strict';
|
||||
|
||||
module.exports = {
|
||||
extends: 'recommended',
|
||||
rules: {
|
||||
// should definitely move to template only
|
||||
// glimmer components for this one
|
||||
'no-partial': false,
|
||||
|
||||
// these need to be looked into, but
|
||||
// may be a bigger change
|
||||
'no-invalid-interactive': false,
|
||||
'simple-unless': false,
|
||||
|
||||
'self-closing-void-elements': false,
|
||||
'no-unnecessary-concat': false,
|
||||
'no-quoteless-attributes': false,
|
||||
'no-nested-interactive': false,
|
||||
|
||||
// Only used in list-pager, which can be replaced with
|
||||
// an angle-bracket component
|
||||
'no-attrs-in-components': false,
|
||||
|
||||
// Used in practice with charts. Ideally this would be true
|
||||
// except for a whitelist of chart files.
|
||||
'no-inline-styles': false,
|
||||
|
||||
// not sure we'll ever want these on,
|
||||
// would be nice but if prettier isn't doing
|
||||
// it for us, then not sure it's worth it
|
||||
'attribute-indentation': false,
|
||||
'block-indentation': false,
|
||||
quotes: false,
|
||||
},
|
||||
|
||||
ignore: [
|
||||
'app/templates/components/freestyle/**',
|
||||
'nomad-ui/templates/components/freestyle/**'
|
||||
]
|
||||
};
|
10
ui/README.md
10
ui/README.md
|
@ -49,6 +49,16 @@ Nomad UI tests can be run independently of Nomad golang tests.
|
|||
* `ember test` (single run, headless browser)
|
||||
* `ember test --server` (watches for changes, runs in a full browser)
|
||||
|
||||
|
||||
|
||||
### Linting
|
||||
|
||||
Linting should happen automatically in your editor and when committing changes, but it can also be invoked manually.
|
||||
|
||||
* `npm run lint:hbs`
|
||||
* `npm run lint:js`
|
||||
* `npm run lint:js -- --fix`
|
||||
|
||||
### Building
|
||||
|
||||
Typically `make release` or `make dev-ui` will be the desired build workflow, but in the event that build artifacts need to be inspected, `ember build` will output compiled files in `ui/dist`.
|
||||
|
|
|
@ -78,7 +78,7 @@ export default Watchable.extend({
|
|||
|
||||
plan(job) {
|
||||
const jobId = job.get('id');
|
||||
const store = this.get('store');
|
||||
const store = this.store;
|
||||
const url = addToPath(this.urlForFindRecord(jobId, 'job'), '/plan');
|
||||
|
||||
return this.ajax(url, 'POST', {
|
||||
|
|
|
@ -8,7 +8,7 @@ export default ApplicationAdapter.extend({
|
|||
|
||||
findSelf() {
|
||||
return this.ajax(`${this.buildURL()}/token/self`, 'GET').then(token => {
|
||||
const store = this.get('store');
|
||||
const store = this.store;
|
||||
store.pushPayload('token', {
|
||||
tokens: [token],
|
||||
});
|
||||
|
|
|
@ -42,9 +42,9 @@ export default ApplicationAdapter.extend({
|
|||
if (previousBeforeSend) {
|
||||
previousBeforeSend(...arguments);
|
||||
}
|
||||
this.get('xhrs').track(key, jqXHR);
|
||||
this.xhrs.track(key, jqXHR);
|
||||
jqXHR.always(() => {
|
||||
this.get('xhrs').remove(key, jqXHR);
|
||||
this.xhrs.remove(key, jqXHR);
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -60,7 +60,7 @@ export default ApplicationAdapter.extend({
|
|||
const url = this.urlForFindAll(type.modelName);
|
||||
|
||||
if (get(snapshotRecordArray || {}, 'adapterOptions.watch')) {
|
||||
params.index = this.get('watchList').getIndexFor(url);
|
||||
params.index = this.watchList.getIndexFor(url);
|
||||
}
|
||||
|
||||
return this.ajax(url, 'GET', {
|
||||
|
@ -73,7 +73,7 @@ export default ApplicationAdapter.extend({
|
|||
params = assign(queryString.parse(params) || {}, this.buildQuery(), additionalParams);
|
||||
|
||||
if (get(snapshot || {}, 'adapterOptions.watch')) {
|
||||
params.index = this.get('watchList').getIndexFor(url);
|
||||
params.index = this.watchList.getIndexFor(url);
|
||||
}
|
||||
|
||||
return this.ajax(url, 'GET', {
|
||||
|
@ -97,7 +97,7 @@ export default ApplicationAdapter.extend({
|
|||
let params = {};
|
||||
|
||||
if (watch) {
|
||||
params.index = this.get('watchList').getIndexFor(url);
|
||||
params.index = this.watchList.getIndexFor(url);
|
||||
}
|
||||
|
||||
// Avoid duplicating existing query params by passing them to ajax
|
||||
|
@ -113,7 +113,7 @@ export default ApplicationAdapter.extend({
|
|||
data: params,
|
||||
}).then(
|
||||
json => {
|
||||
const store = this.get('store');
|
||||
const store = this.store;
|
||||
const normalizeMethod =
|
||||
relationship.kind === 'belongsTo'
|
||||
? 'normalizeFindBelongsToResponse'
|
||||
|
@ -138,7 +138,7 @@ export default ApplicationAdapter.extend({
|
|||
// case sensitive.
|
||||
const newIndex = headers['x-nomad-index'] || headers['X-Nomad-Index'];
|
||||
if (newIndex) {
|
||||
this.get('watchList').setIndexFor(requestData.url, newIndex);
|
||||
this.watchList.setIndexFor(requestData.url, newIndex);
|
||||
}
|
||||
|
||||
return this._super(...arguments);
|
||||
|
@ -149,7 +149,7 @@ export default ApplicationAdapter.extend({
|
|||
return;
|
||||
}
|
||||
const url = this.urlForFindRecord(id, modelName);
|
||||
this.get('xhrs').cancel(`GET ${url}`);
|
||||
this.xhrs.cancel(`GET ${url}`);
|
||||
},
|
||||
|
||||
cancelFindAll(modelName) {
|
||||
|
@ -161,7 +161,7 @@ export default ApplicationAdapter.extend({
|
|||
if (params) {
|
||||
url = `${url}?${params}`;
|
||||
}
|
||||
this.get('xhrs').cancel(`GET ${url}`);
|
||||
this.xhrs.cancel(`GET ${url}`);
|
||||
},
|
||||
|
||||
cancelReloadRelationship(model, relationshipName) {
|
||||
|
@ -175,7 +175,7 @@ export default ApplicationAdapter.extend({
|
|||
);
|
||||
} else {
|
||||
const url = model[relationship.kind](relationship.key).link();
|
||||
this.get('xhrs').cancel(`GET ${url}`);
|
||||
this.xhrs.cancel(`GET ${url}`);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
|
@ -30,8 +30,8 @@ export default Component.extend({
|
|||
if (!this.get('allocation.isRunning')) return;
|
||||
|
||||
return AllocationStatsTracker.create({
|
||||
fetch: url => this.get('token').authorizedRequest(url),
|
||||
allocation: this.get('allocation'),
|
||||
fetch: url => this.token.authorizedRequest(url),
|
||||
allocation: this.allocation,
|
||||
});
|
||||
}),
|
||||
|
||||
|
@ -41,22 +41,22 @@ export default Component.extend({
|
|||
onClick() {},
|
||||
|
||||
click(event) {
|
||||
lazyClick([this.get('onClick'), event]);
|
||||
lazyClick([this.onClick, event]);
|
||||
},
|
||||
|
||||
didReceiveAttrs() {
|
||||
const allocation = this.get('allocation');
|
||||
const allocation = this.allocation;
|
||||
|
||||
if (allocation) {
|
||||
run.scheduleOnce('afterRender', this, qualifyAllocation);
|
||||
} else {
|
||||
this.get('fetchStats').cancelAll();
|
||||
this.fetchStats.cancelAll();
|
||||
}
|
||||
},
|
||||
|
||||
fetchStats: task(function*() {
|
||||
do {
|
||||
if (this.get('stats')) {
|
||||
if (this.stats) {
|
||||
try {
|
||||
yield this.get('stats.poll').perform();
|
||||
this.set('statsError', false);
|
||||
|
@ -66,14 +66,14 @@ export default Component.extend({
|
|||
}
|
||||
|
||||
yield timeout(500);
|
||||
} while (this.get('enablePolling'));
|
||||
} while (this.enablePolling);
|
||||
}).drop(),
|
||||
});
|
||||
|
||||
function qualifyAllocation() {
|
||||
const allocation = this.get('allocation');
|
||||
const allocation = this.allocation;
|
||||
return allocation.reload().then(() => {
|
||||
this.get('fetchStats').perform();
|
||||
this.fetchStats.perform();
|
||||
|
||||
// Make sure that the job record in the store for this allocation
|
||||
// is complete and not a partial from the list endpoint
|
||||
|
|
|
@ -11,11 +11,11 @@ export default DistributionBar.extend({
|
|||
data: computed(
|
||||
'allocationContainer.{queuedAllocs,completeAllocs,failedAllocs,runningAllocs,startingAllocs}',
|
||||
function() {
|
||||
if (!this.get('allocationContainer')) {
|
||||
if (!this.allocationContainer) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const allocs = this.get('allocationContainer').getProperties(
|
||||
const allocs = this.allocationContainer.getProperties(
|
||||
'queuedAllocs',
|
||||
'completeAllocs',
|
||||
'failedAllocs',
|
||||
|
|
|
@ -9,11 +9,11 @@ export default DistributionBar.extend({
|
|||
'data-test-children-status-bar': true,
|
||||
|
||||
data: computed('job.{pendingChildren,runningChildren,deadChildren}', function() {
|
||||
if (!this.get('job')) {
|
||||
if (!this.job) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const children = this.get('job').getProperties(
|
||||
const children = this.job.getProperties(
|
||||
'pendingChildren',
|
||||
'runningChildren',
|
||||
'deadChildren'
|
||||
|
|
|
@ -15,32 +15,32 @@ export default Component.extend(WithVisibilityDetection, {
|
|||
onClick() {},
|
||||
|
||||
click(event) {
|
||||
lazyClick([this.get('onClick'), event]);
|
||||
lazyClick([this.onClick, event]);
|
||||
},
|
||||
|
||||
didReceiveAttrs() {
|
||||
// Reload the node in order to get detail information
|
||||
const node = this.get('node');
|
||||
const node = this.node;
|
||||
if (node) {
|
||||
node.reload().then(() => {
|
||||
this.get('watch').perform(node, 100);
|
||||
this.watch.perform(node, 100);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
visibilityHandler() {
|
||||
if (document.hidden) {
|
||||
this.get('watch').cancelAll();
|
||||
this.watch.cancelAll();
|
||||
} else {
|
||||
const node = this.get('node');
|
||||
const node = this.node;
|
||||
if (node) {
|
||||
this.get('watch').perform(node, 100);
|
||||
this.watch.perform(node, 100);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
willDestroy() {
|
||||
this.get('watch').cancelAll();
|
||||
this.watch.cancelAll();
|
||||
this._super(...arguments);
|
||||
},
|
||||
|
||||
|
|
|
@ -2,7 +2,8 @@ import Component from '@ember/component';
|
|||
import { computed, observer, set } from '@ember/object';
|
||||
import { run } from '@ember/runloop';
|
||||
import { assign } from '@ember/polyfills';
|
||||
import { guidFor, copy } from '@ember/object/internals';
|
||||
import { guidFor } from '@ember/object/internals';
|
||||
import { copy } from 'ember-copy';
|
||||
import d3 from 'd3-selection';
|
||||
import 'd3-transition';
|
||||
import WindowResizable from '../mixins/window-resizable';
|
||||
|
@ -23,7 +24,7 @@ export default Component.extend(WindowResizable, {
|
|||
maskId: null,
|
||||
|
||||
_data: computed('data', function() {
|
||||
const data = copy(this.get('data'), true);
|
||||
const data = copy(this.data, true);
|
||||
const sum = data.mapBy('value').reduce(sumAggregate, 0);
|
||||
|
||||
return data.map(({ label, value, className, layers }, index) => ({
|
||||
|
@ -73,7 +74,7 @@ export default Component.extend(WindowResizable, {
|
|||
// prettier-ignore
|
||||
/* eslint-disable */
|
||||
renderChart() {
|
||||
const { chart, _data, isNarrow } = this.getProperties('chart', '_data', 'isNarrow');
|
||||
const { chart, _data, isNarrow } = this;
|
||||
const width = this.$('svg').width();
|
||||
const filteredData = _data.filter(d => d.value > 0);
|
||||
filteredData.forEach((d, index) => {
|
||||
|
@ -89,7 +90,7 @@ export default Component.extend(WindowResizable, {
|
|||
.append('g')
|
||||
.on('mouseenter', d => {
|
||||
run(() => {
|
||||
const slices = this.get('slices');
|
||||
const slices = this.slices;
|
||||
const slice = slices.filter(datum => datum.label === d.label);
|
||||
slices.classed('active', false).classed('inactive', true);
|
||||
slice.classed('active', true).classed('inactive', false);
|
||||
|
@ -109,7 +110,7 @@ export default Component.extend(WindowResizable, {
|
|||
slices = slices.merge(slicesEnter);
|
||||
slices.attr('class', d => {
|
||||
const className = d.className || `slice-${_data.indexOf(d)}`
|
||||
const activeDatum = this.get('activeDatum');
|
||||
const activeDatum = this.activeDatum;
|
||||
const isActive = activeDatum && activeDatum.label === d.label;
|
||||
const isInactive = activeDatum && activeDatum.label !== d.label;
|
||||
return [ className, isActive && 'active', isInactive && 'inactive' ].compact().join(' ');
|
||||
|
@ -148,7 +149,7 @@ export default Component.extend(WindowResizable, {
|
|||
.attr('width', setWidth)
|
||||
.attr('x', setOffset)
|
||||
.attr('y', () => isNarrow ? '50%' : 0)
|
||||
.attr('clip-path', `url(#${this.get('maskId')})`)
|
||||
.attr('clip-path', `url(#${this.maskId})`)
|
||||
.attr('height', () => isNarrow ? '6px' : '100%')
|
||||
.attr('transform', () => isNarrow ? 'translate(0, -3)' : '')
|
||||
.merge(layers)
|
||||
|
@ -159,7 +160,7 @@ export default Component.extend(WindowResizable, {
|
|||
.attr('x', setOffset)
|
||||
|
||||
if (isNarrow) {
|
||||
d3.select(this.get('element')).select('.mask')
|
||||
d3.select(this.element).select('.mask')
|
||||
.attr('height', '6px')
|
||||
.attr('y', '50%');
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ export default Component.extend({
|
|||
}.on('init'),
|
||||
|
||||
willDestroy() {
|
||||
clearInterval(this.get('timer'));
|
||||
clearInterval(this.timer);
|
||||
},
|
||||
|
||||
distributionBarDatum: computed(() => {
|
||||
|
|
|
@ -11,7 +11,7 @@ export default Component.extend({
|
|||
setInterval(() => {
|
||||
this.incrementProperty('timerTicks');
|
||||
|
||||
const ref = this.get('lineChartLive');
|
||||
const ref = this.lineChartLive;
|
||||
ref.addObject({ ts: Date.now(), val: Math.random() * 30 + 20 });
|
||||
if (ref.length > 60) {
|
||||
ref.splice(0, ref.length - 60);
|
||||
|
@ -21,7 +21,7 @@ export default Component.extend({
|
|||
}.on('init'),
|
||||
|
||||
willDestroy() {
|
||||
clearInterval(this.get('timer'));
|
||||
clearInterval(this.timer);
|
||||
},
|
||||
|
||||
lineChartData: computed(() => {
|
||||
|
|
|
@ -14,7 +14,7 @@ export default Component.extend({
|
|||
}.on('init'),
|
||||
|
||||
willDestroy() {
|
||||
clearInterval(this.get('timer'));
|
||||
clearInterval(this.timer);
|
||||
},
|
||||
|
||||
denominator: computed('timerTicks', function() {
|
||||
|
@ -26,7 +26,7 @@ export default Component.extend({
|
|||
}),
|
||||
|
||||
numerator: computed('denominator', 'percentage', function() {
|
||||
return Math.round(this.get('denominator') * this.get('percentage') * 100) / 100;
|
||||
return Math.round(this.denominator * this.percentage * 100) / 100;
|
||||
}),
|
||||
|
||||
liveDetails: computed('denominator', 'numerator', 'percentage', function() {
|
||||
|
|
|
@ -10,14 +10,14 @@ export default Component.extend({
|
|||
this.set(
|
||||
'timer',
|
||||
setInterval(() => {
|
||||
const metricsHigh = this.get('metricsHigh');
|
||||
const metricsHigh = this.metricsHigh;
|
||||
const prev = metricsHigh.length ? metricsHigh[metricsHigh.length - 1].value : 0.9;
|
||||
this.appendTSValue(
|
||||
metricsHigh,
|
||||
Math.min(Math.max(prev + Math.random() * 0.05 - 0.025, 0.5), 1)
|
||||
);
|
||||
|
||||
const metricsLow = this.get('metricsLow');
|
||||
const metricsLow = this.metricsLow;
|
||||
const prev2 = metricsLow.length ? metricsLow[metricsLow.length - 1].value : 0.1;
|
||||
this.appendTSValue(
|
||||
metricsLow,
|
||||
|
@ -39,7 +39,7 @@ export default Component.extend({
|
|||
},
|
||||
|
||||
willDestroy() {
|
||||
clearInterval(this.get('timer'));
|
||||
clearInterval(this.timer);
|
||||
},
|
||||
|
||||
metricsHigh: computed(() => {
|
||||
|
|
|
@ -107,12 +107,12 @@ export default Component.extend({
|
|||
],
|
||||
|
||||
filteredShortList: computed('searchTerm', 'shortList.[]', function() {
|
||||
const term = this.get('searchTerm').toLowerCase();
|
||||
return this.get('shortList').filter(product => product.name.toLowerCase().includes(term));
|
||||
const term = this.searchTerm.toLowerCase();
|
||||
return this.shortList.filter(product => product.name.toLowerCase().includes(term));
|
||||
}),
|
||||
|
||||
sortedShortList: computed('shortList.[]', 'sortProperty', 'sortDescending', function() {
|
||||
const sorted = this.get('shortList').sortBy(this.get('sortProperty'));
|
||||
return this.get('sortDescending') ? sorted.reverse() : sorted;
|
||||
const sorted = this.shortList.sortBy(this.sortProperty);
|
||||
return this.sortDescending ? sorted.reverse() : sorted;
|
||||
}),
|
||||
});
|
||||
|
|
|
@ -37,7 +37,7 @@ export default Component.extend({
|
|||
gotoJobsForNamespace(namespace) {
|
||||
if (!namespace || !namespace.get('id')) return;
|
||||
|
||||
this.get('router').transitionTo('jobs', {
|
||||
this.router.transitionTo('jobs', {
|
||||
queryParams: { namespace: namespace.get('id') },
|
||||
});
|
||||
},
|
||||
|
|
|
@ -9,13 +9,13 @@ export default Component.extend({
|
|||
deployments: computed(() => []),
|
||||
|
||||
sortedDeployments: computed('deployments.@each.versionSubmitTime', function() {
|
||||
return this.get('deployments')
|
||||
return this.deployments
|
||||
.sortBy('versionSubmitTime')
|
||||
.reverse();
|
||||
}),
|
||||
|
||||
annotatedDeployments: computed('sortedDeployments.@each.version', function() {
|
||||
const deployments = this.get('sortedDeployments');
|
||||
const deployments = this.sortedDeployments;
|
||||
return deployments.map((deployment, index) => {
|
||||
const meta = {};
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ export default Component.extend({
|
|||
onSubmit() {},
|
||||
context: computed({
|
||||
get() {
|
||||
return this.get('_context');
|
||||
return this._context;
|
||||
},
|
||||
set(key, value) {
|
||||
const allowedValues = ['new', 'edit'];
|
||||
|
@ -39,14 +39,14 @@ export default Component.extend({
|
|||
showEditorMessage: localStorageProperty('nomadMessageJobEditor', true),
|
||||
|
||||
stage: computed('planOutput', function() {
|
||||
return this.get('planOutput') ? 'plan' : 'editor';
|
||||
return this.planOutput ? 'plan' : 'editor';
|
||||
}),
|
||||
|
||||
plan: task(function*() {
|
||||
this.reset();
|
||||
|
||||
try {
|
||||
yield this.get('job').parse();
|
||||
yield this.job.parse();
|
||||
} catch (err) {
|
||||
const error = messageFromAdapterError(err) || 'Could not parse input';
|
||||
this.set('parseError', error);
|
||||
|
@ -55,7 +55,7 @@ export default Component.extend({
|
|||
}
|
||||
|
||||
try {
|
||||
const plan = yield this.get('job').plan();
|
||||
const plan = yield this.job.plan();
|
||||
this.set('planOutput', plan);
|
||||
} catch (err) {
|
||||
const error = messageFromAdapterError(err) || 'Could not plan job';
|
||||
|
@ -66,10 +66,10 @@ export default Component.extend({
|
|||
|
||||
submit: task(function*() {
|
||||
try {
|
||||
if (this.get('context') === 'new') {
|
||||
yield this.get('job').run();
|
||||
if (this.context === 'new') {
|
||||
yield this.job.run();
|
||||
} else {
|
||||
yield this.get('job').update();
|
||||
yield this.job.update();
|
||||
}
|
||||
|
||||
const id = this.get('job.plainId');
|
||||
|
@ -78,7 +78,7 @@ export default Component.extend({
|
|||
this.reset();
|
||||
|
||||
// Treat the job as ephemeral and only provide ID parts.
|
||||
this.get('onSubmit')(id, namespace);
|
||||
this.onSubmit(id, namespace);
|
||||
} catch (err) {
|
||||
const error = messageFromAdapterError(err) || 'Could not submit job';
|
||||
this.set('runError', error);
|
||||
|
|
|
@ -7,7 +7,7 @@ export default PeriodicChildJobPage.extend({
|
|||
payloadJSON: computed('payload', function() {
|
||||
let json;
|
||||
try {
|
||||
json = JSON.parse(this.get('payload'));
|
||||
json = JSON.parse(this.payload);
|
||||
} catch (e) {
|
||||
// Swallow error and fall back to plain text rendering
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ export default Component.extend({
|
|||
if (!message || message === 'Forbidden') {
|
||||
message = 'Your ACL token does not grant permission to promote deployments.';
|
||||
}
|
||||
this.get('handleError')({
|
||||
this.handleError({
|
||||
title: 'Could Not Promote Deployment',
|
||||
description: message,
|
||||
});
|
||||
|
|
|
@ -12,12 +12,12 @@ export default Component.extend({
|
|||
|
||||
stopJob: task(function*() {
|
||||
try {
|
||||
const job = this.get('job');
|
||||
const job = this.job;
|
||||
yield job.stop();
|
||||
// Eagerly update the job status to avoid flickering
|
||||
this.job.set('status', 'dead');
|
||||
} catch (err) {
|
||||
this.get('handleError')({
|
||||
this.handleError({
|
||||
title: 'Could Not Stop Job',
|
||||
description: 'Your ACL token does not grant permission to stop jobs.',
|
||||
});
|
||||
|
@ -25,7 +25,7 @@ export default Component.extend({
|
|||
}),
|
||||
|
||||
startJob: task(function*() {
|
||||
const job = this.get('job');
|
||||
const job = this.job;
|
||||
const definition = yield job.fetchRawDefinition();
|
||||
|
||||
delete definition.Stop;
|
||||
|
@ -42,7 +42,7 @@ export default Component.extend({
|
|||
message = 'Your ACL token does not grant permission to stop jobs.';
|
||||
}
|
||||
|
||||
this.get('handleError')({
|
||||
this.handleError({
|
||||
title: 'Could Not Start Job',
|
||||
description: message,
|
||||
});
|
||||
|
|
|
@ -3,7 +3,7 @@ import { computed } from '@ember/object';
|
|||
|
||||
export default AbstractJobPage.extend({
|
||||
breadcrumbs: computed('job.{name,id}', 'job.parent.{name,id}', function() {
|
||||
const job = this.get('job');
|
||||
const job = this.job;
|
||||
const parent = this.get('job.parent');
|
||||
|
||||
return [
|
||||
|
|
|
@ -8,7 +8,7 @@ export default AbstractJobPage.extend({
|
|||
|
||||
actions: {
|
||||
forceLaunch() {
|
||||
this.get('job')
|
||||
this.job
|
||||
.forcePeriodic()
|
||||
.catch(() => {
|
||||
this.set('errorMessage', {
|
||||
|
|
|
@ -13,6 +13,6 @@ export default Component.extend({
|
|||
onClick() {},
|
||||
|
||||
click(event) {
|
||||
lazyClick([this.get('onClick'), event]);
|
||||
lazyClick([this.onClick, event]);
|
||||
},
|
||||
});
|
||||
|
|
|
@ -12,7 +12,7 @@ export default Component.extend({
|
|||
verbose: true,
|
||||
|
||||
annotatedVersions: computed('versions.[]', function() {
|
||||
const versions = this.get('versions')
|
||||
const versions = this.versions
|
||||
.sortBy('submitTime')
|
||||
.reverse();
|
||||
return versions.map((version, index) => {
|
||||
|
|
|
@ -6,6 +6,6 @@ export default Component.extend({
|
|||
|
||||
json: null,
|
||||
jsonStr: computed('json', function() {
|
||||
return JSON.stringify(this.get('json'), null, 2);
|
||||
return JSON.stringify(this.json, null, 2);
|
||||
}),
|
||||
});
|
||||
|
|
|
@ -58,20 +58,20 @@ export default Component.extend(WindowResizable, {
|
|||
activeDatum: null,
|
||||
|
||||
activeDatumLabel: computed('activeDatum', function() {
|
||||
const datum = this.get('activeDatum');
|
||||
const datum = this.activeDatum;
|
||||
|
||||
if (!datum) return;
|
||||
|
||||
const x = datum[this.get('xProp')];
|
||||
return this.xFormat(this.get('timeseries'))(x);
|
||||
const x = datum[this.xProp];
|
||||
return this.xFormat(this.timeseries)(x);
|
||||
}),
|
||||
|
||||
activeDatumValue: computed('activeDatum', function() {
|
||||
const datum = this.get('activeDatum');
|
||||
const datum = this.activeDatum;
|
||||
|
||||
if (!datum) return;
|
||||
|
||||
const y = datum[this.get('yProp')];
|
||||
const y = datum[this.yProp];
|
||||
return this.yFormat()(y);
|
||||
}),
|
||||
|
||||
|
@ -88,19 +88,19 @@ export default Component.extend(WindowResizable, {
|
|||
tooltipStyle: styleStringProperty('tooltipPosition'),
|
||||
|
||||
xScale: computed('data.[]', 'xProp', 'timeseries', 'yAxisOffset', function() {
|
||||
const xProp = this.get('xProp');
|
||||
const scale = this.get('timeseries') ? d3Scale.scaleTime() : d3Scale.scaleLinear();
|
||||
const data = this.get('data');
|
||||
const xProp = this.xProp;
|
||||
const scale = this.timeseries ? d3Scale.scaleTime() : d3Scale.scaleLinear();
|
||||
const data = this.data;
|
||||
|
||||
const domain = data.length ? d3Array.extent(this.get('data'), d => d[xProp]) : [0, 1];
|
||||
const domain = data.length ? d3Array.extent(this.data, d => d[xProp]) : [0, 1];
|
||||
|
||||
scale.rangeRound([10, this.get('yAxisOffset')]).domain(domain);
|
||||
scale.rangeRound([10, this.yAxisOffset]).domain(domain);
|
||||
|
||||
return scale;
|
||||
}),
|
||||
|
||||
xRange: computed('data.[]', 'xFormat', 'xProp', 'timeseries', function() {
|
||||
const { xProp, timeseries, data } = this.getProperties('xProp', 'timeseries', 'data');
|
||||
const { xProp, timeseries, data } = this;
|
||||
const range = d3Array.extent(data, d => d[xProp]);
|
||||
const formatter = this.xFormat(timeseries);
|
||||
|
||||
|
@ -108,40 +108,40 @@ export default Component.extend(WindowResizable, {
|
|||
}),
|
||||
|
||||
yRange: computed('data.[]', 'yFormat', 'yProp', function() {
|
||||
const yProp = this.get('yProp');
|
||||
const range = d3Array.extent(this.get('data'), d => d[yProp]);
|
||||
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() {
|
||||
const yProp = this.get('yProp');
|
||||
let max = d3Array.max(this.get('data'), d => d[yProp]) || 1;
|
||||
const yProp = this.yProp;
|
||||
let max = d3Array.max(this.data, d => d[yProp]) || 1;
|
||||
if (max > 1) {
|
||||
max = nice(max);
|
||||
}
|
||||
|
||||
return d3Scale
|
||||
.scaleLinear()
|
||||
.rangeRound([this.get('xAxisOffset'), 10])
|
||||
.rangeRound([this.xAxisOffset, 10])
|
||||
.domain([0, max]);
|
||||
}),
|
||||
|
||||
xAxis: computed('xScale', function() {
|
||||
const formatter = this.xFormat(this.get('timeseries'));
|
||||
const formatter = this.xFormat(this.timeseries);
|
||||
|
||||
return d3Axis
|
||||
.axisBottom()
|
||||
.scale(this.get('xScale'))
|
||||
.scale(this.xScale)
|
||||
.ticks(5)
|
||||
.tickFormat(formatter);
|
||||
}),
|
||||
|
||||
yTicks: computed('xAxisOffset', function() {
|
||||
const height = this.get('xAxisOffset');
|
||||
const height = this.xAxisOffset;
|
||||
const tickCount = Math.ceil(height / 120) * 2 + 1;
|
||||
const domain = this.get('yScale').domain();
|
||||
const domain = this.yScale.domain();
|
||||
const ticks = lerp(domain, tickCount);
|
||||
return domain[1] - domain[0] > 1 ? nice(ticks) : ticks;
|
||||
}),
|
||||
|
@ -151,20 +151,20 @@ export default Component.extend(WindowResizable, {
|
|||
|
||||
return d3Axis
|
||||
.axisRight()
|
||||
.scale(this.get('yScale'))
|
||||
.tickValues(this.get('yTicks'))
|
||||
.scale(this.yScale)
|
||||
.tickValues(this.yTicks)
|
||||
.tickFormat(formatter);
|
||||
}),
|
||||
|
||||
yGridlines: computed('yScale', function() {
|
||||
// The first gridline overlaps the x-axis, so remove it
|
||||
const [, ...ticks] = this.get('yTicks');
|
||||
const [, ...ticks] = this.yTicks;
|
||||
|
||||
return d3Axis
|
||||
.axisRight()
|
||||
.scale(this.get('yScale'))
|
||||
.scale(this.yScale)
|
||||
.tickValues(ticks)
|
||||
.tickSize(-this.get('yAxisOffset'))
|
||||
.tickSize(-this.yAxisOffset)
|
||||
.tickFormat('');
|
||||
}),
|
||||
|
||||
|
@ -185,20 +185,15 @@ export default Component.extend(WindowResizable, {
|
|||
}),
|
||||
|
||||
xAxisOffset: computed('height', 'xAxisHeight', function() {
|
||||
return this.get('height') - this.get('xAxisHeight');
|
||||
return this.height - this.xAxisHeight;
|
||||
}),
|
||||
|
||||
yAxisOffset: computed('width', 'yAxisWidth', function() {
|
||||
return this.get('width') - this.get('yAxisWidth');
|
||||
return this.width - this.yAxisWidth;
|
||||
}),
|
||||
|
||||
line: computed('data.[]', 'xScale', 'yScale', function() {
|
||||
const { xScale, yScale, xProp, yProp } = this.getProperties(
|
||||
'xScale',
|
||||
'yScale',
|
||||
'xProp',
|
||||
'yProp'
|
||||
);
|
||||
const { xScale, yScale, xProp, yProp } = this;
|
||||
|
||||
const line = d3Shape
|
||||
.line()
|
||||
|
@ -206,16 +201,11 @@ export default Component.extend(WindowResizable, {
|
|||
.x(d => xScale(d[xProp]))
|
||||
.y(d => yScale(d[yProp]));
|
||||
|
||||
return line(this.get('data'));
|
||||
return line(this.data);
|
||||
}),
|
||||
|
||||
area: computed('data.[]', 'xScale', 'yScale', function() {
|
||||
const { xScale, yScale, xProp, yProp } = this.getProperties(
|
||||
'xScale',
|
||||
'yScale',
|
||||
'xProp',
|
||||
'yProp'
|
||||
);
|
||||
const { xScale, yScale, xProp, yProp } = this;
|
||||
|
||||
const area = d3Shape
|
||||
.area()
|
||||
|
@ -224,7 +214,7 @@ export default Component.extend(WindowResizable, {
|
|||
.y0(yScale(0))
|
||||
.y1(d => yScale(d[yProp]));
|
||||
|
||||
return area(this.get('data'));
|
||||
return area(this.data);
|
||||
}),
|
||||
|
||||
didInsertElement() {
|
||||
|
@ -258,13 +248,7 @@ export default Component.extend(WindowResizable, {
|
|||
},
|
||||
|
||||
updateActiveDatum(mouseX) {
|
||||
const { xScale, xProp, yScale, yProp, data } = this.getProperties(
|
||||
'xScale',
|
||||
'xProp',
|
||||
'yScale',
|
||||
'yProp',
|
||||
'data'
|
||||
);
|
||||
const { xScale, xProp, yScale, yProp, data } = this;
|
||||
|
||||
if (!data || !data.length) return;
|
||||
|
||||
|
@ -318,17 +302,17 @@ export default Component.extend(WindowResizable, {
|
|||
// axis, the axes themselves are recomputed and need to
|
||||
// be re-rendered.
|
||||
this.mountD3Elements();
|
||||
if (this.get('isActive')) {
|
||||
this.updateActiveDatum(this.get('latestMouseX'));
|
||||
if (this.isActive) {
|
||||
this.updateActiveDatum(this.latestMouseX);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
mountD3Elements() {
|
||||
if (!this.get('isDestroyed') && !this.get('isDestroying')) {
|
||||
d3.select(this.element.querySelector('.x-axis')).call(this.get('xAxis'));
|
||||
d3.select(this.element.querySelector('.y-axis')).call(this.get('yAxis'));
|
||||
d3.select(this.element.querySelector('.y-gridlines')).call(this.get('yGridlines'));
|
||||
if (!this.isDestroyed && !this.isDestroying) {
|
||||
d3.select(this.element.querySelector('.x-axis')).call(this.xAxis);
|
||||
d3.select(this.element.querySelector('.y-axis')).call(this.yAxis);
|
||||
d3.select(this.element.querySelector('.y-gridlines')).call(this.yGridlines);
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -11,12 +11,12 @@ export default Component.extend({
|
|||
startExpanded: false,
|
||||
|
||||
decoratedSource: computed('source.[]', function() {
|
||||
const stateCache = this.get('stateCache');
|
||||
const key = this.get('key');
|
||||
const stateCache = this.stateCache;
|
||||
const key = this.key;
|
||||
const deepKey = `item.${key}`;
|
||||
const startExpanded = this.get('startExpanded');
|
||||
const startExpanded = this.startExpanded;
|
||||
|
||||
const decoratedSource = this.get('source').map(item => {
|
||||
const decoratedSource = this.source.map(item => {
|
||||
const cacheItem = stateCache.findBy(deepKey, get(item, key));
|
||||
return {
|
||||
item,
|
||||
|
|
|
@ -8,19 +8,19 @@ export default Component.extend({
|
|||
spread: 2,
|
||||
|
||||
startsAt: computed('size', 'page', function() {
|
||||
return (this.get('page') - 1) * this.get('size') + 1;
|
||||
return (this.page - 1) * this.size + 1;
|
||||
}),
|
||||
|
||||
endsAt: computed('source.[]', 'size', 'page', function() {
|
||||
return Math.min(this.get('page') * this.get('size'), this.get('source.length'));
|
||||
return Math.min(this.page * this.size, this.get('source.length'));
|
||||
}),
|
||||
|
||||
lastPage: computed('source.[]', 'size', function() {
|
||||
return Math.ceil(this.get('source.length') / this.get('size'));
|
||||
return Math.ceil(this.get('source.length') / this.size);
|
||||
}),
|
||||
|
||||
pageLinks: computed('source.[]', 'page', 'spread', function() {
|
||||
const { spread, page, lastPage } = this.getProperties('spread', 'page', 'lastPage');
|
||||
const { spread, page, lastPage } = this;
|
||||
|
||||
// When there is only one page, don't bother with page links
|
||||
if (lastPage === 1) {
|
||||
|
@ -38,8 +38,8 @@ export default Component.extend({
|
|||
}),
|
||||
|
||||
list: computed('source.[]', 'page', 'size', function() {
|
||||
const size = this.get('size');
|
||||
const start = (this.get('page') - 1) * size;
|
||||
return this.get('source').slice(start, start + size);
|
||||
const size = this.size;
|
||||
const start = (this.page - 1) * size;
|
||||
return this.source.slice(start, start + size);
|
||||
}),
|
||||
});
|
||||
|
|
|
@ -9,7 +9,7 @@ export default Component.extend({
|
|||
|
||||
// Plan for a future with metadata (e.g., isSelected)
|
||||
decoratedSource: computed('source.[]', function() {
|
||||
return this.get('source').map(row => ({
|
||||
return this.source.map(row => ({
|
||||
model: row,
|
||||
}));
|
||||
}),
|
||||
|
|
|
@ -16,10 +16,10 @@ export default Component.extend({
|
|||
classNameBindings: ['isActive:is-active', 'sortDescending:desc:asc'],
|
||||
|
||||
isActive: computed('currentProp', 'prop', function() {
|
||||
return this.get('currentProp') === this.get('prop');
|
||||
return this.currentProp === this.prop;
|
||||
}),
|
||||
|
||||
shouldSortDescending: computed('sortDescending', 'isActive', function() {
|
||||
return !this.get('isActive') || !this.get('sortDescending');
|
||||
return !this.isActive || !this.sortDescending;
|
||||
}),
|
||||
});
|
||||
|
|
|
@ -27,8 +27,8 @@ export default Component.extend({
|
|||
},
|
||||
|
||||
didReceiveAttrs() {
|
||||
const dropdown = this.get('dropdown');
|
||||
if (this.get('isOpen') && dropdown) {
|
||||
const dropdown = this.dropdown;
|
||||
if (this.isOpen && dropdown) {
|
||||
run.scheduleOnce('afterRender', () => {
|
||||
dropdown.actions.reposition();
|
||||
});
|
||||
|
@ -37,22 +37,22 @@ export default Component.extend({
|
|||
|
||||
actions: {
|
||||
toggle({ key }) {
|
||||
const newSelection = this.get('selection').slice();
|
||||
const newSelection = this.selection.slice();
|
||||
if (newSelection.includes(key)) {
|
||||
newSelection.removeObject(key);
|
||||
} else {
|
||||
newSelection.addObject(key);
|
||||
}
|
||||
this.get('onSelect')(newSelection);
|
||||
this.onSelect(newSelection);
|
||||
},
|
||||
|
||||
openOnArrowDown(dropdown, e) {
|
||||
this.capture(dropdown);
|
||||
|
||||
if (!this.get('isOpen') && e.keyCode === ARROW_DOWN) {
|
||||
if (!this.isOpen && e.keyCode === ARROW_DOWN) {
|
||||
dropdown.actions.open(e);
|
||||
e.preventDefault();
|
||||
} else if (this.get('isOpen') && (e.keyCode === TAB || e.keyCode === ARROW_DOWN)) {
|
||||
} else if (this.isOpen && (e.keyCode === TAB || e.keyCode === ARROW_DOWN)) {
|
||||
const optionsId = this.element.querySelector('.dropdown-trigger').getAttribute('aria-owns');
|
||||
const firstElement = document.querySelector(`#${optionsId} .dropdown-option`);
|
||||
|
||||
|
@ -66,7 +66,7 @@ export default Component.extend({
|
|||
traverseList(option, e) {
|
||||
if (e.keyCode === ESC) {
|
||||
// Close the dropdown
|
||||
const dropdown = this.get('dropdown');
|
||||
const dropdown = this.dropdown;
|
||||
if (dropdown) {
|
||||
dropdown.actions.close(e);
|
||||
// Return focus to the trigger so tab works as expected
|
||||
|
|
|
@ -20,24 +20,24 @@ export default Component.extend({
|
|||
|
||||
// An instance of a StatsTracker. An alternative interface to resource
|
||||
tracker: computed('trackedResource', 'type', function() {
|
||||
const resource = this.get('trackedResource');
|
||||
return this.get('statsTrackersRegistry').getTracker(resource);
|
||||
const resource = this.trackedResource;
|
||||
return this.statsTrackersRegistry.getTracker(resource);
|
||||
}),
|
||||
|
||||
type: computed('resource', function() {
|
||||
const resource = this.get('resource');
|
||||
const resource = this.resource;
|
||||
return resource && resource.constructor.modelName;
|
||||
}),
|
||||
|
||||
trackedResource: computed('resource', 'type', function() {
|
||||
// TaskStates use the allocation stats tracker
|
||||
return this.get('type') === 'task-state'
|
||||
return this.type === 'task-state'
|
||||
? this.get('resource.allocation')
|
||||
: this.get('resource');
|
||||
: this.resource;
|
||||
}),
|
||||
|
||||
metricLabel: computed('metric', function() {
|
||||
const metric = this.get('metric');
|
||||
const metric = this.metric;
|
||||
const mappings = {
|
||||
cpu: 'CPU',
|
||||
memory: 'Memory',
|
||||
|
@ -46,10 +46,10 @@ export default Component.extend({
|
|||
}),
|
||||
|
||||
data: computed('resource', 'metric', 'type', function() {
|
||||
if (!this.get('tracker')) return [];
|
||||
if (!this.tracker) return [];
|
||||
|
||||
const metric = this.get('metric');
|
||||
if (this.get('type') === 'task-state') {
|
||||
const metric = this.metric;
|
||||
if (this.type === 'task-state') {
|
||||
// handle getting the right task out of the tracker
|
||||
const task = this.get('tracker.tasks').findBy('task', this.get('resource.name'));
|
||||
return task && task[metric];
|
||||
|
@ -59,9 +59,9 @@ export default Component.extend({
|
|||
}),
|
||||
|
||||
reservedAmount: computed('resource', 'metric', 'type', function() {
|
||||
const metricProperty = this.get('metric') === 'cpu' ? 'reservedCPU' : 'reservedMemory';
|
||||
const metricProperty = this.metric === 'cpu' ? 'reservedCPU' : 'reservedMemory';
|
||||
|
||||
if (this.get('type') === 'task-state') {
|
||||
if (this.type === 'task-state') {
|
||||
const task = this.get('tracker.tasks').findBy('task', this.get('resource.name'));
|
||||
return task[metricProperty];
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ export default Component.extend({
|
|||
}),
|
||||
|
||||
chartClass: computed('metric', function() {
|
||||
const metric = this.get('metric');
|
||||
const metric = this.metric;
|
||||
const mappings = {
|
||||
cpu: 'is-info',
|
||||
memory: 'is-danger',
|
||||
|
@ -87,13 +87,13 @@ export default Component.extend({
|
|||
}),
|
||||
|
||||
didReceiveAttrs() {
|
||||
if (this.get('tracker')) {
|
||||
this.get('poller').perform();
|
||||
if (this.tracker) {
|
||||
this.poller.perform();
|
||||
}
|
||||
},
|
||||
|
||||
willDestroy() {
|
||||
this.get('poller').cancelAll();
|
||||
this.poller.cancelAll();
|
||||
this.get('tracker.signalPause').perform();
|
||||
},
|
||||
});
|
||||
|
|
|
@ -14,7 +14,7 @@ export default Component.extend({
|
|||
}),
|
||||
|
||||
gotoRegion(region) {
|
||||
this.get('router').transitionTo('jobs', {
|
||||
this.router.transitionTo('jobs', {
|
||||
queryParams: { region },
|
||||
});
|
||||
},
|
||||
|
|
|
@ -11,7 +11,7 @@ export default Component.extend({
|
|||
|
||||
// An allocation can also be provided directly
|
||||
allocation: computed('allocationId', function() {
|
||||
return this.get('store').findRecord('allocation', this.get('allocationId'));
|
||||
return this.store.findRecord('allocation', this.allocationId);
|
||||
}),
|
||||
|
||||
time: null,
|
||||
|
|
|
@ -20,18 +20,18 @@ export default Component.extend({
|
|||
actions: {
|
||||
setSearchTerm(e) {
|
||||
this.set('_searchTerm', e.target.value);
|
||||
run.debounce(this, updateSearch, this.get('debounce'));
|
||||
run.debounce(this, updateSearch, this.debounce);
|
||||
},
|
||||
|
||||
clear() {
|
||||
this.set('_searchTerm', '');
|
||||
run.debounce(this, updateSearch, this.get('debounce'));
|
||||
run.debounce(this, updateSearch, this.debounce);
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
function updateSearch() {
|
||||
const newTerm = this.get('_searchTerm');
|
||||
const newTerm = this._searchTerm;
|
||||
this.onChange(newTerm);
|
||||
this.set('searchTerm', newTerm);
|
||||
}
|
||||
|
|
|
@ -22,8 +22,8 @@ export default Component.extend({
|
|||
// const targetURL = this.get('router').urlFor('servers.server', this.get('agent'));
|
||||
// const currentURL = `${this.get('router.rootURL').slice(0, -1)}${this.get('router.currentURL')}`;
|
||||
|
||||
const router = this.get('router');
|
||||
const targetURL = router.generate('servers.server', this.get('agent'));
|
||||
const router = this.router;
|
||||
const targetURL = router.generate('servers.server', this.agent);
|
||||
const currentURL = `${router.get('rootURL').slice(0, -1)}${
|
||||
router.get('currentURL').split('?')[0]
|
||||
}`;
|
||||
|
@ -33,7 +33,7 @@ export default Component.extend({
|
|||
}),
|
||||
|
||||
click() {
|
||||
const transition = () => this.get('router').transitionTo('servers.server', this.get('agent'));
|
||||
const transition = () => this.router.transitionTo('servers.server', this.agent);
|
||||
lazyClick([transition, event]);
|
||||
},
|
||||
});
|
||||
|
|
|
@ -24,7 +24,7 @@ export default LineChart.extend({
|
|||
title: 'Stats Time Series Chart',
|
||||
|
||||
description: computed('data.[]', 'xProp', 'yProp', function() {
|
||||
const { xProp, yProp, data } = this.getProperties('data', 'xProp', 'yProp');
|
||||
const { xProp, yProp, data } = this;
|
||||
const yRange = d3Array.extent(data, d => d[yProp]);
|
||||
const xRange = d3Array.extent(data, d => d[xProp]);
|
||||
const yFormatter = this.yFormat();
|
||||
|
@ -35,9 +35,9 @@ export default LineChart.extend({
|
|||
}),
|
||||
|
||||
xScale: computed('data.[]', 'xProp', 'timeseries', 'yAxisOffset', function() {
|
||||
const xProp = this.get('xProp');
|
||||
const scale = this.get('timeseries') ? d3Scale.scaleTime() : d3Scale.scaleLinear();
|
||||
const data = this.get('data');
|
||||
const xProp = this.xProp;
|
||||
const scale = this.timeseries ? d3Scale.scaleTime() : d3Scale.scaleLinear();
|
||||
const data = this.data;
|
||||
|
||||
const [low, high] = d3Array.extent(data, d => d[xProp]);
|
||||
const minLow = moment(high)
|
||||
|
@ -45,14 +45,14 @@ export default LineChart.extend({
|
|||
.toDate();
|
||||
|
||||
const extent = data.length ? [Math.min(low, minLow), high] : [minLow, new Date()];
|
||||
scale.rangeRound([10, this.get('yAxisOffset')]).domain(extent);
|
||||
scale.rangeRound([10, this.yAxisOffset]).domain(extent);
|
||||
|
||||
return scale;
|
||||
}),
|
||||
|
||||
yScale: computed('data.[]', 'yProp', 'xAxisOffset', function() {
|
||||
const yProp = this.get('yProp');
|
||||
const yValues = (this.get('data') || []).mapBy(yProp);
|
||||
const yProp = this.yProp;
|
||||
const yValues = (this.data || []).mapBy(yProp);
|
||||
|
||||
let [low, high] = [0, 1];
|
||||
if (yValues.compact().length) {
|
||||
|
@ -61,7 +61,7 @@ export default LineChart.extend({
|
|||
|
||||
return d3Scale
|
||||
.scaleLinear()
|
||||
.rangeRound([this.get('xAxisOffset'), 10])
|
||||
.rangeRound([this.xAxisOffset, 10])
|
||||
.domain([Math.min(0, low), Math.max(1, high)]);
|
||||
}),
|
||||
});
|
||||
|
|
|
@ -11,6 +11,6 @@ export default Component.extend({
|
|||
onClick() {},
|
||||
|
||||
click(event) {
|
||||
lazyClick([this.get('onClick'), event]);
|
||||
lazyClick([this.onClick, event]);
|
||||
},
|
||||
});
|
||||
|
|
|
@ -26,7 +26,7 @@ export default Component.extend(WindowResizable, {
|
|||
serverTimeout: 5000,
|
||||
|
||||
didReceiveAttrs() {
|
||||
if (this.get('allocation') && this.get('task')) {
|
||||
if (this.allocation && this.task) {
|
||||
this.send('toggleStream');
|
||||
}
|
||||
},
|
||||
|
@ -53,29 +53,29 @@ export default Component.extend(WindowResizable, {
|
|||
const allocation = this.get('allocation.id');
|
||||
|
||||
const url = `/v1/client/fs/logs/${allocation}`;
|
||||
return this.get('useServer') ? url : `//${address}${url}`;
|
||||
return this.useServer ? url : `//${address}${url}`;
|
||||
}),
|
||||
|
||||
logParams: computed('task', 'mode', function() {
|
||||
return {
|
||||
task: this.get('task'),
|
||||
type: this.get('mode'),
|
||||
task: this.task,
|
||||
type: this.mode,
|
||||
};
|
||||
}),
|
||||
|
||||
logger: logger('logUrl', 'logParams', function logFetch() {
|
||||
// If the log request can't settle in one second, the client
|
||||
// must be unavailable and the server should be used instead
|
||||
const timing = this.get('useServer') ? this.get('serverTimeout') : this.get('clientTimeout');
|
||||
const timing = this.useServer ? this.serverTimeout : this.clientTimeout;
|
||||
return url =>
|
||||
RSVP.race([this.get('token').authorizedRequest(url), timeout(timing)]).then(
|
||||
RSVP.race([this.token.authorizedRequest(url), timeout(timing)]).then(
|
||||
response => response,
|
||||
error => {
|
||||
if (this.get('useServer')) {
|
||||
if (this.useServer) {
|
||||
this.set('noConnection', true);
|
||||
} else {
|
||||
this.send('failoverToServer');
|
||||
this.get('stream').perform();
|
||||
this.stream.perform();
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
|
@ -98,32 +98,32 @@ export default Component.extend(WindowResizable, {
|
|||
}),
|
||||
|
||||
stream: task(function*() {
|
||||
this.get('logger').on('tick', () => {
|
||||
this.logger.on('tick', () => {
|
||||
run.scheduleOnce('afterRender', () => {
|
||||
const cliWindow = this.$('.cli-window');
|
||||
cliWindow.scrollTop(cliWindow[0].scrollHeight);
|
||||
});
|
||||
});
|
||||
|
||||
yield this.get('logger').startStreaming();
|
||||
this.get('logger').off('tick');
|
||||
yield this.logger.startStreaming();
|
||||
this.logger.off('tick');
|
||||
}),
|
||||
|
||||
willDestroy() {
|
||||
this.get('logger').stop();
|
||||
this.logger.stop();
|
||||
},
|
||||
|
||||
actions: {
|
||||
setMode(mode) {
|
||||
this.get('logger').stop();
|
||||
this.logger.stop();
|
||||
this.set('mode', mode);
|
||||
this.get('stream').perform();
|
||||
this.stream.perform();
|
||||
},
|
||||
toggleStream() {
|
||||
if (this.get('logger.isStreaming')) {
|
||||
this.get('logger').stop();
|
||||
this.logger.stop();
|
||||
} else {
|
||||
this.get('stream').perform();
|
||||
this.stream.perform();
|
||||
}
|
||||
},
|
||||
failoverToServer() {
|
||||
|
|
|
@ -25,11 +25,11 @@ export default Component.extend({
|
|||
stats: computed('task', 'task.isRunning', function() {
|
||||
if (!this.get('task.isRunning')) return;
|
||||
|
||||
return this.get('statsTrackersRegistry').getTracker(this.get('task.allocation'));
|
||||
return this.statsTrackersRegistry.getTracker(this.get('task.allocation'));
|
||||
}),
|
||||
|
||||
taskStats: computed('task.name', 'stats.tasks.[]', function() {
|
||||
if (!this.get('stats')) return;
|
||||
if (!this.stats) return;
|
||||
|
||||
return this.get('stats.tasks').findBy('task', this.get('task.name'));
|
||||
}),
|
||||
|
@ -40,12 +40,12 @@ export default Component.extend({
|
|||
onClick() {},
|
||||
|
||||
click(event) {
|
||||
lazyClick([this.get('onClick'), event]);
|
||||
lazyClick([this.onClick, event]);
|
||||
},
|
||||
|
||||
fetchStats: task(function*() {
|
||||
do {
|
||||
if (this.get('stats')) {
|
||||
if (this.stats) {
|
||||
try {
|
||||
yield this.get('stats.poll').perform();
|
||||
this.set('statsError', false);
|
||||
|
@ -55,16 +55,16 @@ export default Component.extend({
|
|||
}
|
||||
|
||||
yield timeout(500);
|
||||
} while (this.get('enablePolling'));
|
||||
} while (this.enablePolling);
|
||||
}).drop(),
|
||||
|
||||
didReceiveAttrs() {
|
||||
const allocation = this.get('task.allocation');
|
||||
|
||||
if (allocation) {
|
||||
this.get('fetchStats').perform();
|
||||
this.fetchStats.perform();
|
||||
} else {
|
||||
this.get('fetchStats').cancelAll();
|
||||
this.fetchStats.cancelAll();
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
|
@ -25,7 +25,7 @@ export default Component.extend({
|
|||
this.set('state', 'prompt');
|
||||
},
|
||||
confirm() {
|
||||
RSVP.resolve(this.get('onConfirm')()).then(() => {
|
||||
RSVP.resolve(this.onConfirm()).then(() => {
|
||||
this.send('setToIdle');
|
||||
});
|
||||
},
|
||||
|
|
|
@ -19,39 +19,39 @@ export default Controller.extend({
|
|||
error: null,
|
||||
|
||||
errorStr: computed('error', function() {
|
||||
return this.get('error').toString();
|
||||
return this.error.toString();
|
||||
}),
|
||||
|
||||
errorCodes: computed('error', function() {
|
||||
return codesForError(this.get('error'));
|
||||
return codesForError(this.error);
|
||||
}),
|
||||
|
||||
is403: computed('errorCodes.[]', function() {
|
||||
return this.get('errorCodes').includes('403');
|
||||
return this.errorCodes.includes('403');
|
||||
}),
|
||||
|
||||
is404: computed('errorCodes.[]', function() {
|
||||
return this.get('errorCodes').includes('404');
|
||||
return this.errorCodes.includes('404');
|
||||
}),
|
||||
|
||||
is500: computed('errorCodes.[]', function() {
|
||||
return this.get('errorCodes').includes('500');
|
||||
return this.errorCodes.includes('500');
|
||||
}),
|
||||
|
||||
isNoLeader: computed('error', function() {
|
||||
const error = this.get('error');
|
||||
const error = this.error;
|
||||
return error instanceof NoLeaderError;
|
||||
}),
|
||||
|
||||
throwError: observer('error', function() {
|
||||
if (this.get('config.isDev')) {
|
||||
run.next(() => {
|
||||
throw this.get('error');
|
||||
throw this.error;
|
||||
});
|
||||
} else if (!Ember.testing) {
|
||||
run.next(() => {
|
||||
// eslint-disable-next-line
|
||||
console.warn('UNRECOVERABLE ERROR:', this.get('error'));
|
||||
console.warn('UNRECOVERABLE ERROR:', this.error);
|
||||
});
|
||||
}
|
||||
}),
|
||||
|
|
|
@ -43,11 +43,11 @@ export default Controller.extend(Sortable, Searchable, {
|
|||
selectionFlags: selection('qpFlags'),
|
||||
|
||||
optionsClass: computed('nodes.[]', function() {
|
||||
const classes = Array.from(new Set(this.get('nodes').mapBy('nodeClass'))).compact();
|
||||
const classes = Array.from(new Set(this.nodes.mapBy('nodeClass'))).compact();
|
||||
|
||||
// Remove any invalid node classes from the query param/selection
|
||||
scheduleOnce('actions', () => {
|
||||
this.set('qpClass', serialize(intersection(classes, this.get('selectionClass'))));
|
||||
this.set('qpClass', serialize(intersection(classes, this.selectionClass)));
|
||||
});
|
||||
|
||||
return classes.sort().map(dc => ({ key: dc, label: dc }));
|
||||
|
@ -60,13 +60,13 @@ export default Controller.extend(Sortable, Searchable, {
|
|||
]),
|
||||
|
||||
optionsDatacenter: computed('nodes.[]', function() {
|
||||
const datacenters = Array.from(new Set(this.get('nodes').mapBy('datacenter'))).compact();
|
||||
const datacenters = Array.from(new Set(this.nodes.mapBy('datacenter'))).compact();
|
||||
|
||||
// Remove any invalid datacenters from the query param/selection
|
||||
scheduleOnce('actions', () => {
|
||||
this.set(
|
||||
'qpDatacenter',
|
||||
serialize(intersection(datacenters, this.get('selectionDatacenter')))
|
||||
serialize(intersection(datacenters, this.selectionDatacenter))
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -90,17 +90,12 @@ export default Controller.extend(Sortable, Searchable, {
|
|||
selectionStatus: statuses,
|
||||
selectionDatacenter: datacenters,
|
||||
selectionFlags: flags,
|
||||
} = this.getProperties(
|
||||
'selectionClass',
|
||||
'selectionStatus',
|
||||
'selectionDatacenter',
|
||||
'selectionFlags'
|
||||
);
|
||||
} = this;
|
||||
|
||||
const onlyIneligible = flags.includes('ineligible');
|
||||
const onlyDraining = flags.includes('draining');
|
||||
|
||||
return this.get('nodes').filter(node => {
|
||||
return this.nodes.filter(node => {
|
||||
if (classes.length && !classes.includes(node.get('nodeClass'))) return false;
|
||||
if (statuses.length && !statuses.includes(node.get('status'))) return false;
|
||||
if (datacenters.length && !datacenters.includes(node.get('datacenter'))) return false;
|
||||
|
|
|
@ -62,7 +62,7 @@ export default Controller.extend(Sortable, Searchable, {
|
|||
optionsDatacenter: computed('visibleJobs.[]', function() {
|
||||
const flatten = (acc, val) => acc.concat(val);
|
||||
const allDatacenters = new Set(
|
||||
this.get('visibleJobs')
|
||||
this.visibleJobs
|
||||
.mapBy('datacenters')
|
||||
.reduce(flatten, [])
|
||||
);
|
||||
|
@ -72,7 +72,7 @@ export default Controller.extend(Sortable, Searchable, {
|
|||
scheduleOnce('actions', () => {
|
||||
this.set(
|
||||
'qpDatacenter',
|
||||
serialize(intersection(availableDatacenters, this.get('selectionDatacenter')))
|
||||
serialize(intersection(availableDatacenters, this.selectionDatacenter))
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -85,7 +85,7 @@ export default Controller.extend(Sortable, Searchable, {
|
|||
const hasPrefix = /.[-._]/;
|
||||
|
||||
// Collect and count all the prefixes
|
||||
const allNames = this.get('visibleJobs').mapBy('name');
|
||||
const allNames = this.visibleJobs.mapBy('name');
|
||||
const nameHistogram = allNames.reduce((hist, name) => {
|
||||
if (hasPrefix.test(name)) {
|
||||
const prefix = name.match(/(.+?)[-.]/)[1];
|
||||
|
@ -106,7 +106,7 @@ export default Controller.extend(Sortable, Searchable, {
|
|||
// Remove any invalid prefixes from the query param/selection
|
||||
const availablePrefixes = prefixes.mapBy('prefix');
|
||||
scheduleOnce('actions', () => {
|
||||
this.set('qpPrefix', serialize(intersection(availablePrefixes, this.get('selectionPrefix'))));
|
||||
this.set('qpPrefix', serialize(intersection(availablePrefixes, this.selectionPrefix)));
|
||||
});
|
||||
|
||||
// Sort, format, and include the count in the label
|
||||
|
@ -126,7 +126,7 @@ export default Controller.extend(Sortable, Searchable, {
|
|||
const hasNamespaces = this.get('system.namespaces.length');
|
||||
const activeNamespace = this.get('system.activeNamespace.id') || 'default';
|
||||
|
||||
return this.get('model')
|
||||
return this.model
|
||||
.compact()
|
||||
.filter(job => !hasNamespaces || job.get('namespace.id') === activeNamespace)
|
||||
.filter(job => !job.get('parent.content'));
|
||||
|
@ -144,16 +144,11 @@ export default Controller.extend(Sortable, Searchable, {
|
|||
selectionStatus: statuses,
|
||||
selectionDatacenter: datacenters,
|
||||
selectionPrefix: prefixes,
|
||||
} = this.getProperties(
|
||||
'selectionType',
|
||||
'selectionStatus',
|
||||
'selectionDatacenter',
|
||||
'selectionPrefix'
|
||||
);
|
||||
} = this;
|
||||
|
||||
// A job must match ALL filter facets, but it can match ANY selection within a facet
|
||||
// Always return early to prevent unnecessary facet predicates.
|
||||
return this.get('visibleJobs').filter(job => {
|
||||
return this.visibleJobs.filter(job => {
|
||||
if (types.length && !types.includes(job.get('displayType'))) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ export default Controller.extend(WithNamespaceResetting, {
|
|||
isEditing: false,
|
||||
|
||||
edit() {
|
||||
this.get('job').set('_newDefinition', JSON.stringify(this.get('definition'), null, 2));
|
||||
this.job.set('_newDefinition', JSON.stringify(this.definition, null, 2));
|
||||
this.set('isEditing', true);
|
||||
},
|
||||
|
||||
|
|
|
@ -15,12 +15,12 @@ export default Controller.extend({
|
|||
tokenRecord: null,
|
||||
|
||||
resetStore() {
|
||||
this.get('store').unloadAll();
|
||||
this.store.unloadAll();
|
||||
},
|
||||
|
||||
actions: {
|
||||
clearTokenProperties() {
|
||||
this.get('token').setProperties({
|
||||
this.token.setProperties({
|
||||
secret: undefined,
|
||||
});
|
||||
this.setProperties({
|
||||
|
@ -32,7 +32,7 @@ export default Controller.extend({
|
|||
},
|
||||
|
||||
verifyToken() {
|
||||
const { secret } = this.getProperties('secret', 'accessor');
|
||||
const { secret } = this;
|
||||
const TokenAdapter = getOwner(this).lookup('adapter:token');
|
||||
|
||||
this.set('token.secret', secret);
|
||||
|
@ -44,11 +44,11 @@ export default Controller.extend({
|
|||
|
||||
// Clear out all data to ensure only data the new token is privileged to
|
||||
// see is shown
|
||||
this.get('system').reset();
|
||||
this.system.reset();
|
||||
this.resetStore();
|
||||
|
||||
// Immediately refetch the token now that the store is empty
|
||||
const newToken = this.get('store').findRecord('token', tokenId);
|
||||
const newToken = this.store.findRecord('token', tokenId);
|
||||
|
||||
this.setProperties({
|
||||
tokenIsValid: true,
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import Helper from '@ember/component/helper';
|
||||
import { pluralize } from 'ember-inflector';
|
||||
|
||||
export function pluralize([term, count]) {
|
||||
return count === 1 ? term : term.pluralize();
|
||||
export function pluralizeHelper([term, count]) {
|
||||
return count === 1 ? term : pluralize(term);
|
||||
}
|
||||
|
||||
export default Helper.helper(pluralize);
|
||||
export default Helper.helper(pluralizeHelper);
|
||||
|
|
|
@ -41,13 +41,13 @@ export default Mixin.create({
|
|||
// preferable to generalize this rather than risking it being
|
||||
// forgotten on a single page.
|
||||
resetPagination() {
|
||||
if (this.get('currentPage') != null) {
|
||||
if (this.currentPage != null) {
|
||||
this.set('currentPage', 1);
|
||||
}
|
||||
},
|
||||
|
||||
fuse: computed('listToSearch.[]', 'fuzzySearchProps.[]', function() {
|
||||
return new Fuse(this.get('listToSearch'), {
|
||||
return new Fuse(this.listToSearch, {
|
||||
shouldSort: true,
|
||||
threshold: 0.4,
|
||||
location: 0,
|
||||
|
@ -56,7 +56,7 @@ export default Mixin.create({
|
|||
matchAllTokens: true,
|
||||
maxPatternLength: 32,
|
||||
minMatchCharLength: 1,
|
||||
keys: this.get('fuzzySearchProps') || [],
|
||||
keys: this.fuzzySearchProps || [],
|
||||
getFn(item, key) {
|
||||
return get(item, key);
|
||||
},
|
||||
|
@ -73,31 +73,31 @@ export default Mixin.create({
|
|||
'fuzzySearchProps.[]',
|
||||
'regexSearchProps.[]',
|
||||
function() {
|
||||
const searchTerm = this.get('searchTerm').trim();
|
||||
const searchTerm = this.searchTerm.trim();
|
||||
|
||||
if (!searchTerm || !searchTerm.length) {
|
||||
return this.get('listToSearch');
|
||||
return this.listToSearch;
|
||||
}
|
||||
|
||||
const results = [];
|
||||
|
||||
if (this.get('exactMatchEnabled')) {
|
||||
if (this.exactMatchEnabled) {
|
||||
results.push(
|
||||
...exactMatchSearch(
|
||||
searchTerm,
|
||||
this.get('listToSearch'),
|
||||
this.get('exactMatchSearchProps')
|
||||
this.listToSearch,
|
||||
this.exactMatchSearchProps
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (this.get('fuzzySearchEnabled')) {
|
||||
results.push(...this.get('fuse').search(searchTerm));
|
||||
if (this.fuzzySearchEnabled) {
|
||||
results.push(...this.fuse.search(searchTerm));
|
||||
}
|
||||
|
||||
if (this.get('regexEnabled')) {
|
||||
if (this.regexEnabled) {
|
||||
results.push(
|
||||
...regexSearch(searchTerm, this.get('listToSearch'), this.get('regexSearchProps'))
|
||||
...regexSearch(searchTerm, this.listToSearch, this.regexSearchProps)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -21,10 +21,10 @@ export default Mixin.create({
|
|||
listToSort: computed(() => []),
|
||||
|
||||
listSorted: computed('listToSort.[]', 'sortProperty', 'sortDescending', function() {
|
||||
const sorted = this.get('listToSort')
|
||||
const sorted = this.listToSort
|
||||
.compact()
|
||||
.sortBy(this.get('sortProperty'));
|
||||
if (this.get('sortDescending')) {
|
||||
.sortBy(this.sortProperty);
|
||||
if (this.sortDescending) {
|
||||
return sorted.reverse();
|
||||
}
|
||||
return sorted;
|
||||
|
|
|
@ -10,12 +10,12 @@ export default Mixin.create({
|
|||
|
||||
setupWindowResize: function() {
|
||||
run.scheduleOnce('afterRender', this, () => {
|
||||
this.set('_windowResizeHandler', this.get('windowResizeHandler').bind(this));
|
||||
$(window).on('resize', this.get('_windowResizeHandler'));
|
||||
this.set('_windowResizeHandler', this.windowResizeHandler.bind(this));
|
||||
$(window).on('resize', this._windowResizeHandler);
|
||||
});
|
||||
}.on('didInsertElement'),
|
||||
|
||||
removeWindowResize: function() {
|
||||
$(window).off('resize', this.get('_windowResizeHandler'));
|
||||
$(window).off('resize', this._windowResizeHandler);
|
||||
}.on('willDestroyElement'),
|
||||
});
|
||||
|
|
|
@ -9,14 +9,14 @@ export default Mixin.create({
|
|||
|
||||
setupDocumentVisibility: function() {
|
||||
if (!Ember.testing) {
|
||||
this.set('_visibilityHandler', this.get('visibilityHandler').bind(this));
|
||||
document.addEventListener('visibilitychange', this.get('_visibilityHandler'));
|
||||
this.set('_visibilityHandler', this.visibilityHandler.bind(this));
|
||||
document.addEventListener('visibilitychange', this._visibilityHandler);
|
||||
}
|
||||
}.on('init'),
|
||||
|
||||
removeDocumentVisibility: function() {
|
||||
if (!Ember.testing) {
|
||||
document.removeEventListener('visibilitychange', this.get('_visibilityHandler'));
|
||||
document.removeEventListener('visibilitychange', this._visibilityHandler);
|
||||
}
|
||||
}.on('willDestroy'),
|
||||
});
|
||||
|
|
|
@ -2,7 +2,7 @@ import Mixin from '@ember/object/mixin';
|
|||
|
||||
export default Mixin.create({
|
||||
setupController(controller) {
|
||||
if (this.get('isForbidden')) {
|
||||
if (this.isForbidden) {
|
||||
this.set('isForbidden', undefined);
|
||||
controller.set('isForbidden', true);
|
||||
}
|
||||
|
|
|
@ -9,14 +9,14 @@ export default Mixin.create({
|
|||
|
||||
setupDocumentVisibility: function() {
|
||||
if (!Ember.testing) {
|
||||
this.set('_visibilityHandler', this.get('visibilityHandler').bind(this));
|
||||
document.addEventListener('visibilitychange', this.get('_visibilityHandler'));
|
||||
this.set('_visibilityHandler', this.visibilityHandler.bind(this));
|
||||
document.addEventListener('visibilitychange', this._visibilityHandler);
|
||||
}
|
||||
}.on('activate'),
|
||||
|
||||
removeDocumentVisibility: function() {
|
||||
if (!Ember.testing) {
|
||||
document.removeEventListener('visibilitychange', this.get('_visibilityHandler'));
|
||||
document.removeEventListener('visibilitychange', this._visibilityHandler);
|
||||
}
|
||||
}.on('deactivate'),
|
||||
});
|
||||
|
|
|
@ -7,7 +7,7 @@ export default Mixin.create(WithVisibilityDetection, {
|
|||
watchers: computed(() => []),
|
||||
|
||||
cancelAllWatchers() {
|
||||
this.get('watchers').forEach(watcher => {
|
||||
this.watchers.forEach(watcher => {
|
||||
assert('Watchers must be Ember Concurrency Tasks.', !!watcher.cancelAll);
|
||||
watcher.cancelAll();
|
||||
});
|
||||
|
|
|
@ -16,11 +16,11 @@ export default Model.extend({
|
|||
region: attr('string'),
|
||||
|
||||
rpcAddr: computed('address', 'port', function() {
|
||||
const { address, rpcPort } = this.getProperties('address', 'rpcPort');
|
||||
const { address, rpcPort } = this;
|
||||
return address && rpcPort && `${address}:${rpcPort}`;
|
||||
}),
|
||||
|
||||
isLeader: computed('system.leader.rpcAddr', function() {
|
||||
return this.get('system.leader.rpcAddr') === this.get('rpcAddr');
|
||||
return this.get('system.leader.rpcAddr') === this.rpcAddr;
|
||||
}),
|
||||
});
|
||||
|
|
|
@ -36,7 +36,7 @@ export default Model.extend({
|
|||
clientStatus: attr('string'),
|
||||
desiredStatus: attr('string'),
|
||||
statusIndex: computed('clientStatus', function() {
|
||||
return STATUS_ORDER[this.get('clientStatus')] || 100;
|
||||
return STATUS_ORDER[this.clientStatus] || 100;
|
||||
}),
|
||||
|
||||
isRunning: equal('clientStatus', 'running'),
|
||||
|
@ -57,12 +57,12 @@ export default Model.extend({
|
|||
lost: 'is-light',
|
||||
};
|
||||
|
||||
return classMap[this.get('clientStatus')] || 'is-dark';
|
||||
return classMap[this.clientStatus] || 'is-dark';
|
||||
}),
|
||||
|
||||
taskGroup: computed('taskGroupName', 'job.taskGroups.[]', function() {
|
||||
const taskGroups = this.get('job.taskGroups');
|
||||
return taskGroups && taskGroups.findBy('name', this.get('taskGroupName'));
|
||||
return taskGroups && taskGroups.findBy('name', this.taskGroupName);
|
||||
}),
|
||||
|
||||
unhealthyDrivers: computed('taskGroup.drivers.[]', 'node.unhealthyDriverNames.[]', function() {
|
||||
|
@ -80,19 +80,17 @@ export default Model.extend({
|
|||
rescheduleEvents: fragmentArray('reschedule-event'),
|
||||
|
||||
hasRescheduleEvents: computed('rescheduleEvents.length', 'nextAllocation', function() {
|
||||
return this.get('rescheduleEvents.length') > 0 || this.get('nextAllocation');
|
||||
return this.get('rescheduleEvents.length') > 0 || this.nextAllocation;
|
||||
}),
|
||||
|
||||
hasStoppedRescheduling: computed(
|
||||
'nextAllocation',
|
||||
'clientStatus',
|
||||
'followUpEvaluation',
|
||||
'followUpEvaluation.content',
|
||||
function() {
|
||||
return (
|
||||
!this.get('nextAllocation.content') &&
|
||||
!this.get('followUpEvaluation.content') &&
|
||||
this.get('clientStatus') === 'failed'
|
||||
);
|
||||
return !this.get('nextAllocation.content') &&
|
||||
!this.get('followUpEvaluation.content') &&
|
||||
this.clientStatus === 'failed';
|
||||
}
|
||||
),
|
||||
});
|
||||
|
|
|
@ -18,12 +18,10 @@ export default Model.extend({
|
|||
// If any task group is not promoted yet requires promotion and the deployment
|
||||
// is still running, the deployment needs promotion.
|
||||
requiresPromotion: computed('taskGroupSummaries.@each.promoted', function() {
|
||||
return (
|
||||
this.get('status') === 'running' &&
|
||||
this.get('taskGroupSummaries')
|
||||
.toArray()
|
||||
.some(summary => summary.get('requiresPromotion') && !summary.get('promoted'))
|
||||
);
|
||||
return this.status === 'running' &&
|
||||
this.taskGroupSummaries
|
||||
.toArray()
|
||||
.some(summary => summary.get('requiresPromotion') && !summary.get('promoted'));
|
||||
}),
|
||||
|
||||
status: attr('string'),
|
||||
|
@ -35,7 +33,7 @@ export default Model.extend({
|
|||
allocations: hasMany('allocations'),
|
||||
|
||||
version: computed('versionNumber', 'job.versions.content.@each.number', function() {
|
||||
return (this.get('job.versions') || []).findBy('number', this.get('versionNumber'));
|
||||
return (this.get('job.versions') || []).findBy('number', this.versionNumber);
|
||||
}),
|
||||
|
||||
// Dependent keys can only go one level past an @each so an alias is needed
|
||||
|
@ -57,11 +55,11 @@ export default Model.extend({
|
|||
cancelled: 'is-cancelled',
|
||||
};
|
||||
|
||||
return classMap[this.get('status')] || 'is-dark';
|
||||
return classMap[this.status] || 'is-dark';
|
||||
}),
|
||||
|
||||
promote() {
|
||||
assert('A deployment needs to requirePromotion to be promoted', this.get('requiresPromotion'));
|
||||
assert('A deployment needs to requirePromotion to be promoted', this.requiresPromotion);
|
||||
return this.store.adapterFor('deployment').promote(this);
|
||||
},
|
||||
});
|
||||
|
|
|
@ -32,7 +32,7 @@ export default Model.extend({
|
|||
parameterizedDetails: attr(),
|
||||
|
||||
hasChildren: computed('periodic', 'parameterized', 'dispatched', function() {
|
||||
return this.get('periodic') || (this.get('parameterized') && !this.get('dispatched'));
|
||||
return this.periodic || (this.parameterized && !this.dispatched);
|
||||
}),
|
||||
|
||||
parent: belongsTo('job', { inverse: 'children' }),
|
||||
|
@ -40,19 +40,19 @@ export default Model.extend({
|
|||
|
||||
// The parent job name is prepended to child launch job names
|
||||
trimmedName: computed('name', 'parent', function() {
|
||||
return this.get('parent.content') ? this.get('name').replace(/.+?\//, '') : this.get('name');
|
||||
return this.get('parent.content') ? this.name.replace(/.+?\//, '') : this.name;
|
||||
}),
|
||||
|
||||
// A composite of type and other job attributes to determine
|
||||
// a better type descriptor for human interpretation rather
|
||||
// than for scheduling.
|
||||
displayType: computed('type', 'periodic', 'parameterized', function() {
|
||||
if (this.get('periodic')) {
|
||||
if (this.periodic) {
|
||||
return 'periodic';
|
||||
} else if (this.get('parameterized')) {
|
||||
} else if (this.parameterized) {
|
||||
return 'parameterized';
|
||||
}
|
||||
return this.get('type');
|
||||
return this.type;
|
||||
}),
|
||||
|
||||
// A composite of type and other job attributes to determine
|
||||
|
@ -64,20 +64,20 @@ export default Model.extend({
|
|||
'parent.periodic',
|
||||
'parent.parameterized',
|
||||
function() {
|
||||
const type = this.get('type');
|
||||
const type = this.type;
|
||||
|
||||
if (this.get('parent.periodic')) {
|
||||
return 'periodic-child';
|
||||
} else if (this.get('parent.parameterized')) {
|
||||
return 'parameterized-child';
|
||||
} else if (this.get('periodic')) {
|
||||
} else if (this.periodic) {
|
||||
return 'periodic';
|
||||
} else if (this.get('parameterized')) {
|
||||
} else if (this.parameterized) {
|
||||
return 'parameterized';
|
||||
} else if (JOB_TYPES.includes(type)) {
|
||||
// Guard against the API introducing a new type before the UI
|
||||
// is prepared to handle it.
|
||||
return this.get('type');
|
||||
return this.type;
|
||||
}
|
||||
|
||||
// A fail-safe in the event the API introduces a new type.
|
||||
|
@ -122,7 +122,7 @@ export default Model.extend({
|
|||
namespace: belongsTo('namespace'),
|
||||
|
||||
drivers: computed('taskGroups.@each.drivers', function() {
|
||||
return this.get('taskGroups')
|
||||
return this.taskGroups
|
||||
.mapBy('drivers')
|
||||
.reduce((all, drivers) => {
|
||||
all.push(...drivers);
|
||||
|
@ -134,7 +134,7 @@ export default Model.extend({
|
|||
// Getting all unhealthy drivers for a job can be incredibly expensive if the job
|
||||
// has many allocations. This can lead to making an API request for many nodes.
|
||||
unhealthyDrivers: computed('allocations.@each.unhealthyDrivers.[]', function() {
|
||||
return this.get('allocations')
|
||||
return this.allocations
|
||||
.mapBy('unhealthyDrivers')
|
||||
.reduce((all, drivers) => {
|
||||
all.push(...drivers);
|
||||
|
@ -144,7 +144,7 @@ export default Model.extend({
|
|||
}),
|
||||
|
||||
hasBlockedEvaluation: computed('evaluations.@each.isBlocked', function() {
|
||||
return this.get('evaluations')
|
||||
return this.evaluations
|
||||
.toArray()
|
||||
.some(evaluation => evaluation.get('isBlocked'));
|
||||
}),
|
||||
|
@ -152,7 +152,7 @@ export default Model.extend({
|
|||
hasPlacementFailures: and('latestFailureEvaluation', 'hasBlockedEvaluation'),
|
||||
|
||||
latestEvaluation: computed('evaluations.@each.modifyIndex', 'evaluations.isPending', function() {
|
||||
const evaluations = this.get('evaluations');
|
||||
const evaluations = this.evaluations;
|
||||
if (!evaluations || evaluations.get('isPending')) {
|
||||
return null;
|
||||
}
|
||||
|
@ -163,7 +163,7 @@ export default Model.extend({
|
|||
'evaluations.@each.modifyIndex',
|
||||
'evaluations.isPending',
|
||||
function() {
|
||||
const evaluations = this.get('evaluations');
|
||||
const evaluations = this.evaluations;
|
||||
if (!evaluations || evaluations.get('isPending')) {
|
||||
return null;
|
||||
}
|
||||
|
@ -180,7 +180,7 @@ export default Model.extend({
|
|||
latestDeployment: belongsTo('deployment', { inverse: 'jobForLatest' }),
|
||||
|
||||
runningDeployment: computed('latestDeployment', 'latestDeployment.isRunning', function() {
|
||||
const latest = this.get('latestDeployment');
|
||||
const latest = this.latestDeployment;
|
||||
if (latest.get('isRunning')) return latest;
|
||||
}),
|
||||
|
||||
|
@ -197,22 +197,22 @@ export default Model.extend({
|
|||
},
|
||||
|
||||
plan() {
|
||||
assert('A job must be parsed before planned', this.get('_newDefinitionJSON'));
|
||||
assert('A job must be parsed before planned', this._newDefinitionJSON);
|
||||
return this.store.adapterFor('job').plan(this);
|
||||
},
|
||||
|
||||
run() {
|
||||
assert('A job must be parsed before ran', this.get('_newDefinitionJSON'));
|
||||
assert('A job must be parsed before ran', this._newDefinitionJSON);
|
||||
return this.store.adapterFor('job').run(this);
|
||||
},
|
||||
|
||||
update() {
|
||||
assert('A job must be parsed before updated', this.get('_newDefinitionJSON'));
|
||||
assert('A job must be parsed before updated', this._newDefinitionJSON);
|
||||
return this.store.adapterFor('job').update(this);
|
||||
},
|
||||
|
||||
parse() {
|
||||
const definition = this.get('_newDefinition');
|
||||
const definition = this._newDefinition;
|
||||
let promise;
|
||||
|
||||
try {
|
||||
|
@ -221,7 +221,7 @@ export default Model.extend({
|
|||
this.set('_newDefinitionJSON', json);
|
||||
|
||||
// You can't set the ID of a record that already exists
|
||||
if (this.get('isNew')) {
|
||||
if (this.isNew) {
|
||||
this.setIdByPayload(json);
|
||||
}
|
||||
|
||||
|
@ -231,7 +231,7 @@ export default Model.extend({
|
|||
// in anyway, the parse endpoint will throw an error.
|
||||
promise = this.store
|
||||
.adapterFor('job')
|
||||
.parse(this.get('_newDefinition'))
|
||||
.parse(this._newDefinition)
|
||||
.then(response => {
|
||||
this.set('_newDefinitionJSON', response);
|
||||
this.setIdByPayload(response);
|
||||
|
@ -255,7 +255,7 @@ export default Model.extend({
|
|||
},
|
||||
|
||||
resetId() {
|
||||
this.set('id', JSON.stringify([this.get('plainId'), this.get('namespace.name') || 'default']));
|
||||
this.set('id', JSON.stringify([this.plainId, this.get('namespace.name') || 'default']));
|
||||
},
|
||||
|
||||
statusClass: computed('status', function() {
|
||||
|
@ -265,13 +265,13 @@ export default Model.extend({
|
|||
dead: 'is-light',
|
||||
};
|
||||
|
||||
return classMap[this.get('status')] || 'is-dark';
|
||||
return classMap[this.status] || 'is-dark';
|
||||
}),
|
||||
|
||||
payload: attr('string'),
|
||||
decodedPayload: computed('payload', function() {
|
||||
// Lazily decode the base64 encoded payload
|
||||
return window.atob(this.get('payload') || '');
|
||||
return window.atob(this.payload || '');
|
||||
}),
|
||||
|
||||
// An arbitrary HCL or JSON string that is used by the serializer to plan
|
||||
|
|
|
@ -9,7 +9,7 @@ export default Fragment.extend({
|
|||
attributes: attr(),
|
||||
|
||||
attributesStructured: computed('attributes', function() {
|
||||
const original = this.get('attributes');
|
||||
const original = this.attributes;
|
||||
|
||||
if (!original) {
|
||||
return;
|
||||
|
@ -30,6 +30,6 @@ export default Fragment.extend({
|
|||
//
|
||||
// ex: nodeAttrs.get('driver.docker')
|
||||
// [ "1", { version: "17.05.0-ce", volumes: { enabled: "1" } } ]
|
||||
return get(this.get('attributesStructured'), key);
|
||||
return get(this.attributesStructured, key);
|
||||
},
|
||||
});
|
||||
|
|
|
@ -11,7 +11,7 @@ export default Fragment.extend({
|
|||
|
||||
attributesShort: computed('name', 'attributes.attributesStructured', function() {
|
||||
const attributes = this.get('attributes.attributesStructured');
|
||||
return get(attributes, `driver.${this.get('name')}`);
|
||||
return get(attributes, `driver.${this.name}`);
|
||||
}),
|
||||
|
||||
name: attr('string'),
|
||||
|
@ -21,6 +21,6 @@ export default Fragment.extend({
|
|||
updateTime: attr('date'),
|
||||
|
||||
healthClass: computed('healthy', function() {
|
||||
return this.get('healthy') ? 'running' : 'failed';
|
||||
return this.healthy ? 'running' : 'failed';
|
||||
}),
|
||||
});
|
||||
|
|
|
@ -31,15 +31,15 @@ export default Model.extend({
|
|||
isEligible: equal('schedulingEligibility', 'eligible'),
|
||||
|
||||
address: computed('httpAddr', function() {
|
||||
return ipParts(this.get('httpAddr')).address;
|
||||
return ipParts(this.httpAddr).address;
|
||||
}),
|
||||
|
||||
port: computed('httpAddr', function() {
|
||||
return ipParts(this.get('httpAddr')).port;
|
||||
return ipParts(this.httpAddr).port;
|
||||
}),
|
||||
|
||||
isPartial: computed('httpAddr', function() {
|
||||
return this.get('httpAddr') == null;
|
||||
return this.httpAddr == null;
|
||||
}),
|
||||
|
||||
allocations: hasMany('allocations', { inverse: 'node' }),
|
||||
|
@ -48,20 +48,20 @@ export default Model.extend({
|
|||
events: fragmentArray('node-event'),
|
||||
|
||||
detectedDrivers: computed('drivers.@each.detected', function() {
|
||||
return this.get('drivers').filterBy('detected');
|
||||
return this.drivers.filterBy('detected');
|
||||
}),
|
||||
|
||||
unhealthyDrivers: computed('detectedDrivers.@each.healthy', function() {
|
||||
return this.get('detectedDrivers').filterBy('healthy', false);
|
||||
return this.detectedDrivers.filterBy('healthy', false);
|
||||
}),
|
||||
|
||||
unhealthyDriverNames: computed('unhealthyDrivers.@each.name', function() {
|
||||
return this.get('unhealthyDrivers').mapBy('name');
|
||||
return this.unhealthyDrivers.mapBy('name');
|
||||
}),
|
||||
|
||||
// A status attribute that includes states not included in node status.
|
||||
// Useful for coloring and sorting nodes
|
||||
compositeStatus: computed('status', 'isEligible', function() {
|
||||
return this.get('isEligible') ? this.get('status') : 'ineligible';
|
||||
return this.isEligible ? this.status : 'ineligible';
|
||||
}),
|
||||
});
|
||||
|
|
|
@ -15,13 +15,13 @@ export default Fragment.extend({
|
|||
tasks: fragmentArray('task'),
|
||||
|
||||
drivers: computed('tasks.@each.driver', function() {
|
||||
return this.get('tasks')
|
||||
return this.tasks
|
||||
.mapBy('driver')
|
||||
.uniq();
|
||||
}),
|
||||
|
||||
allocations: computed('job.allocations.@each.taskGroup', function() {
|
||||
return maybe(this.get('job.allocations')).filterBy('taskGroupName', this.get('name'));
|
||||
return maybe(this.get('job.allocations')).filterBy('taskGroupName', this.name);
|
||||
}),
|
||||
|
||||
reservedCPU: sumAggregation('tasks', 'reservedCPU'),
|
||||
|
@ -32,7 +32,7 @@ export default Fragment.extend({
|
|||
|
||||
placementFailures: computed('job.latestFailureEvaluation.failedTGAllocs.[]', function() {
|
||||
const placementFailures = this.get('job.latestFailureEvaluation.failedTGAllocs');
|
||||
return placementFailures && placementFailures.findBy('name', this.get('name'));
|
||||
return placementFailures && placementFailures.findBy('name', this.name);
|
||||
}),
|
||||
|
||||
queuedOrStartingAllocs: computed('summary.{queuedAllocs,startingAllocs}', function() {
|
||||
|
@ -40,6 +40,6 @@ export default Fragment.extend({
|
|||
}),
|
||||
|
||||
summary: computed('job.taskGroupSummaries.[]', function() {
|
||||
return maybe(this.get('job.taskGroupSummaries')).findBy('name', this.get('name'));
|
||||
return maybe(this.get('job.taskGroupSummaries')).findBy('name', this.name);
|
||||
}),
|
||||
});
|
||||
|
|
|
@ -18,7 +18,7 @@ export default Fragment.extend({
|
|||
|
||||
task: computed('allocation.taskGroup.tasks.[]', function() {
|
||||
const tasks = this.get('allocation.taskGroup.tasks');
|
||||
return tasks && tasks.findBy('name', this.get('name'));
|
||||
return tasks && tasks.findBy('name', this.name);
|
||||
}),
|
||||
|
||||
driver: alias('task.driver'),
|
||||
|
@ -41,6 +41,6 @@ export default Fragment.extend({
|
|||
failed: 'is-error',
|
||||
};
|
||||
|
||||
return classMap[this.get('state')] || 'is-dark';
|
||||
return classMap[this.state] || 'is-dark';
|
||||
}),
|
||||
});
|
||||
|
|
|
@ -9,7 +9,7 @@ import { jobCrumbs } from 'nomad-ui/utils/breadcrumb-utils';
|
|||
export default Route.extend(WithWatchers, {
|
||||
startWatchers(controller, model) {
|
||||
if (model) {
|
||||
controller.set('watcher', this.get('watch').perform(model));
|
||||
controller.set('watcher', this.watch.perform(model));
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -35,8 +35,8 @@ export default Route.extend({
|
|||
(queryParam && queryParam !== currentRegion) ||
|
||||
(!queryParam && currentRegion !== defaultRegion)
|
||||
) {
|
||||
this.get('system').reset();
|
||||
this.get('store').unloadAll();
|
||||
this.system.reset();
|
||||
this.store.unloadAll();
|
||||
}
|
||||
|
||||
this.set('system.activeRegion', queryParam || defaultRegion);
|
||||
|
|
|
@ -21,8 +21,8 @@ export default Route.extend(WithForbiddenState, {
|
|||
|
||||
model() {
|
||||
return RSVP.hash({
|
||||
nodes: this.get('store').findAll('node'),
|
||||
agents: this.get('store').findAll('agent'),
|
||||
nodes: this.store.findAll('node'),
|
||||
agents: this.store.findAll('agent'),
|
||||
}).catch(notifyForbidden(this));
|
||||
},
|
||||
});
|
||||
|
|
|
@ -31,8 +31,8 @@ export default Route.extend(WithWatchers, {
|
|||
|
||||
startWatchers(controller, model) {
|
||||
if (model) {
|
||||
controller.set('watchModel', this.get('watch').perform(model));
|
||||
controller.set('watchAllocations', this.get('watchAllocations').perform(model));
|
||||
controller.set('watchModel', this.watch.perform(model));
|
||||
controller.set('watchAllocations', this.watchAllocations.perform(model));
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ import WithWatchers from 'nomad-ui/mixins/with-watchers';
|
|||
|
||||
export default Route.extend(WithWatchers, {
|
||||
startWatchers(controller) {
|
||||
controller.set('watcher', this.get('watch').perform());
|
||||
controller.set('watcher', this.watch.perform());
|
||||
},
|
||||
|
||||
watch: watchAll('node'),
|
||||
|
|
|
@ -6,7 +6,7 @@ export default Route.extend({
|
|||
emberFreestyle: service(),
|
||||
|
||||
beforeModel() {
|
||||
let emberFreestyle = this.get('emberFreestyle');
|
||||
let emberFreestyle = this.emberFreestyle;
|
||||
|
||||
return emberFreestyle.ensureHljs().then(() => {
|
||||
return RSVP.all([
|
||||
|
|
|
@ -30,7 +30,7 @@ export default Route.extend(WithForbiddenState, {
|
|||
},
|
||||
|
||||
model() {
|
||||
return this.get('store')
|
||||
return this.store
|
||||
.findAll('job', { reload: true })
|
||||
.catch(notifyForbidden(this));
|
||||
},
|
||||
|
|
|
@ -5,7 +5,7 @@ import WithWatchers from 'nomad-ui/mixins/with-watchers';
|
|||
|
||||
export default Route.extend(WithWatchers, {
|
||||
startWatchers(controller) {
|
||||
controller.set('modelWatch', this.get('watch').perform());
|
||||
controller.set('modelWatch', this.watch.perform());
|
||||
},
|
||||
|
||||
watch: watchAll('job'),
|
||||
|
|
|
@ -18,7 +18,7 @@ export default Route.extend({
|
|||
const namespace = transition.queryParams.namespace || this.get('system.activeNamespace.id');
|
||||
const name = params.job_name;
|
||||
const fullId = JSON.stringify([name, namespace || 'default']);
|
||||
return this.get('store')
|
||||
return this.store
|
||||
.findRecord('job', fullId, { reload: true })
|
||||
.then(job => {
|
||||
return RSVP.all([job.get('allocations'), job.get('evaluations')]).then(() => job);
|
||||
|
|
|
@ -11,7 +11,7 @@ export default Route.extend(WithWatchers, {
|
|||
|
||||
startWatchers(controller, model) {
|
||||
if (model) {
|
||||
controller.set('watchAllocations', this.get('watchAllocations').perform(model));
|
||||
controller.set('watchAllocations', this.watchAllocations.perform(model));
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ export default Route.extend({
|
|||
|
||||
resetController(controller, isExiting) {
|
||||
if (isExiting) {
|
||||
const job = controller.get('job');
|
||||
const job = controller.job;
|
||||
job.rollbackAttributes();
|
||||
job.resetId();
|
||||
controller.set('isEditing', false);
|
||||
|
|
|
@ -12,8 +12,8 @@ export default Route.extend(WithWatchers, {
|
|||
|
||||
startWatchers(controller, model) {
|
||||
if (model) {
|
||||
controller.set('watchDeployments', this.get('watchDeployments').perform(model));
|
||||
controller.set('watchVersions', this.get('watchVersions').perform(model));
|
||||
controller.set('watchDeployments', this.watchDeployments.perform(model));
|
||||
controller.set('watchVersions', this.watchVersions.perform(model));
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ export default Route.extend(WithWatchers, {
|
|||
|
||||
startWatchers(controller, model) {
|
||||
if (model) {
|
||||
controller.set('watchEvaluations', this.get('watchEvaluations').perform(model));
|
||||
controller.set('watchEvaluations', this.watchEvaluations.perform(model));
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -9,13 +9,13 @@ export default Route.extend(WithWatchers, {
|
|||
return;
|
||||
}
|
||||
controller.set('watchers', {
|
||||
model: this.get('watch').perform(model),
|
||||
summary: this.get('watchSummary').perform(model.get('summary')),
|
||||
allocations: this.get('watchAllocations').perform(model),
|
||||
evaluations: this.get('watchEvaluations').perform(model),
|
||||
model: this.watch.perform(model),
|
||||
summary: this.watchSummary.perform(model.get('summary')),
|
||||
allocations: this.watchAllocations.perform(model),
|
||||
evaluations: this.watchEvaluations.perform(model),
|
||||
latestDeployment:
|
||||
model.get('supportsDeployments') && this.get('watchLatestDeployment').perform(model),
|
||||
list: model.get('hasChildren') && this.get('watchAll').perform(),
|
||||
model.get('supportsDeployments') && this.watchLatestDeployment.perform(model),
|
||||
list: model.get('hasChildren') && this.watchAll.perform(),
|
||||
});
|
||||
},
|
||||
|
||||
|
|
|
@ -55,9 +55,9 @@ export default Route.extend(WithWatchers, {
|
|||
if (model) {
|
||||
const job = model.get('job');
|
||||
controller.set('watchers', {
|
||||
job: this.get('watchJob').perform(job),
|
||||
summary: this.get('watchSummary').perform(job.get('summary')),
|
||||
allocations: this.get('watchAllocations').perform(job),
|
||||
job: this.watchJob.perform(job),
|
||||
summary: this.watchSummary.perform(job.get('summary')),
|
||||
allocations: this.watchAllocations.perform(job),
|
||||
});
|
||||
}
|
||||
},
|
||||
|
|
|
@ -11,7 +11,7 @@ export default Route.extend(WithWatchers, {
|
|||
|
||||
startWatchers(controller, model) {
|
||||
if (model) {
|
||||
controller.set('watcher', this.get('watchVersions').perform(model));
|
||||
controller.set('watcher', this.watchVersions.perform(model));
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -13,14 +13,14 @@ export default Route.extend({
|
|||
],
|
||||
|
||||
model() {
|
||||
return this.get('store').createRecord('job', {
|
||||
return this.store.createRecord('job', {
|
||||
namespace: this.get('system.activeNamespace'),
|
||||
});
|
||||
},
|
||||
|
||||
resetController(controller, isExiting) {
|
||||
if (isExiting) {
|
||||
controller.get('model').deleteRecord();
|
||||
controller.model.deleteRecord();
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
|
@ -21,8 +21,8 @@ export default Route.extend(WithForbiddenState, {
|
|||
|
||||
model() {
|
||||
return RSVP.hash({
|
||||
nodes: this.get('store').findAll('node'),
|
||||
agents: this.get('store').findAll('agent'),
|
||||
nodes: this.store.findAll('node'),
|
||||
agents: this.store.findAll('agent'),
|
||||
}).catch(notifyForbidden(this));
|
||||
},
|
||||
});
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import { copy } from '@ember/object/internals';
|
||||
import { copy } from 'ember-copy';
|
||||
import { get } from '@ember/object';
|
||||
import { makeArray } from '@ember/array';
|
||||
import JSONSerializer from 'ember-data/serializers/json';
|
||||
import { pluralize, singularize } from 'ember-inflector';
|
||||
import removeRecord from '../utils/remove-record';
|
||||
|
||||
export default JSONSerializer.extend({
|
||||
|
@ -12,11 +13,10 @@ export default JSONSerializer.extend({
|
|||
},
|
||||
|
||||
keyForRelationship(attr, relationshipType) {
|
||||
const key = `${attr
|
||||
.singularize()
|
||||
const key = `${singularize(attr)
|
||||
.camelize()
|
||||
.capitalize()}ID`;
|
||||
return relationshipType === 'hasMany' ? key.pluralize() : key;
|
||||
return relationshipType === 'hasMany' ? pluralize(key) : key;
|
||||
},
|
||||
|
||||
// Modeled after the pushPayload for ember-data/serializers/rest
|
||||
|
@ -68,6 +68,6 @@ export default JSONSerializer.extend({
|
|||
},
|
||||
|
||||
modelNameFromPayloadKey(key) {
|
||||
return key.dasherize().singularize();
|
||||
return singularize(key.dasherize());
|
||||
},
|
||||
});
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { copy } from '@ember/object/internals';
|
||||
import { copy } from 'ember-copy';
|
||||
import ApplicationSerializer from './application';
|
||||
|
||||
export default ApplicationSerializer.extend({
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { copy } from '@ember/object/internals';
|
||||
import { copy } from 'ember-copy';
|
||||
import ApplicationSerializer from './application';
|
||||
|
||||
export default ApplicationSerializer.extend({
|
||||
|
|
|
@ -22,14 +22,14 @@ export default Service.extend({
|
|||
|
||||
// Routes can reset the breadcrumb trail to start anew even
|
||||
// if the route is deeply nested.
|
||||
if (route.get('resetBreadcrumbs')) {
|
||||
if (route.resetBreadcrumbs) {
|
||||
crumbs = [];
|
||||
}
|
||||
|
||||
// Breadcrumbs are either an array of static crumbs
|
||||
// or a function that returns breadcrumbs given the current
|
||||
// model for the route's controller.
|
||||
let breadcrumbs = route.get('breadcrumbs') || [];
|
||||
let breadcrumbs = route.breadcrumbs || [];
|
||||
if (typeof breadcrumbs === 'function') {
|
||||
breadcrumbs = breadcrumbs(route.get('controller.model')) || [];
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ export default Service.extend({
|
|||
}
|
||||
|
||||
const tracker = Constructor.create({
|
||||
fetch: url => this.get('token').authorizedRequest(url),
|
||||
fetch: url => this.token.authorizedRequest(url),
|
||||
[resourceProp]: resource,
|
||||
});
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ export default Service.extend({
|
|||
store: service(),
|
||||
|
||||
leader: computed('activeRegion', function() {
|
||||
const token = this.get('token');
|
||||
const token = this.token;
|
||||
|
||||
return PromiseObject.create({
|
||||
promise: token
|
||||
|
@ -26,7 +26,7 @@ export default Service.extend({
|
|||
}),
|
||||
|
||||
defaultRegion: computed(function() {
|
||||
const token = this.get('token');
|
||||
const token = this.token;
|
||||
return PromiseObject.create({
|
||||
promise: token
|
||||
.authorizedRawRequest(`/${namespace}/agent/members`)
|
||||
|
@ -38,7 +38,7 @@ export default Service.extend({
|
|||
}),
|
||||
|
||||
regions: computed(function() {
|
||||
const token = this.get('token');
|
||||
const token = this.token;
|
||||
|
||||
return PromiseArray.create({
|
||||
promise: token.authorizedRawRequest(`/${namespace}/regions`).then(jsonWithDefault([])),
|
||||
|
@ -47,7 +47,7 @@ export default Service.extend({
|
|||
|
||||
activeRegion: computed('regions.[]', {
|
||||
get() {
|
||||
const regions = this.get('regions');
|
||||
const regions = this.regions;
|
||||
const region = window.localStorage.nomadActiveRegion;
|
||||
|
||||
if (regions.includes(region)) {
|
||||
|
@ -78,30 +78,28 @@ export default Service.extend({
|
|||
'defaultRegion.region',
|
||||
'shouldShowRegions',
|
||||
function() {
|
||||
return (
|
||||
this.get('shouldShowRegions') &&
|
||||
this.get('activeRegion') !== this.get('defaultRegion.region')
|
||||
);
|
||||
return this.shouldShowRegions &&
|
||||
this.activeRegion !== this.get('defaultRegion.region');
|
||||
}
|
||||
),
|
||||
|
||||
namespaces: computed('activeRegion', function() {
|
||||
return PromiseArray.create({
|
||||
promise: this.get('store')
|
||||
promise: this.store
|
||||
.findAll('namespace')
|
||||
.then(namespaces => namespaces.compact()),
|
||||
});
|
||||
}),
|
||||
|
||||
shouldShowNamespaces: computed('namespaces.[]', function() {
|
||||
const namespaces = this.get('namespaces').toArray();
|
||||
const namespaces = this.namespaces.toArray();
|
||||
return namespaces.length && namespaces.some(namespace => namespace.get('id') !== 'default');
|
||||
}),
|
||||
|
||||
activeNamespace: computed('namespaces.[]', {
|
||||
get() {
|
||||
const namespaceId = window.localStorage.nomadActiveNamespace || 'default';
|
||||
const namespace = this.get('namespaces').findBy('id', namespaceId);
|
||||
const namespace = this.namespaces.findBy('id', namespaceId);
|
||||
|
||||
if (namespace) {
|
||||
return namespace;
|
||||
|
@ -110,14 +108,14 @@ export default Service.extend({
|
|||
// If the namespace in localStorage is no longer in the cluster, it needs to
|
||||
// be cleared from localStorage
|
||||
window.localStorage.removeItem('nomadActiveNamespace');
|
||||
return this.get('namespaces').findBy('id', 'default');
|
||||
return this.namespaces.findBy('id', 'default');
|
||||
},
|
||||
set(key, value) {
|
||||
if (value == null) {
|
||||
window.localStorage.removeItem('nomadActiveNamespace');
|
||||
} else if (typeof value === 'string') {
|
||||
window.localStorage.nomadActiveNamespace = value;
|
||||
return this.get('namespaces').findBy('id', value);
|
||||
return this.namespaces.findBy('id', value);
|
||||
} else {
|
||||
window.localStorage.nomadActiveNamespace = value.get('name');
|
||||
return value;
|
||||
|
|
|
@ -29,7 +29,7 @@ export default Service.extend({
|
|||
// param since the region cannot be known at this point.
|
||||
authorizedRawRequest(url, options = { credentials: 'include' }) {
|
||||
const headers = {};
|
||||
const token = this.get('secret');
|
||||
const token = this.secret;
|
||||
|
||||
if (token) {
|
||||
headers['X-Nomad-Token'] = token;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { readOnly } from '@ember/object/computed';
|
||||
import { copy } from '@ember/object/internals';
|
||||
import { copy } from 'ember-copy';
|
||||
import Service from '@ember/service';
|
||||
|
||||
let list = {};
|
||||
|
|
|
@ -65,7 +65,7 @@
|
|||
<td data-test-task-address-is-dynamic>{{if row.model.isDynamic "Yes" "No"}}</td>
|
||||
<td data-test-task-address-name>{{row.model.name}}</td>
|
||||
<td data-test-task-address-address>
|
||||
<a href="http://{{network.ip}}:{{row.model.port}}" target="_blank">
|
||||
<a href="http://{{network.ip}}:{{row.model.port}}" target="_blank" rel="noopener noreferrer">
|
||||
{{network.ip}}:{{row.model.port}}
|
||||
</a>
|
||||
</td>
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
{{#freestyle-usage "accordion" title="Accordion"}}
|
||||
{{#list-accordion source=products key="name" as |a|}}
|
||||
{{#a.head buttonLabel="details"}}
|
||||
{{#list-accordion source=products key="name" as |ac|}}
|
||||
{{#ac.head buttonLabel="details"}}
|
||||
<div class="columns inline-definitions">
|
||||
<div class="column is-1">{{a.item.name}}</div>
|
||||
<div class="column is-1">{{ac.item.name}}</div>
|
||||
<div class="column is-1">
|
||||
<span class="bumper-left badge is-light">{{a.item.lang}}</span>
|
||||
<span class="bumper-left badge is-light">{{ac.item.lang}}</span>
|
||||
</div>
|
||||
</div>
|
||||
{{/a.head}}
|
||||
{{#a.body}}
|
||||
<h1 class="title is-4">{{a.item.name}}</h1>
|
||||
<p>{{a.item.desc}}</p>
|
||||
<p><a href="{{a.item.link}}">Learn more...</a></p>
|
||||
{{/a.body}}
|
||||
{{/ac.head}}
|
||||
{{#ac.body}}
|
||||
<h1 class="title is-4">{{ac.item.name}}</h1>
|
||||
<p>{{ac.item.desc}}</p>
|
||||
<p><a href="{{ac.item.link}}">Learn more...</a></p>
|
||||
{{/ac.body}}
|
||||
{{/list-accordion}}
|
||||
{{/freestyle-usage}}
|
||||
|
||||
|
|
|
@ -25,13 +25,13 @@
|
|||
{{#each network.reservedPorts as |port|}}
|
||||
<li data-test-port>
|
||||
<strong>{{port.Label}}:</strong>
|
||||
<a href="http://{{network.ip}}:{{port.Value}}" target="_blank">{{network.ip}}:{{port.Value}}</a>
|
||||
<a href="http://{{network.ip}}:{{port.Value}}" target="_blank" rel="noopener noreferrer">{{network.ip}}:{{port.Value}}</a>
|
||||
</li>
|
||||
{{/each}}
|
||||
{{#each network.dynamicPorts as |port|}}
|
||||
<li>
|
||||
<strong>{{port.Label}}:</strong>
|
||||
<a href="http://{{network.ip}}:{{port.Value}}" target="_blank">{{network.ip}}:{{port.Value}}</a>
|
||||
<a href="http://{{network.ip}}:{{port.Value}}" target="_blank" rel="noopener noreferrer">{{network.ip}}:{{port.Value}}</a>
|
||||
</li>
|
||||
{{/each}}
|
||||
{{/with}}
|
||||
|
|
|
@ -16,7 +16,7 @@ export default Mixin.create({
|
|||
endOffset: null,
|
||||
|
||||
offsetParams: computed('endOffset', function() {
|
||||
const endOffset = this.get('endOffset');
|
||||
const endOffset = this.endOffset;
|
||||
return endOffset
|
||||
? { origin: 'start', offset: endOffset }
|
||||
: { origin: 'end', offset: MAX_OUTPUT_LENGTH };
|
||||
|
@ -26,8 +26,8 @@ export default Mixin.create({
|
|||
|
||||
fullUrl: computed('url', 'params', 'offsetParams', 'additionalParams', function() {
|
||||
const queryParams = queryString.stringify(
|
||||
assign({}, this.get('params'), this.get('offsetParams'), this.get('additionalParams'))
|
||||
assign({}, this.params, this.offsetParams, this.additionalParams)
|
||||
);
|
||||
return `${this.get('url')}?${queryParams}`;
|
||||
return `${this.url}?${queryParams}`;
|
||||
}),
|
||||
});
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue