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

feat(vm-snapshots): implement vm snapshots details sidebar #1454

Merged
merged 4 commits into from
Dec 4, 2018
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 4 additions & 7 deletions src/app/account/account/account-item.component.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { EventEmitter } from '@angular/core';
import { MatMenuTrigger } from '@angular/material';
import { AuthService } from '../../shared/services/auth.service';
import { Account } from '../../shared/models';
import { stateTranslations } from '../account-container/account.container';
import { AuthService } from '../../shared/services/auth.service';
import { isUserBelongsToAccount } from '../../shared/utils/account';
import { stateTranslations } from '../account-container/account.container';

export class AccountItemComponent {
public item: Account;
Expand All @@ -19,11 +19,8 @@ export class AccountItemComponent {

constructor(protected authService: AuthService) {}

public handleClick(e: MouseEvent): void {
e.stopPropagation();
if (!this.matMenuTrigger || !this.matMenuTrigger.menuOpen) {
this.onClick.emit(this.item);
}
public handleClick(): void {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove matMenuTrigger in this component if it's not used.

this.onClick.emit(this.item);
}

public isAdmin() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<mat-card
(click)="handleClick($event)"
(click)="handleClick()"
[class.card-selected]="isSelected(item)"
class="entity-card"
>
Expand All @@ -18,7 +18,9 @@
[style.visibility]="!isSelf ? 'visible' : 'hidden'"
mat-icon-button
[matMenuTriggerFor]="actionsMenu"
class="entity-card-menu">
class="entity-card-menu"
(click)="$event.stopPropagation()"
>
<mat-icon class="mdi-dots-vertical"></mat-icon>
</button>
</ng-container>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<mat-list-item
(click)="handleClick($event)"
(click)="handleClick()"
[class.card-selected]="isSelected(item)"
class="entity-list-item"
>
Expand Down Expand Up @@ -30,6 +30,7 @@ <h2 class="entity-list-item-title">
mat-icon-button
[style.visibility]="isAdmin() && !isSelf ? 'visible' : 'hidden'"
[matMenuTriggerFor]="actionsMenu"
(click)="$event.stopPropagation()"
>
<mat-icon class="mdi-dots-vertical"></mat-icon>
</button>
Expand Down
63 changes: 0 additions & 63 deletions src/app/reducers/snapshots/redux/snapshot.reducers.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,67 +92,4 @@ describe('Snapshot Reducer', () => {
expect(state.ids).toEqual(['2']);
expect(state.entities).toEqual({ 2: snapshots[1] });
});

it('should select filtered snapshots', () => {
const differentSnapshots: Snapshot[] = [
{
id: '1',
domain: 'test-domain',
domainid: 'test-domain-id',
created: '2016-01-11T15:59:42+0700',
physicalsize: 100,
volumeid: 'volume-id-2',
name: 'snapshot for testing',
tags: [],
state: SnapshotStates.BackedUp,
revertable: true,
snapshottype: SnapshotType.Daily,
account: 'develop',
},
{
id: '2',
domain: 'test-domain',
domainid: 'test-domain-id',
created: '2017-10-15T15:59:42+0700',
physicalsize: 100,
volumeid: 'volume-id-3',
name: 'snapshot for testing',
tags: [],
state: SnapshotStates.BackedUp,
revertable: false,
snapshottype: SnapshotType.Manual,
account: 'test',
},
];

let slice = fromSnapshots.selectFilteredSnapshots.projector(differentSnapshots, {
accounts: [],
vmIds: [],
date: '2017-10-15T00:00:00.000Z',
query: undefined,
volumeSnapshotTypes: [],
});

expect(slice).toEqual([differentSnapshots[1]]);

slice = fromSnapshots.selectFilteredSnapshots.projector(differentSnapshots, {
accounts: [],
vmIds: [],
date: null,
query: undefined,
volumeSnapshotTypes: [SnapshotType.Daily],
});

expect(slice).toEqual([differentSnapshots[0]]);

slice = fromSnapshots.selectFilteredSnapshots.projector(differentSnapshots, {
accounts: ['develop'],
vmIds: [],
date: null,
query: undefined,
volumeSnapshotTypes: [],
});

expect(slice).toEqual([differentSnapshots[0]]);
});
});
48 changes: 1 addition & 47 deletions src/app/reducers/snapshots/redux/snapshot.reducers.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { createEntityAdapter, EntityAdapter, EntityState } from '@ngrx/entity';
import { createFeatureSelector, createSelector } from '@ngrx/store';
import * as moment from 'moment';
import { getSnapshotDescription, Snapshot } from '../../../shared/models';
import * as snapshotPageSelectors from '../../../snapshot/store/snapshot-page.selectors';
import { Snapshot } from '../../../shared/models';
import * as volumeActions from '../../volumes/redux/volumes.actions';
import * as snapshotActions from './snapshot.actions';

Expand Down Expand Up @@ -89,48 +88,3 @@ export const { selectIds, selectEntities, selectAll, selectTotal } = adapter.get
);

