Move machine into host

This commit is contained in:
Vincent Fiduccia 2016-09-30 17:04:17 -07:00
parent 67dbd04fc7
commit 4666d3d422
42 changed files with 121 additions and 288 deletions

View File

@ -12,7 +12,7 @@ export default Ember.Route.extend({
// Check for waiting only if cattle, because other orchestrations have system services menus that link here
if ( !project.get('kubernetes') && !project.get('swarm') && !project.get('mesos') )
{
return this.get('projects').checkForWaiting(auth.get('hosts'),auth.get('machines'));
return this.get('projects').checkForWaiting(auth.get('hosts'));
}
},

View File

@ -24,8 +24,8 @@ export default Ember.Controller.extend({
}.property('model.stacks.@each.externalId'),
hasHosts: function() {
return (this.get('model.hosts.length') > 0) || (this.get('model.machines.length') > 0);
}.property('model.{hosts,machines}'),
return (this.get('model.hosts.length') > 0);
}.property('model.hosts.length'),
isReady: function() {
return this.get('projects.isReady') && this.get('hasHosts');

View File

@ -10,8 +10,8 @@ export default Ember.Controller.extend({
}.property('projects.current.mesos'),
hasHosts: function() {
return (this.get('model.hosts.length') + this.get('model.machines.length')) >= this.get('expectHosts');
}.property('model.hosts.length','model.machines.length'),
return this.get('model.hosts.length') >= this.get('expectHosts');
}.property('model.hosts.length'),
actions: {
kubernetesReady() {

View File

@ -22,7 +22,7 @@ export default Ember.Route.extend({
this.replaceWith('authenticated.project.index');
}
}
else if ( (model.get('hosts.length') + model.get('machines.length')) > 0 && this.get('projects.isReady') )
else if ( model.get('hosts.length') > 0 && this.get('projects.isReady') )
{
this.replaceWith('authenticated.project.index');
}

View File

@ -54,7 +54,6 @@ export default Ember.Route.extend(Subscribe, {
projectSchemas: ['project', this.toCb('loadProjectSchemas')],
orchestrationState: ['projectSchemas', this.toCb('updateOrchestration')],
instances: ['projectSchemas', this.cbFind('instance')],
machines: ['projectSchemas', this.cbFind('machine')],
services: ['projectSchemas', this.cbFind('service')],
hosts: ['projectSchemas', this.cbFind('host')],
stacks: ['projectSchemas', this.cbFind('stack')],

View File

@ -1,6 +1,5 @@
<section class="horizontal-form container-fluid">
<h2>{{t 'editHost.title'}}</h2>
{{top-errors errors=errors}}
<div class="row form-group">
<div class="col-sm-12 col-md-2 form-label">
@ -44,4 +43,5 @@
</div>
</section>
{{top-errors errors=errors}}
{{save-cancel editing=editing save="save" cancel="cancel"}}

View File

@ -9,7 +9,6 @@ export default Ember.Component.extend(ManageLabels, GroupedInstances, {
show : null,
classNames : ['pod','host'],
classNameBindings : ['isMachine:machine-host'],
init() {
this._super(...arguments);
@ -40,12 +39,9 @@ export default Ember.Component.extend(ManageLabels, GroupedInstances, {
return this.get('filteredInstances').sortBy('name','id');
}.property('filteredInstances.@each.{name,id}'),
isMachine: Ember.computed.equal('model.type','machine'),
isActive: Ember.computed.equal('model.state','active'),
showAdd: function() {
return this.get('isActive') && !this.get('isMachine');
}.property('isActive','isMachine'),
isProvisioning: Ember.computed.equal('model.state','provisioning'),
showAdd: Ember.computed.alias('isActive'),
stateBackground: function() {
return this.get('model.stateColor').replace("text-","bg-");

View File

@ -4,33 +4,25 @@
<div class="pull-right">{{action-menu model=model}}</div>
</div>
<div class="pod-name">
{{#if isMachine}}
{{model.displayName}}
{{else}}
<a href="{{href-to 'host' model.id}}">{{model.displayName}}</a>
{{#if model.showTransitioningMessage}}
<div class="pod-message {{if model.isError 'text-danger' 'text-muted'}}">
{{model.transitioningMessage}}
</div>
{{/if}}
<a href="{{href-to 'host' model.id}}">{{model.displayName}}</a>
{{#if model.showTransitioningMessage}}
<div class="pod-message {{if model.isError 'text-danger' 'text-muted'}}">
{{model.transitioningMessage}}
</div>
{{/if}}
</div>
{{#if isMachine}}
{{#if isProvisioning}}
<div class="machine-info force-wrap">
{{#if isActive}}
{{format-html-message 'hostPod.machineInfo.active.activating'}}
{{else}}
{{#if model.isError}}
{{#if model.transitioningMessage}}
<span class="text-danger">{{model.transitioningMessage}}</span>
{{else}}
<span class="text-danger">{{t 'hostPod.machineInfo.deactivated.error'}}</span>
{{/if}}
{{#if model.isError}}
{{#if model.transitioningMessage}}
<span class="text-danger">{{model.transitioningMessage}}</span>
{{else}}
<div class="color:black;">{{t 'hostPod.machineInfo.deactivated.setup'}}</div>
{{model.transitioningMessage}}
<span class="text-danger">{{t 'hostPod.machineInfo.deactivated.error'}}</span>
{{/if}}
{{else}}
<div class="color:black;">{{t 'hostPod.machineInfo.deactivated.setup'}}</div>
{{model.transitioningMessage}}
{{/if}}
</div>
{{else}}
@ -58,8 +50,8 @@
{{/if}}
</div>
<div class="pod-info-container">
{{#if model.machine}}
<div class="pod-info-item"><i class="icon icon-cloud"></i> {{model.machine.driver}}</div>
{{#if model.driver}}
<div class="pod-info-item"><i class="icon icon-cloud"></i> {{model.driver}}</div>
{{/if}}
</div>
</div>

View File

@ -22,7 +22,7 @@ export default Ember.Component.extend(Driver, {
});
this.set('model', this.get('store').createRecord({
type: 'machine',
type: 'host',
aliyunecsConfig: config,
}));

View File

@ -127,7 +127,7 @@ export default Ember.Component.extend(Driver, {
});
this.set('model', this.get('store').createRecord({
type : 'machine',
type : 'host',
amazonec2Config : config,
}));
},

View File

@ -35,7 +35,7 @@ export default Ember.Component.extend(Driver, {
});
this.set('model', this.get('store').createRecord({
type: 'machine',
type: 'host',
azureConfig: config,
}));

View File

@ -1,6 +1,7 @@
import Ember from 'ember';
import Driver from 'ui/mixins/driver';
import fetch from 'ember-api-store/utils/fetch';
import Util from 'ui/utils/util';
const DIGITALOCEAN_API = 'api.digitalocean.com/v2';
const VALID_IMAGES = [
@ -81,7 +82,7 @@ export default Ember.Component.extend(Driver, {
}, (err) => {
let errors = this.get('errors') || [];
errors.push(`${err.xhr.status}: ${err.err}`);
errors.push(`${err.statusText}: ${err.body.message}`);
this.setProperties({
errors: errors,
@ -102,7 +103,7 @@ export default Ember.Component.extend(Driver, {
});
this.set('model', this.get('store').createRecord({
type: 'machine',
type: 'host',
digitaloceanConfig: config,
}));
},
@ -135,19 +136,19 @@ export default Ember.Component.extend(Driver, {
return true;
},
apiRequest: function(command, params, method='GET') {
apiRequest: function(command, params) {
let proxyEndpoint = this.get('app.proxyEndpoint');
let url = `${proxyEndpoint}/${DIGITALOCEAN_API}/${command}?per_page=100`;
url = Util.addQueryParams(url,params);
let accessToken = this.get('model.digitaloceanConfig.accessToken');
return fetch({
url: url,
method: method,
header: {
return fetch(url, {
headers: {
'Accept': 'application/json',
'X-Api-Auth-Header': 'Bearer ' + accessToken
},
data: params,
}, true);
}).then((res) => {
return res.body;
});
}
});

View File

@ -76,7 +76,7 @@ export default Ember.Component.extend(Driver, {
});
this.set('model', this.get('store').createRecord({
type: 'machine',
type: 'host',
exoscaleConfig: config
}));
},

View File

@ -21,7 +21,7 @@ export default Ember.Component.extend(Driver, {
bootstrap() {
let model = this.get('store').createRecord({
type: 'machine',
type: 'host',
});
this.setProperties({
@ -47,14 +47,14 @@ export default Ember.Component.extend(Driver, {
driverChanged: function() {
let driver = this.get('otherDriver');
let machine = this.get('model');
let host = this.get('model');
if ( driver && machine) {
if ( !machine.get(driver) ) {
machine.set(driver, this.get('store').createRecord({ type: driver }));
if ( driver && host) {
if ( !host.get(driver) ) {
host.set(driver, this.get('store').createRecord({ type: driver }));
}
this.set('driverOpts', machine.get(driver));
this.set('driverOpts', host.get(driver));
}
else {
this.set('otherDriver', this.get('otherChoices.firstObject.value'));
@ -73,11 +73,11 @@ export default Ember.Component.extend(Driver, {
willSave() {
// Null out all the drivers that aren't the active one, because the API only accepts one.
let activeDriver = this.get('otherDriver');
let machine = this.get('model');
let host = this.get('model');
this.get('otherChoices').forEach((choice) => {
let cur = choice.value;
if ( choice.value !== activeDriver ) {
machine.set(cur, null);
host.set(cur, null);
}
});

View File

@ -28,7 +28,7 @@ export default Ember.Component.extend(Driver, {
});
this.set('model', store.createRecord({
type: 'machine',
type: 'host',
packetConfig: config,
}));
}

View File

@ -62,7 +62,7 @@ export default Ember.Component.extend(Driver, {
});
this.set('model', this.get('store').createRecord({
type: 'machine',
type: 'host',
rackspaceConfig: config,
}));
},

View File

@ -30,7 +30,7 @@ export default Ember.Component.extend(Driver, {
});
this.set('model', store.createRecord({
type: 'machine',
type: 'host',
ubiquityConfig: config,
}));
},

View File

@ -17,7 +17,7 @@ export default Ember.Component.extend(Driver, {
});
this.set('model', this.get('store').createRecord({
type: 'machine',
type: 'host',
vmwarevsphereConfig: config,
engineInstallUrl: '',
}));

View File

@ -39,7 +39,7 @@ export default Ember.Component.extend({
this.set('subStep', 0);
this.set('subCount', 0);
if ( (this.get('model.hosts.length') + this.get('model.machines.length')) === 0 )
if ( this.get('model.hosts.length') === 0 )
{
this.set('currentStep', 0);
return;

View File

@ -37,7 +37,7 @@ export default Ember.Component.extend({
this.set('subStep', 0);
this.set('subCount', 0);
if ( (this.get('model.hosts.length') + this.get('model.machines.length')) < 3 )
if ( this.get('model.hosts.length') < 3 )
{
this.set('currentStep', 0);
return;

View File

@ -31,7 +31,7 @@ export default Ember.Component.extend({
this.set('subStep', 0);
this.set('subCount', 0);
if ( (this.get('model.hosts.length') + this.get('model.machines.length')) === 0 )
if ( this.get('model.hosts.length') === 0 )
{
this.set('currentStep', 0);
return;

View File

@ -80,8 +80,8 @@
<div>
<label>{{t 'hostsPage.hostPage.infoMultiStats.provider.labelText'}}</label>
{{#if host.machine}}
<div>{{host.machine.driver}}</div>
{{#if host.driver}}
<div>{{host.driver}}</div>
{{else}}
<div class="text-muted">{{t 'hostsPage.hostPage.infoMultiStats.provider.noHost'}}</div>
{{/if}}

View File

@ -23,31 +23,6 @@ export default Ember.Controller.extend({
this.set('show', (this.get('showSystem') ? 'all' : 'standard'));
}.observes('showSystem'),
pods: function() {
var out = [];
var hosts = this.get('model.hosts');
var machines = this.get('model.machines');
var knownMachines = hosts.map((host) => { return host.get('physicalHostId'); }).uniq();
out.pushObjects(hosts.toArray());
// Copy in the pending machines
machines.forEach((machine) => {
if ( machine.get('isPending') && knownMachines.indexOf(machine.get('id')) === -1 )
{
out.pushObject(Ember.Object.create({
isPendingMachine: true,
machine: machine,
name: machine.get('name'),
displayName: machine.get('name')
}));
}
});
return out.sortBy('displayName','id');
}.property('model.hosts.@each.{name,id,physicalHostId}','model.machines.@each.{name,id,isPending}'),
listLinkOptions: {
route: 'hosts',
options: {

View File

@ -2,16 +2,9 @@ import Ember from 'ember';
export default Ember.Route.extend({
model: function() {
var store = this.get('store');
var promises = [
store.find('machine'),
store.find('host'),
];
return Ember.RSVP.all(promises).then((results) => {
return this.get('store').findAll('host').then((hosts) => {
return {
machines: results[0],
hosts: results[1],
hosts: hosts,
};
});
},

View File

@ -15,10 +15,6 @@
</div>
</section>
{{#columns-section pods=pods emptyMessage=(t 'hostsPage.index.columns.emptyMessage') as |item| }}
{{#if item.isPendingMachine}}
{{host-pod model=item.machine mode=mode newContainer="newContainer"}}
{{else}}
{{host-pod model=item mode=mode newContainer="newContainer" show=show}}
{{/if}}
{{#columns-section pods=model.hosts emptyMessage=(t 'hostsPage.index.columns.emptyMessage') as |item| }}
{{host-pod model=item mode=mode newContainer="newContainer" show=show}}
{{/columns-section}}

View File

@ -3,18 +3,18 @@ import Ember from 'ember';
export default Ember.Controller.extend({
access: Ember.inject.service(),
queryParams : ['backTo', 'driver', 'machineId'],
queryParams : ['backTo', 'driver', 'hostId'],
backTo : null,
driver : null,
machineId : null,
hostId : null,
allowCustom : true,
allowOther : true,
actions: {
switchDriver(name) {
if (this.get('machineId')) {
this.set('machineId', null);
if (this.get('hostId')) {
this.set('hostId', null);
this.set('model.clonedModel', null);
}
this.set('driver', name);

View File

@ -28,7 +28,7 @@ export default Ember.Route.extend({
driver: {
refreshModel: true
},
machineId: {
hostId: {
refreshModel: false,
}
},
@ -65,7 +65,7 @@ export default Ember.Route.extend({
resetController(controller, isExisting /*, transition*/) {
if ( isExisting )
{
controller.set('machineId', null);
controller.set('hostId', null);
controller.set('backTo', null);
}
},

View File

@ -4,7 +4,6 @@ export default Ember.Route.extend({
model: function() {
var store = this.get('store');
return Ember.RSVP.hash({
machines: store.findAll('machine'),
hosts: store.findAll('host'),
instances: store.findAll('instance'),
}).then((hash) => {

View File

@ -9,7 +9,7 @@ export default Ember.Route.extend({
beforeModel() {
this._super(...arguments);
var auth = this.modelFor('authenticated');
return this.get('projects').checkForWaiting(auth.get('hosts'),auth.get('machines'));
return this.get('projects').checkForWaiting(auth.get('hosts'));
},
model() {

View File

@ -6,6 +6,6 @@ export default Ember.Route.extend({
beforeModel() {
this._super(...arguments);
var auth = this.modelFor('authenticated');
return this.get('projects').checkForWaiting(auth.get('hosts'),auth.get('machines'));
return this.get('projects').checkForWaiting(auth.get('hosts'));
},
});

View File

@ -177,7 +177,7 @@ export default Ember.Mixin.create({
var icon = '';
if ( trans === 'yes' )
{
icon = 'icon icon-spinner';
icon = 'icon icon-spinner icon-spin';
}
else if ( trans === 'error' )
{

View File

@ -292,7 +292,7 @@ export default Ember.Mixin.create({
labelsChanged: debouncedObserver('labelArray.@each.{type,key,value}', function() {
// Make a map of the keys we care about, and combine multiple values together
let map = {};
this.get('labelArray').forEach(function(row) {
(this.get('labelArray')||[]).forEach(function(row) {
let key = row.get('key') || '';
let type = row.get('type') || '';

View File

@ -30,8 +30,7 @@ var Host = Resource.extend({
},
clone: function() {
var machine = this.get('machine');
this.get('application').transitionToRoute('hosts.new', {queryParams: {machineId: machine.get('id'), driver: machine.get('driver')}});
this.get('application').transitionToRoute('hosts.new', {queryParams: {hostId: this.get('id'), driver: this.get('driver')}});
},
edit: function() {
@ -39,15 +38,11 @@ var Host = Resource.extend({
},
machineConfig: function() {
var machine = this.get('machine');
if ( machine )
var url = this.linkFor('config');
if ( url )
{
var url = machine.linkFor('config');
if ( url )
{
url = this.get('endpointSvc').addAuthParams(url);
Util.download(url);
}
url = this.get('endpointSvc').addAuthParams(url);
Util.download(url);
}
}
},
@ -64,34 +59,16 @@ var Host = Resource.extend({
{ label: 'action.viewInApi', icon: 'icon icon-external-link',action: 'goToApi', enabled: true},
];
if ( this.get('machine') )
if ( this.get('links.config') )
{
if ( this.get('machine.links.config') )
{
out.push({ label: 'action.machineConfig', icon: 'icon icon-download', action: 'machineConfig', enabled: true});
}
out.push({ label: 'action.clone', icon: 'icon icon-copy', action: 'clone', enabled: true });
out.push({ label: 'action.machineConfig', icon: 'icon icon-download', action: 'machineConfig', enabled: true});
}
out.push({ label: 'action.clone', icon: 'icon icon-copy', action: 'clone', enabled: true });
out.push({ label: 'action.edit', icon: 'icon icon-edit', action: 'edit', enabled: !!a.update });
return out;
}.property('actionLinks.{activate,deactivate,remove,purge,update}','machine','machine.links.config'),
state: function() {
var host = this.get('hostState');
var agent = this.get('agentState');
if ( host === 'active' && agent )
{
return agent;
}
else
{
return host;
}
}.property('hostState','agentState'),
}.property('actionLinks.{activate,deactivate,remove,purge,update}','links.config'),
displayIp: Ember.computed.alias('agentIpAddress'),
@ -99,19 +76,6 @@ var Host = Resource.extend({
return this.get('name') || this.get('hostname') || '('+this.get('id')+')';
}.property('name','hostname','id'),
//@TODO PERF
machine: function() {
var phid = this.get('physicalHostId');
if ( !phid )
{
return null;
}
var machine = this.get('store').getById('machine', phid);
return machine;
}.property('physicalHostId'),
//@TODO PERF
osBlurb: function() {
var out = this.get('info.osInfo.operatingSystem')||'';
@ -225,15 +189,10 @@ var Host = Resource.extend({
});
Host.reopenClass({
// Remap the host state to hostState so the regular state can be a computed combination of host+agent state.
mangleIn: function(data) {
data['hostState'] = data['state'];
delete data['state'];
return data;
},
defaultSortBy: 'name,hostname',
stateMap: {
'active': {icon: 'icon icon-host', color: 'text-success'},
'provisioning': {icon: 'icon icon-host', color: 'text-info'},
'reconnecting': {icon: 'icon icon-help', color: 'text-danger'},
}
});

View File

@ -1,79 +0,0 @@
import Resource from 'ember-api-store/models/resource';
import PolledResource from 'ui/mixins/cattle-polled-resource';
var pendingStates = [
'requested',
'bootstrapping',
'creating',
'created',
'erroring',
'error',
'updating'
];
var Machine = Resource.extend(PolledResource, {
type: 'machine',
reservedKeys: ['hostsUpdated','hosts','isPending'],
actions: {
clone: function() {
this.get('router').transitionTo('hosts.new', {queryParams: {machineId: this.get('id'), driver: this.get('driver')}});
},
},
availableActions: function() {
var a = this.get('actionLinks')||{};
var out = [
{ label: 'action.remove', icon: 'icon icon-trash', action: 'promptDelete', enabled: !!a.remove, altAction: 'delete'},
{ divider: true },
{ label: 'action.clone', icon: 'icon icon-copy', action: 'clone', enabled: true },
];
if ( this.hasLink('config') )
{
out.push({ label: 'action.machineConfig', icon: 'icon icon-download', action: 'machineConfig', enabled: true});
}
out.push({ label: 'action.viewInApi', icon: 'icon icon-external-link',action: 'goToApi', enabled: true});
return out;
}.property('actionLinks.remove', 'links.config'),
hostsUpdated: 0,
onHostChanged: function() {
this.incrementProperty('hostsUpdated');
}.observes('hosts.@each.{id,name,state}'),
isPending: function() {
if ( pendingStates.indexOf(this.get('state')) >= 0 )
{
return true;
}
else
{
return this.get('state') === 'active' && this.get('hosts.length') === 0;
}
}.property('state','hosts.[]','hostsUpdated'),
combinedState: function() {
let state = this.get('state');
if (state === 'active' )
{
return 'waiting';
}
else
{
return state;
}
}.property('state'),
});
Machine.reopenClass({
stateMap: {
'bootstrapping': {icon: 'icon icon-tag', color: 'text-info'},
'active': {icon: 'icon icon-tag', color: 'text-info'},
}
});
export default Machine;

View File

@ -459,7 +459,7 @@ Service.reopenClass({
return _allMaps.filterBy('serviceId', serviceId).map((map) => {
return Ember.Object.create({
name: map.get('name'),
service: getByServiceId(l('service:store'), map.get('consumedServiceId')), // @TODO
service: getByServiceId(window.l('service:store'), map.get('consumedServiceId')), // @TODO boooo
ports: map.get('ports')||[],
});
}).filter((obj) => {

View File

@ -20,7 +20,7 @@ export default Ember.Service.extend(CatalogResource, {
fetchCatalogs(auth) {
const store = this.get('store');
return this.get('projects').checkForWaiting(auth.get('hosts'),auth.get('machines')).then(() => {
return this.get('projects').checkForWaiting(auth.get('hosts')).then(() => {
return store.request({url: `${this.get('app.catalogEndpoint')}/catalogs`});
});
},

View File

@ -213,7 +213,7 @@ export default Ember.Service.extend({
);
}.property('orchestrationState'), // The state object is always completely replaced, so this is ok
checkForWaiting(hosts,machines) {
checkForWaiting(hosts) {
let router = getOwner(this).get('router');
let hasHosts = false;
@ -223,7 +223,7 @@ export default Ember.Service.extend({
}
else
{
hasHosts = (hosts && hosts.get('length') > 0) || (machines && machines.get('length') > 0);
hasHosts = (hosts && hosts.get('length') > 0);
}
if ( !hasHosts )

View File

@ -29,34 +29,34 @@
// Animated Icons
// --------------------------
.icon-spin {
-webkit-animation: icon-spin 2s infinite linear;
animation: icon-spin 2s infinite linear;
-webkit-animation: icon-spin 2s infinite steps(8);
animation: icon-spin 2s infinite steps(8);
}
.icon-pulse {
-webkit-animation: icon-spin 1s infinite steps(8);
animation: icon-spin 1s infinite steps(8);
}
//.icon-pulse {
// -webkit-animation: icon-spin 1s infinite steps(8);
// animation: icon-spin 1s infinite steps(8);
//}
@-webkit-keyframes icon-spin {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
-webkit-transform: rotateZ(0deg);
transform: rotateZ(0deg);
}
100% {
-webkit-transform: rotate(359deg);
transform: rotate(359deg);
-webkit-transform: rotateZ(360deg);
transform: rotateZ(360deg);
}
}
@keyframes icon-spin {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
-webkit-transform: rotateZ(0deg);
transform: rotateZ(0deg);
}
100% {
-webkit-transform: rotate(359deg);
transform: rotate(359deg);
-webkit-transform: rotateZ(360deg);
transform: rotateZ(360deg);
}
}

View File

@ -172,15 +172,15 @@
@-webkit-keyframes orbit {
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
-webkit-transform: rotateZ(360deg);
transform: rotateZ(360deg);
}
}
@keyframes orbit {
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
-webkit-transform: rotateZ(360deg);
transform: rotateZ(360deg);
}
}
@ -282,31 +282,31 @@
@-webkit-keyframes rotate {
0% {
-webkit-transform: rotate(0deg) scale(1);
transform: rotate(0deg) scale(1);
-webkit-transform: rotateZ(0deg) scale(1);
transform: rotateZ(0deg) scale(1);
}
50% {
-webkit-transform: rotate(180deg) scale(0.6);
transform: rotate(180deg) scale(0.6);
-webkit-transform: rotateZ(180deg) scale(0.6);
transform: rotateZ(180deg) scale(0.6);
}
100% {
-webkit-transform: rotate(360deg) scale(1);
transform: rotate(360deg) scale(1);
-webkit-transform: rotateZ(360deg) scale(1);
transform: rotateZ(360deg) scale(1);
}
}
@keyframes rotate {
0% {
-webkit-transform: rotate(0deg) scale(1);
transform: rotate(0deg) scale(1);
-webkit-transform: rotateZ(0deg) scale(1);
transform: rotateZ(0deg) scale(1);
}
50% {
-webkit-transform: rotate(180deg) scale(0.6);
transform: rotate(180deg) scale(0.6);
-webkit-transform: rotateZ(180deg) scale(0.6);
transform: rotateZ(180deg) scale(0.6);
}
100% {
-webkit-transform: rotate(360deg) scale(1);
transform: rotate(360deg) scale(1);
-webkit-transform: rotateZ(360deg) scale(1);
transform: rotateZ(360deg) scale(1);
}
}

View File

@ -7,6 +7,6 @@ export default ApplicationsTabRoute.extend({
beforeModel() {
this._super(...arguments);
var auth = this.modelFor('authenticated');
return this.get('projects').checkForWaiting(auth.get('hosts'),auth.get('machines'));
return this.get('projects').checkForWaiting(auth.get('hosts'));
},
});

View File

@ -83,9 +83,11 @@ export function addQueryParam(url, key, val) {
}
export function addQueryParams(url, params) {
Object.keys(params).forEach(function(key) {
url = addQueryParam(url, key, params[key]);
});
if ( params && typeof params === 'object' ) {
Object.keys(params).forEach(function(key) {
url = addQueryParam(url, key, params[key]);
});
}
return url;
}

View File

@ -23,7 +23,7 @@
"devDependencies": {
"ansi_up": "^1.3.0",
"broccoli-asset-rev": "^2.4.2",
"ember-api-store": "^2.0.0-dev7",
"ember-api-store": "^2.0.0-dev9",
"ember-browserify": "^1.0.1",
"ember-cli": "^2.8.0",
"ember-cli-app-version": "^1.0.0",