Skip to content
This repository has been archived by the owner on Mar 25, 2023. It is now read-only.

Commit

Permalink
#216 update to master
Browse files Browse the repository at this point in the history
  • Loading branch information
Vladimir Shakhov committed Jul 19, 2017
2 parents ba7f9c4 + 367e404 commit 6cad2f4
Show file tree
Hide file tree
Showing 22 changed files with 558 additions and 397 deletions.
27 changes: 27 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,30 @@
<a name="1.0.5"></a>
## 1.0.5 (2017-07-12)

Features, Enhancements

|#ticket|What was done|
|---|---|
|[#246](https://github.com/bwsw/cloudstack-ui/issues/246)|Warning message appears in case of VM start fail|
|[#230](https://github.com/bwsw/cloudstack-ui/issues/230)|Reload icon for VM statistics pane in a sidebar is implemented|
|[#224](https://github.com/bwsw/cloudstack-ui/issues/224)|VM Group change dialog is upgraded|
|[#225](https://github.com/bwsw/cloudstack-ui/issues/225)|Affinity Group change dialog is upgraded|
|[#197](https://github.com/bwsw/cloudstack-ui/issues/197)|A contrast circle around state bullet is added|
|[#116](https://github.com/bwsw/cloudstack-ui/issues/116)|SSH keys (re)setting in VM detailed sidebar is implemented|
|[#20](https://github.com/bwsw/cloudstack-ui/issues/20)|Parameters are configurable in json config|

Bugs fixed

|#ticket|What was done|
|---|---|
|[#254](https://github.com/bwsw/cloudstack-ui/issues/254)|Empty event list problem is fixed|
|[#232](https://github.com/bwsw/cloudstack-ui/issues/232)|Incorrect Activity Log Date bug is fixed|
|[#231](https://github.com/bwsw/cloudstack-ui/issues/231)|A tooltip is added for Regenerate keys action icon in Settings|
|[#228](https://github.com/bwsw/cloudstack-ui/issues/228)|Configured logout timeout bug is fixed|
|[#223](https://github.com/bwsw/cloudstack-ui/issues/223)|VM color picker bug is fixed|

---

<a name="1.0.4"></a>
## 1.0.4 (2017-06-27)

Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ Table of Contents

CloudStack-UI is a project whose purpose is to develop an easy-to-use, light, and user friendly frontend interface for the [Apache CloudStack](http://cloudstack.apache.org/) virtualization management system. Apache CloudStack itself is a great product which is used very widely, but its frontend is developed for administrators (from our point of view), not for end cloud users. Some of the interactions are not straightforward and unnatural to an average user and require quite a long time to adapt. Other reasons to develop are connected with a lack of functions like virtual machine statistics & charting, sophisticated resource accounting, and application management. These are in our long-term TODO list.

Join CloudStack-UI LinkedIn [Group](https://www.linkedin.com/groups/13540203)

## Project Story

At [Bitworks Software](https://bitworks.software/), we run an ACS public cloud for 3 years (actually we still run CS 4.3 cloud in production) and we found that average users who are familiar with Digital Ocean, Amazon AWS, and other VPS management systems feel uncomfortable with original CloudStack UI and make a lot of operational mistakes. That’s why we decided to implement a convenient and neat end-user facing UI covering regular activities, which are important for day-to-day VM management.
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "cloudstack-ui",
"version": "1.0.4",
"version": "1.0.5",
"license": "Apache-2.0",
"scripts": {
"ng": "ng",
Expand Down Expand Up @@ -34,7 +34,7 @@
"reflect-metadata": "^0.1.10",
"rxjs": "^5.1.0",
"uuid": "^3.1.0",
"zone.js": "^0.8.4"
"zone.js": "0.8.12"
},
"devDependencies": {
"@angular/cli": "1.1.3",
Expand Down
15 changes: 15 additions & 0 deletions src/app/vm/vm-sidebar/color/vm-color.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<mdl-card class="vm-card" mdl-shadow="2">
<mdl-card-title>
<h2 mdl-card-title-text>{{ 'COLOR' | translate }}</h2>
</mdl-card-title>
<mdl-card-supporting-text>
<cs-color-picker
*ngIf="colorList"
class="color-picker"
[colors]="colorList"
[ngModel]="color"
[disabled]="colorUpdateInProgress"
(change)="changeColor($event)"
></cs-color-picker>
</mdl-card-supporting-text>
</mdl-card>
14 changes: 14 additions & 0 deletions src/app/vm/vm-sidebar/color/vm-color.component.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
.color-picker {
margin: -20px 0;
width: 330px;
}

mdl-card {
z-index: 2;
}

mdl-card,
mdl-card-supporting-text
{
overflow: visible;
}
61 changes: 61 additions & 0 deletions src/app/vm/vm-sidebar/color/vm-color.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { Component, Input, OnChanges, OnDestroy, OnInit } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { Subject } from 'rxjs/Subject';
import { Color } from '../../../shared/models';
import { ConfigService } from '../../../shared/services';
import { VirtualMachine } from '../../shared/vm.model';
import { VmService } from '../../shared/vm.service';


@Component({
selector: 'cs-vm-color',
templateUrl: 'vm-color.component.html',
styleUrls: ['vm-color.component.scss']
})
export class VmColorComponent implements OnChanges, OnInit, OnDestroy {
@Input() public vm: VirtualMachine;

public color: Color;
public colorList: Array<Color>;

public colorUpdateInProgress: boolean;
private colorSubject = new Subject<Color>();

constructor(
private configService: ConfigService,
private vmService: VmService
) {}

public ngOnInit(): void {
Observable.forkJoin(
this.configService.get('themeColors'),
this.configService.get('vmColors')
).subscribe(
([themeColors, vmColors]) => this.colorList = themeColors.concat(vmColors)
);

this.colorSubject
.debounceTime(1000)
.switchMap(color => {
this.colorUpdateInProgress = true;
return this.vmService.setColor(this.vm, color);
})
.subscribe(vm => {
this.colorUpdateInProgress = false;
this.vm = vm;
this.vmService.updateVmInfo(this.vm);
}, () => this.colorUpdateInProgress = false);
}

public ngOnChanges(): void {
this.color = this.vm.getColor();
}

public ngOnDestroy(): void {
this.colorSubject.unsubscribe();
}

public changeColor(color: Color): void {
this.colorSubject.next(color);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<mdl-card
class="vm-card"
mdl-shadow="2"
>
<mdl-card-title>
<h2 mdl-card-title-text>{{ 'FIREWALL_RULES' | translate }}</h2>
</mdl-card-title>
<mdl-card-supporting-text>
<div class="grid security-group">
<div class="row">
<div>{{ 'INGRESS' | translate }}</div>
<div>{{ vm.securityGroup[0]?.ingressRules.length }}</div>
</div>
<div class="row">
<div>{{ 'EGRESS' | translate}}</div>
<div>{{ vm.securityGroup[0]?.egressRules.length }}</div>
</div>
</div>
</mdl-card-supporting-text>
<mdl-card-actions mdl-card-border>
<button
[mdl-tooltip]="'EDIT' | translate"
mdl-tooltip-position="top"
mdl-button
mdl-button-type="icon"
(click)="showRulesDialog(vm.securityGroup[0])"
>
<mdl-icon>edit</mdl-icon>
</button>
</mdl-card-actions>
</mdl-card>
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { Component, Input } from '@angular/core';
import { VirtualMachine } from '../../../shared/vm.model';
import { DialogService } from '../../../../dialog/dialog-module/dialog.service';
import { SgRulesComponent } from '../../../../security-group/sg-rules/sg-rules.component';
import { SecurityGroup } from '../../../../security-group/sg.model';


@Component({
selector: 'cs-firewall-rules-detail',
templateUrl: 'firewall-rules-detail.component.html'
})
export class FirewallRulesDetailComponent {
@Input() public vm: VirtualMachine;

constructor(private dialogService: DialogService) {}

public showRulesDialog(securityGroup: SecurityGroup): void {
this.dialogService.showCustomDialog({
component: SgRulesComponent,
providers: [{ provide: 'securityGroup', useValue: securityGroup }],
styles: { 'width': '880px' },
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<cs-nic-detail [vm]="vm"></cs-nic-detail>

<cs-firewall-rules-detail
*ngIf="!disableSecurityGroup"
[vm]="vm"
></cs-firewall-rules-detail>
25 changes: 25 additions & 0 deletions src/app/vm/vm-sidebar/network-detail/network-detail.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { Component, Input, OnChanges } from '@angular/core';
import { ZoneService } from '../../../shared/services';
import { VirtualMachine } from '../../shared/vm.model';


@Component({
selector: 'cs-network-detail',
templateUrl: 'network-detail.component.html'
})
export class NetworkDetailComponent implements OnChanges {
@Input() public vm: VirtualMachine;

public disableSecurityGroup: boolean;

constructor(private zoneService: ZoneService) {}

public ngOnChanges(): void {
this.checkSecurityGroupDisabled();
}

private checkSecurityGroupDisabled(): void {
this.zoneService.get(this.vm.zoneId)
.subscribe(zone => this.disableSecurityGroup = zone.networkTypeIsBasic);
}
}
83 changes: 83 additions & 0 deletions src/app/vm/vm-sidebar/network-detail/nic/nic-detail.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<mdl-card class="vm-card" mdl-shadow="2">
<mdl-card-title>
<h2 mdl-card-title-text>{{ 'NETWORK_CONFIGURATION' | translate }}</h2>
</mdl-card-title>
<mdl-card-supporting-text>
<div class="collapsed-panel grid nic" *ngIf="!expandNIC">
<div class="row" *ngFor="let nic of vm.nic; let i = index">
<div>
{{ 'NIC' | translate }} {{ i+1 }}
</div>
<div>
{{ nic.ipAddress }}
</div>
</div>
</div>
<div class="expanded-panel grid nic" *ngIf="expandNIC">
<div *ngFor="let nic of vm.nic; let i = index">
<div class="nic-name">{{ 'NIC' | translate }} {{i+1}}</div>
<div class="row">
<div>{{ 'NIC_FIELDS.macAddress' | translate }}</div>
<div>{{ nic.macAddress }}</div>
</div>
<div class="row">
<div>{{ 'NIC_FIELDS.ipAddress' | translate }}</div>
<div>{{ nic.ipAddress }}</div>
</div>
<div class="row">
<div>{{ 'NIC_FIELDS.netmask' | translate }}</div>
<div>{{ nic.netmask }}</div>
</div>
<div class="row">
<div>{{ 'NIC_FIELDS.gateway' | translate }}</div>
<div>{{ nic.gateway }}</div>
</div>
<div class="row">
<div>{{ 'NIC_FIELDS.type' | translate }}</div>
<div>{{ nic.type }}</div>
</div>
<ng-container>
<div class="row">
<div>{{ 'NIC_FIELDS.secondaryIp' | translate }}</div>
<div>
<button
mdl-button
mdl-button-type="icon"
class="mdl-icon-button--small"
(click)="confirmAddSecondaryIp(vm)"
>
<mdl-icon class="mdl-icon--small">add</mdl-icon>
</button>
</div>
</div>
<div class="secondary-ips">
<div class="row" *ngFor="let ip of nic.secondaryIp">
<div>{{ ip.ipaddress }}</div>
<div>
<button
mdl-button
mdl-button-type="icon"
class="mdl-icon-button--small"
(click)="confirmRemoveSecondaryIp(ip.id, vm)"
>
<mdl-icon class="mdl-icon--small">delete</mdl-icon>
</button>
</div>
</div>
</div>
</ng-container>
</div>
</div>
</mdl-card-supporting-text>
<mdl-card-actions mdl-card-border style="text-align: right;">
<button
mdl-button
mdl-ripple
mdl-button-type="icon"
(click)="toggleNIC()"
[class.open]="expandNIC"
>
<mdl-icon>keyboard_arrow_down</mdl-icon>
</button>
</mdl-card-actions>
</mdl-card>
13 changes: 13 additions & 0 deletions src/app/vm/vm-sidebar/network-detail/nic/nic-detail.component.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
.nic-name {
font-weight: bolder;
padding: 2px;
}

.secondary-ips {
margin-left: 5%;
}

.nic .row > div:nth-child(2n)
{
text-align: right;
}
58 changes: 58 additions & 0 deletions src/app/vm/vm-sidebar/network-detail/nic/nic-detail.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { Component, Input } from '@angular/core';
import { VirtualMachine } from '../../../shared/vm.model';
import { DialogService } from '../../../../dialog/dialog-module/dialog.service';
import { VmService } from '../../../shared/vm.service';


@Component({
selector: 'cs-nic-detail',
templateUrl: 'nic-detail.component.html',
styleUrls: ['nic-detail.component.scss']
})
export class NicDetailComponent {
@Input() public vm: VirtualMachine;

public expandNIC = false;

constructor(
private dialogService: DialogService,
private vmService: VmService
) {}

public toggleNIC(): void {
this.expandNIC = !this.expandNIC;
}

public confirmAddSecondaryIp(vm: VirtualMachine): void {
this.dialogService.confirm('ARE_YOU_SURE_ADD_SECONDARY_IP', 'NO', 'YES')
.onErrorResumeNext()
.subscribe(() => this.addSecondaryIp(vm));
}

public confirmRemoveSecondaryIp(secondaryIpId: string, vm: VirtualMachine): void {
this.dialogService.confirm('ARE_YOU_SURE_REMOVE_SECONDARY_IP', 'NO', 'YES')
.onErrorResumeNext()
.subscribe(() => this.removeSecondaryIp(secondaryIpId, vm));
}

private addSecondaryIp(vm: VirtualMachine): void {
this.vmService.addIpToNic(vm.nic[0].id)
.subscribe(
res => {
const ip = res.result.nicsecondaryip;
vm.nic[0].secondaryIp.push(ip);
},
err => this.dialogService.alert(err.errortext)
);
}

private removeSecondaryIp(secondaryIpId: string, vm: VirtualMachine): void {
this.vmService.removeIpFromNic(secondaryIpId)
.subscribe(
() => {
vm.nic[0].secondaryIp = vm.nic[0].secondaryIp.filter(ip => ip.id !== secondaryIpId);
},
err => this.dialogService.alert(err.errortext)
);
}
}
Loading

0 comments on commit 6cad2f4

Please sign in to comment.