export const isLoading = createSelector(getSnapshotEntitiesState, state => state.loading);

export const getSelectedSnapshot = createSelector(
getSnapshotEntitiesState,
state => state.entities[state.selectedSnapshotId],
);

export const selectFilteredSnapshots = createSelector(
selectAll,
snapshotPageSelectors.getFilters,
(snapshots, filter) => {
const filterByTypes = (snapshot: Snapshot) =>
!filter.volumeSnapshotTypes.length ||
!!filter.volumeSnapshotTypes.find(type => type === snapshot.snapshottype);

const filterByAccount = (snapshot: Snapshot) =>
!filter.accounts.length || !!filter.accounts.find(id => id === snapshot.account);

const filterByDate = (snapshot: Snapshot) =>
!filter.date ||
moment(snapshot.created).isBetween(
moment(filter.date).startOf('day'),
moment(filter.date).endOf('day'),
);

const queryLower = filter.query && filter.query.toLowerCase();
const filterByQuery = (snapshot: Snapshot) => {
return (
!filter.query ||
snapshot.name.toLowerCase().indexOf(queryLower) > -1 ||
(getSnapshotDescription(snapshot) &&
getSnapshotDescription(snapshot)
.toLowerCase()
.indexOf(queryLower) > -1)
);
};

return snapshots.filter(
(snapshot: Snapshot) =>
filterByAccount(snapshot) &&
filterByTypes(snapshot) &&
filterByDate(snapshot) &&
filterByQuery(snapshot),
);
},
);
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<mat-card
(click)="handleClick($event)"
(click)="handleClick()"
[class.card-selected]="isSelected(item)"
class="entity-card"
>
Expand All @@ -8,7 +8,7 @@
<mat-card-title [matTooltip]="item.name" class="entity-card-title">
<span [innerHTML]="item.name | highlight:query"></span>
</mat-card-title>
<button mat-icon-button [matMenuTriggerFor]="actionsMenu" class="entity-card-menu">
<button mat-icon-button [matMenuTriggerFor]="actionsMenu" class="entity-card-menu" (click)="$event.stopPropagation()">
<mat-icon class="mdi-dots-vertical"></mat-icon>
</button>
</mat-card-header>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<mat-list-item
(click)="handleClick($event)"
(click)="handleClick()"
[class.card-selected]="isSelected(item)"
class="entity-list-item"
>
Expand All @@ -20,7 +20,7 @@ <h2 class="entity-list-item-title" [innerHTML]="item.name | highlight:query"></h
<span [innerHTML]="item.description | highlight:query"></span>
</div>

<button mat-icon-button [matMenuTriggerFor]="actionsMenu">
<button mat-icon-button [matMenuTriggerFor]="actionsMenu" (click)="$event.stopPropagation()">
<mat-icon class="mdi-dots-vertical"></mat-icon>
</button>

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { EventEmitter, OnChanges, SimpleChanges } from '@angular/core';
import { MatMenuTrigger } from '@angular/material';

import { getType, isSecurityGroupNative, SecurityGroup } from '../sg.model';
import { NgrxEntities } from '../../shared/interfaces';
import { VirtualMachine } from '../../vm';
import { SecurityGroupViewMode } from '../sg-view-mode';
import { NgrxEntities } from '../../shared/interfaces';

import { getType, isSecurityGroupNative, SecurityGroup } from '../sg.model';

export class SecurityGroupListItemComponent implements OnChanges {
public item: SecurityGroup;
Expand Down Expand Up @@ -34,11 +34,8 @@ export class SecurityGroupListItemComponent implements OnChanges {
}
}

public handleClick(e: MouseEvent): void {
e.stopPropagation();
if (!this.matMenuTrigger.menuOpen) {
this.onClick.emit(this.item);
}
public handleClick(): void {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove matMenuTrigger in this component if it's not used.

this.onClick.emit(this.item);
}

public get isPrivate(): boolean {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
$circle-size: 14px;

:host {
margin-right: 5px;
}

mat-icon {
font-size: $circle-size;
width: $circle-size;
Expand Down
9 changes: 9 additions & 0 deletions src/app/shared/models/vm-snapshot.model.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { SnapshotType } from '../types';
import { BaseModel } from './base.model';
import { Snapshot } from './snapshot.model';

export interface VmSnapshot extends BaseModel {
account: string;
Expand All @@ -16,3 +18,10 @@ export interface VmSnapshot extends BaseModel {
virtualmachineid: string;
zoneid: string;
}

export function getSnapshotType(snapshot: VmSnapshot | Snapshot): SnapshotType {
if (!snapshot) {
return undefined;
}
return (snapshot as VmSnapshot).virtualmachineid == null ? SnapshotType.Volume : SnapshotType.VM;
}
1 change: 1 addition & 0 deletions src/app/shared/types/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from './day-of-week';
export * from './language';
export * from './snapshot-type';
export * from './time-format';
export * from './keyboard-layout';
4 changes: 4 additions & 0 deletions src/app/shared/types/snapshot-type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export enum SnapshotType {
Volume,
VM,
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Component, Input, OnInit } from '@angular/core';
import { Store } from '@ngrx/store';
import { State, vmSnapshotsActions } from '../../../root-store';
import { VmState } from '../../../vm/shared/vm.model';
import { VmSnapshotSidebarViewModel } from '../../models/vm-snapshot-sidebar.view-model';
import { VmSnapshotViewModel } from '../../models/vm-snapshot.view-model';

@Component({
Expand All @@ -11,7 +12,7 @@ import { VmSnapshotViewModel } from '../../models/vm-snapshot.view-model';
})
export class VmSnapshotActionMenuComponent implements OnInit {
@Input()
public snapshot: VmSnapshotViewModel;
public snapshot: VmSnapshotViewModel | VmSnapshotSidebarViewModel;
public vmStates = VmState;

constructor(private store: Store<State>) {}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
<mat-card class="entity-card">
<mat-card
class="entity-card"
[class.card-selected]="isSelected(item)"
(click)="onSelect()"
>
<mat-card-header class="entity-card-header">
<cs-round-state-indicator
class="entity-card-thumbnail"
Expand All @@ -8,7 +12,7 @@
<mat-card-title class="entity-card-title" [matTooltip]="item.name">
<span>{{ item.name }}</span>
</mat-card-title>
<button mat-icon-button [mat-menu-trigger-for]="actionsMenu" class="entity-card-menu">
<button mat-icon-button [mat-menu-trigger-for]="actionsMenu" class="entity-card-menu" (click)="$event.stopPropagation()">
<mat-icon class="mdi-dots-vertical"></mat-icon>
</button>
</mat-card-header>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
import { Component, Input, OnInit } from '@angular/core';
import { Component, EventEmitter, Input, Output, ViewChild } from '@angular/core';
import { MatMenuTrigger } from '@angular/material';
import { VmSnapshotViewModel } from '../../models/vm-snapshot.view-model';

@Component({
selector: 'cs-vm-snapshot-card-view',
templateUrl: './vm-snapshot-card-view.component.html',
styleUrls: ['./vm-snapshot-card-view.component.scss'],
})
export class VmSnapshotCardViewComponent implements OnInit {
export class VmSnapshotCardViewComponent {
@Input()
public item: VmSnapshotViewModel;
@Input()
public isSelected: (vmSnapshot: VmSnapshotViewModel) => boolean;
@Output()
public clicked = new EventEmitter<VmSnapshotViewModel>();
@ViewChild(MatMenuTrigger)
public matMenuTrigger: MatMenuTrigger;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove matMenuTrigger if it is not used


constructor() {}

ngOnInit() {}
public onSelect() {
this.clicked.emit(this.item);
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
<mat-list-item class="entity-list-item">
<mat-list-item
class="entity-list-item"
[class.card-selected]="isSelected(item)"
(click)="onSelect()"
>
<cs-square-state-indicator
class="entity-list-item-status-indicator"
[state]="item.state.toLowerCase()"
Expand All @@ -17,7 +21,7 @@ <h2 class="entity-list-item-title">
{{ 'SNAPSHOT_PAGE.CARD.CREATED' | translate }}: {{ item.created | csStringifyDate }}
</div>

<button mat-icon-button [mat-menu-trigger-for]="actionsMenu">
<button mat-icon-button [mat-menu-trigger-for]="actionsMenu" (click)="$event.stopPropagation()">
<mat-icon class="mdi-dots-vertical"></mat-icon>
</button>

Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
import { Component, Input, OnInit } from '@angular/core';
import { Component, EventEmitter, Input, Output, ViewChild } from '@angular/core';
tamazlykar marked this conversation as resolved.
Show resolved Hide resolved
import { MatMenuTrigger } from '@angular/material';
import { VmSnapshotViewModel } from '../../models/vm-snapshot.view-model';

@Component({
selector: 'cs-vm-snapshot-list-view',
templateUrl: './vm-snapshot-list-view.component.html',
styleUrls: ['./vm-snapshot-list-view.component.scss'],
})
export class VmSnapshotListViewComponent implements OnInit {
export class VmSnapshotListViewComponent {
@Input()
public item: VmSnapshotViewModel;
@Input()
public isSelected: (vmSnapshot: VmSnapshotViewModel) => boolean;
@Output()
public clicked = new EventEmitter<VmSnapshotViewModel>();
@ViewChild(MatMenuTrigger)
public matMenuTrigger: MatMenuTrigger;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove matMenuTrigger if it is not used


constructor() {}

ngOnInit() {}
public onSelect() {
this.clicked.emit(this.item);
}
}
Loading