-
+
+
@@ -40,7 +55,7 @@
mat-icon-button
[matTooltip]="'COMMON.EDIT' | translate"
matTooltipPosition="above"
- (click)="isEdit=!isEdit"
+ (click)="editLimits()"
>
edit
diff --git a/src/app/account/account-sidebar/account-limits/account-limits.component.ts b/src/app/account/account-sidebar/account-limits/account-limits.component.ts
index dd0c37b124..aa748a518a 100644
--- a/src/app/account/account-sidebar/account-limits/account-limits.component.ts
+++ b/src/app/account/account-sidebar/account-limits/account-limits.component.ts
@@ -1,4 +1,5 @@
import {
+ ChangeDetectionStrategy,
Component,
EventEmitter,
Input,
@@ -13,6 +14,7 @@ import {
@Component({
selector: 'cs-account-limits',
templateUrl: 'account-limits.component.html',
+ changeDetection: ChangeDetectionStrategy.OnPush,
styleUrls: ['account-limits.component.scss']
})
export class AccountLimitsComponent {
@@ -21,6 +23,8 @@ export class AccountLimitsComponent {
@Output() public onLimitsEdit: EventEmitter>;
public isEdit: boolean = false;
+ public localLimits = [];
+
public limitLabels = {
[ResourceType.Instance]: 'ACCOUNT_PAGE.CONFIGURATION.VM_LIMIT',
[ResourceType.IP]: 'ACCOUNT_PAGE.CONFIGURATION.IP_LIMIT',
@@ -41,8 +45,13 @@ export class AccountLimitsComponent {
}
public onSave(): void {
- this.onLimitsEdit.emit(this.limits);
+ this.onLimitsEdit.emit(this.localLimits);
this.isEdit = false;
}
+ public editLimits() {
+ this.localLimits = this.limits.map(limit => ({resourcetype: limit.resourcetype, max: limit.max}));
+ this.isEdit = !this.isEdit;
+ }
+
}
diff --git a/src/app/account/account-sidebar/account-settings/account-configuration/account-configuration.component.ts b/src/app/account/account-sidebar/account-settings/account-configuration/account-configuration.component.ts
index 401e4a026c..ca21d530a0 100644
--- a/src/app/account/account-sidebar/account-settings/account-configuration/account-configuration.component.ts
+++ b/src/app/account/account-sidebar/account-settings/account-configuration/account-configuration.component.ts
@@ -1,5 +1,12 @@
-import { Component, EventEmitter, Input, Output } from '@angular/core';
+import {
+ Component,
+ EventEmitter,
+ Input,
+ Output
+} from '@angular/core';
import { Configuration } from '../../../../shared/models/configuration.model';
+import { EditAccountConfigurationComponent } from './edit-account-configuration.component';
+import { MatDialog } from '@angular/material';
@Component({
selector: 'cs-account-configuration',
@@ -9,12 +16,22 @@ export class AccountConfigurationComponent {
@Input() public configuration: Configuration;
@Output() public onConfigurationEdit: EventEmitter;
- constructor() {
+ constructor(
+ private dialog: MatDialog
+ ) {
this.onConfigurationEdit = new EventEmitter();
}
public edit(): void {
- this.onConfigurationEdit.emit(this.configuration);
+ this.dialog.open(EditAccountConfigurationComponent, {
+ width: '375px',
+ data: {
+ title: 'ACCOUNT_PAGE.CONFIGURATION.EDIT',
+ configuration: this.configuration
+ }
+ })
+ .afterClosed()
+ .subscribe(configurationPair => this.onConfigurationEdit.emit(configurationPair));
}
}
diff --git a/src/app/account/account-sidebar/account-settings/account-configuration/edit-account-configuration.component.html b/src/app/account/account-sidebar/account-settings/account-configuration/edit-account-configuration.component.html
index 0bea4536c1..d20f8ae782 100644
--- a/src/app/account/account-sidebar/account-settings/account-configuration/edit-account-configuration.component.html
+++ b/src/app/account/account-sidebar/account-settings/account-configuration/edit-account-configuration.component.html
@@ -28,7 +28,6 @@
mat-button
color="primary"
(click)="close()"
- type="button"
>
{{ 'COMMON.CANCEL' | translate }}
diff --git a/src/app/account/account-sidebar/account-settings/account-settings.component.html b/src/app/account/account-sidebar/account-settings/account-settings.component.html
index 1a7348532e..35fd96fe5b 100644
--- a/src/app/account/account-sidebar/account-settings/account-settings.component.html
+++ b/src/app/account/account-sidebar/account-settings/account-settings.component.html
@@ -11,7 +11,7 @@
diff --git a/src/app/account/account-sidebar/account-settings/account-settings.component.ts b/src/app/account/account-sidebar/account-settings/account-settings.component.ts
index 49877d1959..667701a091 100644
--- a/src/app/account/account-sidebar/account-settings/account-settings.component.ts
+++ b/src/app/account/account-sidebar/account-settings/account-settings.component.ts
@@ -1,44 +1,22 @@
-import { Component, Input, OnInit } from '@angular/core';
-import { EditAccountConfigurationComponent } from './account-configuration/edit-account-configuration.component';
+import {
+ Component,
+ EventEmitter,
+ Input,
+ Output
+} from '@angular/core';
import { Configuration } from '../../../shared/models/configuration.model';
-import { MatDialog } from '@angular/material';
-import { ConfigurationService } from '../../../shared/services/configuration.service';
import { Account } from '../../../shared/models/account.model';
@Component({
selector: 'cs-account-settings',
templateUrl: 'account-settings.component.html'
})
-export class AccountSettingsComponent implements OnInit {
+export class AccountSettingsComponent {
@Input() public account: Account;
- public configurations: Array
;
+ @Input() public configurations: Array;
- constructor(
- private dialog: MatDialog,
- private configurationService: ConfigurationService
- ) { }
-
- ngOnInit() {
- this.getConfiguration();
- }
-
- public getConfiguration() {
- this.configurationService.getList({ accountid: this.account.id })
- .subscribe(configurations => this.configurations = configurations);
- }
-
- public editConfiguration(configuration: Configuration): void {
- this.dialog.open(EditAccountConfigurationComponent, {
- width: '375px',
- data: {
- title: 'ACCOUNT_PAGE.CONFIGURATION.EDIT',
- configuration
- }
- })
- .afterClosed()
- .switchMap(configurationPair => this.configurationService.updateConfiguration(configurationPair, this.account))
- .subscribe(() => this.getConfiguration());
- }
+ @Output() public onConfigurationEdit = new EventEmitter();
+ constructor( ) { }
}
diff --git a/src/app/account/account-sidebar/account-sidebar.component.html b/src/app/account/account-sidebar/account-sidebar.component.html
index 4f1ab0aa65..699c39ec57 100644
--- a/src/app/account/account-sidebar/account-sidebar.component.html
+++ b/src/app/account/account-sidebar/account-sidebar.component.html
@@ -12,11 +12,9 @@
-
+
-
-
-
+
diff --git a/src/app/account/account-sidebar/account-sidebar.component.scss b/src/app/account/account-sidebar/account-sidebar.component.scss
index 5712066378..b1cfd47e18 100644
--- a/src/app/account/account-sidebar/account-sidebar.component.scss
+++ b/src/app/account/account-sidebar/account-sidebar.component.scss
@@ -1,5 +1,4 @@
:host ::ng-deep .name {
- font-weight: bold;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
@@ -10,7 +9,6 @@
overflow: hidden;
text-overflow: ellipsis;
cursor: default;
- max-width: 34% !important;
text-align: right;
white-space: nowrap;
}
@@ -22,11 +20,7 @@
}
:host ::ng-deep .left {
- max-width: 66% !important;
- min-width: 66% !important;
margin-right: 15px;
-
-
span {
width: 100%;
}
@@ -34,7 +28,6 @@
:host ::ng-deep .buttons {
display: none;
- min-width: 68px;
margin-left: 10px;
}
@@ -49,5 +42,5 @@
}
:host ::ng-deep .container:hover .buttons {
- display: inline-block;
+ display: flex;
}
diff --git a/src/app/account/account-sidebar/account-sidebar.component.ts b/src/app/account/account-sidebar/account-sidebar.component.ts
index 8db1ad89a0..8ee8acac76 100644
--- a/src/app/account/account-sidebar/account-sidebar.component.ts
+++ b/src/app/account/account-sidebar/account-sidebar.component.ts
@@ -1,11 +1,8 @@
-import { Component } from '@angular/core';
-import { SidebarComponent } from '../../shared/components/sidebar/sidebar.component';
+import { Component, EventEmitter, Input, Output } from '@angular/core';
import { Account } from '../../shared/models/account.model';
import { AccountService } from '../../shared/services/account.service';
import { NotificationService } from '../../shared/services/notification.service';
import { ActivatedRoute, Router } from '@angular/router';
-import { Observable } from 'rxjs/Observable';
-import { EntityDoesNotExistError } from '../../shared/components/sidebar/entity-does-not-exist-error';
import { AuthService } from '../../shared/services/auth.service';
@Component({
@@ -13,7 +10,11 @@ import { AuthService } from '../../shared/services/auth.service';
templateUrl: 'account-sidebar.component.html',
styleUrls: ['account-sidebar.component.scss']
})
-export class AccountSidebarComponent extends SidebarComponent
{
+export class AccountSidebarComponent {
+
+ @Input() public entity: any;
+ @Output() public onAccountChanged = new EventEmitter();
+
constructor(
protected accountService: AccountService,
protected notificationService: NotificationService,
@@ -21,18 +22,13 @@ export class AccountSidebarComponent extends SidebarComponent{
protected router: Router,
protected authService: AuthService
) {
- super(accountService, notificationService, route, router);
+
}
- protected loadEntity(id: string): Observable {
- return this.accountService.get(id)
- .switchMap(account => {
- if (account) {
- return Observable.of(account);
- } else {
- return Observable.throw(new EntityDoesNotExistError());
- }
- });
+ public tabIsActive(tabId: string) {
+ const path = this.route.snapshot;
+ const pathLastChild = path.firstChild.routeConfig.path;
+ return (tabId === pathLastChild)
}
public isAdmin() {
diff --git a/src/app/account/account-sidebar/account-statistic/account-statistics.component.html b/src/app/account/account-sidebar/account-statistic/account-statistics.component.html
index 1a18b427b0..08f3f73765 100644
--- a/src/app/account/account-sidebar/account-statistic/account-statistics.component.html
+++ b/src/app/account/account-sidebar/account-statistic/account-statistics.component.html
@@ -23,7 +23,7 @@
;
+export class AccountStatisticsComponent {
+ @Input() public stats: Array
;
+ @Output() public onStatsUpdate = new EventEmitter();
public resourceLabels = {
[ResourceType.Instance]: 'ACCOUNT_PAGE.CONFIGURATION.VM_COUNT',
@@ -33,18 +32,9 @@ export class AccountStatisticsComponent implements OnInit {
};
constructor(
- private resourceCountService: ResourceCountService,
private dialogService: DialogService
) { }
- ngOnInit() {
- this.updateStats();
- }
-
- public updateStats(){
- this.resourceCountService.updateResourceCount(this.account)
- .subscribe(stats => this.stats = stats);
- }
public confirmUpdateStats() {
this.dialogService.confirm({
@@ -52,6 +42,6 @@ export class AccountStatisticsComponent implements OnInit {
})
.onErrorResumeNext()
.filter(res => Boolean(res))
- .subscribe(res => this.updateStats());
+ .subscribe(res => this.onStatsUpdate.emit(res));
}
}
diff --git a/src/app/account/account/account-item.component.ts b/src/app/account/account/account-item.component.ts
index 8f029a02db..2ef9ea32b8 100644
--- a/src/app/account/account/account-item.component.ts
+++ b/src/app/account/account/account-item.component.ts
@@ -1,4 +1,10 @@
-import { Component, EventEmitter, Input, Output, ViewChild } from '@angular/core';
+import {
+ Component,
+ EventEmitter,
+ Input,
+ Output,
+ ViewChild
+} from '@angular/core';
import { MatMenuTrigger } from '@angular/material';
import { AuthService } from '../../shared/services/auth.service';
import { Account } from '../../shared/models/account.model';
@@ -14,7 +20,7 @@ export class AccountItemComponent {
@Input() public isSelected: (account) => boolean;
@Output() public onClick = new EventEmitter();
@Output() public onAccountChanged = new EventEmitter();
- @ViewChild(MatMenuTrigger) public mdMenuTrigger: MatMenuTrigger;
+ @ViewChild(MatMenuTrigger) public matMenuTrigger: MatMenuTrigger;
readonly stateTranslations = stateTranslations;
@@ -23,7 +29,7 @@ export class AccountItemComponent {
public handleClick(e: MouseEvent): void {
e.stopPropagation();
- if (!this.mdMenuTrigger || !this.mdMenuTrigger.menuOpen) {
+ if (!this.matMenuTrigger || !this.matMenuTrigger.menuOpen) {
this.onClick.emit(this.item);
}
}
diff --git a/src/app/account/accounts.module.ts b/src/app/account/accounts.module.ts
index c82de8b6cb..26fa8e333d 100644
--- a/src/app/account/accounts.module.ts
+++ b/src/app/account/accounts.module.ts
@@ -12,7 +12,8 @@ import {
MatMenuModule,
MatSelectModule,
MatTabsModule,
- MatTooltipModule
+ MatTooltipModule,
+ MatInputModule
} from '@angular/material';
import { AccountItemComponent } from './account/account-item.component';
import { DynamicModule } from 'ng-dynamic-component';
@@ -25,16 +26,23 @@ import { AccountDetailsComponent } from './account-sidebar/account-details/accou
import { AccountConfigurationComponent } from './account-sidebar/account-settings/account-configuration/account-configuration.component';
import { EditAccountConfigurationComponent } from './account-sidebar/account-settings/account-configuration/edit-account-configuration.component';
import { AccountPageContainerComponent } from './account-container/account.container';
-import { AccountsEffects } from './redux/accounts.effects';
-import { DomainsEffects } from '../domains/redux/domains.effects';
-import { RolesEffects } from '../roles/redux/roles.effects';
+import { AccountsEffects } from '../reducers/accounts/redux/accounts.effects';
+import { DomainsEffects } from '../reducers/domains/redux/domains.effects';
+import { RolesEffects } from '../reducers/roles/redux/roles.effects';
import { StoreModule } from '@ngrx/store';
import { EffectsModule } from '@ngrx/effects';
-import { accountReducers } from './redux/accounts.reducers';
-import { domainReducers } from '../domains/redux/domains.reducers'
-import { roleReducers } from '../roles/redux/roles.reducers';
+import { accountReducers } from '../reducers/accounts/redux/accounts.reducers';
+import { domainReducers } from '../reducers/domains/redux/domains.reducers'
+import { roleReducers } from '../reducers/roles/redux/roles.reducers';
import { DraggableSelectModule } from '../shared/components/draggable-select/draggable-select.module';
-
+import { AccountSidebarContainerComponent } from './account-container/account-sidebar.container';
+import { AccountDetailsContainerComponent } from './account-container/account-details.container';
+import { configurationReducers } from '../reducers/configuration/redux/configurations.reducers';
+import { ConfigurationEffects } from '../reducers/configuration/redux/configurations.effects';
+import { resourceLimitsReducers } from '../reducers/resource-limit/redux/resource-limits.reducers';
+import { ResourceLimitsEffects } from '../reducers/resource-limit/redux/resource-limits.effects';
+import { ResourceCountsEffects } from '../reducers/resource-count/redux/resource-counts.effects';
+import { resourceCountsReducers } from '../reducers/resource-count/redux/resource-counts.reducers';
@NgModule({
imports: [
@@ -47,14 +55,25 @@ import { DraggableSelectModule } from '../shared/components/draggable-select/dra
MatButtonModule,
MatSelectModule,
MatIconModule,
+ MatInputModule,
RouterModule,
SharedModule,
TranslateModule,
DraggableSelectModule,
+ StoreModule.forFeature('configurations', configurationReducers),
+ StoreModule.forFeature('resourceLimits', resourceLimitsReducers),
+ StoreModule.forFeature('resourceCounts', resourceCountsReducers),
StoreModule.forFeature('accounts', accountReducers),
StoreModule.forFeature('domains', domainReducers),
StoreModule.forFeature('roles', roleReducers),
- EffectsModule.forFeature([AccountsEffects, DomainsEffects, RolesEffects]),
+ EffectsModule.forFeature([
+ AccountsEffects,
+ DomainsEffects,
+ RolesEffects,
+ ConfigurationEffects,
+ ResourceLimitsEffects,
+ ResourceCountsEffects
+ ]),
],
declarations: [
AccountPageComponent,
@@ -68,6 +87,8 @@ import { DraggableSelectModule } from '../shared/components/draggable-select/dra
AccountDetailsComponent,
AccountConfigurationComponent,
AccountPageContainerComponent,
+ AccountSidebarContainerComponent,
+ AccountDetailsContainerComponent,
EditAccountConfigurationComponent,
],
entryComponents: [
diff --git a/src/app/account/accounts.routing.ts b/src/app/account/accounts.routing.ts
index bc77e201a0..6a5bd507ab 100644
--- a/src/app/account/accounts.routing.ts
+++ b/src/app/account/accounts.routing.ts
@@ -1,8 +1,8 @@
import { Routes } from '@angular/router';
import { AuthGuard } from '../shared/services/auth-guard.service';
-import { AccountSidebarComponent } from './account-sidebar/account-sidebar.component';
-import { AccountDetailsComponent } from './account-sidebar/account-details/account-details.component';
import { AccountPageContainerComponent } from './account-container/account.container';
+import { AccountSidebarContainerComponent } from './account-container/account-sidebar.container';
+import { AccountDetailsContainerComponent } from './account-container/account-details.container';
export const accountsRoutes: Routes = [
{
@@ -15,7 +15,7 @@ export const accountsRoutes: Routes = [
component: AccountCreationDialogComponent
},*/ {
path: ':id',
- component: AccountSidebarComponent,
+ component: AccountSidebarContainerComponent,
canActivate: [AuthGuard],
children: [
{
@@ -25,7 +25,7 @@ export const accountsRoutes: Routes = [
},
{
path: 'account',
- component: AccountDetailsComponent
+ component: AccountDetailsContainerComponent
},
]
}
diff --git a/src/app/domains/redux/domains.effects.ts b/src/app/domains/redux/domains.effects.ts
deleted file mode 100644
index 69b0049b67..0000000000
--- a/src/app/domains/redux/domains.effects.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-import { Injectable } from '@angular/core';
-import { Actions, Effect } from '@ngrx/effects';
-import { Observable } from 'rxjs/Observable';
-import { Action } from '@ngrx/store';
-import { DomainService } from '../../shared/services/domain.service';
-import { Domain } from '../../shared/models/domain.model';
-import { AuthService } from '../../shared/services/auth.service';
-
-import * as domainActions from './domains.actions';
-
-
-@Injectable()
-export class DomainsEffects {
-
- @Effect()
- loadDomains$: Observable = this.actions$
- .ofType(domainActions.LOAD_DOMAINS_REQUEST)
- .switchMap((action: domainActions.LoadDomainsRequest) => {
- return this.authService.isAdmin()
- ? this.domainService.getList(action.payload)
- .map((domains: Domain[]) => {
- return new domainActions.LoadDomainsResponse(domains);
- })
- .catch(() => Observable.of(new domainActions.LoadDomainsResponse([])))
- : Observable.of(new domainActions.LoadDomainsResponse([]));
- });
-
- constructor(
- private actions$: Actions,
- private domainService: DomainService,
- private authService: AuthService
- ) {
- }
-}
diff --git a/src/app/events/containers/event-list.container.ts b/src/app/events/containers/event-list.container.ts
index 053ef3e4f7..e3d55ebd2b 100644
--- a/src/app/events/containers/event-list.container.ts
+++ b/src/app/events/containers/event-list.container.ts
@@ -5,7 +5,7 @@ import {
import { State } from '../../reducers/index';
import { Store } from '@ngrx/store';
import * as eventAction from '../redux/events.actions';
-import * as accountAction from '../../account/redux/accounts.actions';
+import * as accountAction from '../../reducers/accounts/redux/accounts.actions';
import * as debounce from 'lodash/debounce';
import { FilterService } from '../../shared/services/filter.service';
import {
@@ -14,7 +14,7 @@ import {
} from '@angular/router';
import { SessionStorageService } from '../../shared/services/session-storage.service';
import * as fromEvents from '../redux/events.reducers';
-import * as fromAccounts from '../../account/redux/accounts.reducers';
+import * as fromAccounts from '../../reducers/accounts/redux/accounts.reducers';
import { LanguageService } from '../../shared/services/language.service';
import { WithUnsubscribe } from '../../utils/mixins/with-unsubscribe';
import { AuthService } from '../../shared/services/auth.service';
@@ -46,7 +46,7 @@ export class EventListContainerComponent extends WithUnsubscribe() implements On
readonly firstDayOfWeek$ = this.languageService.getFirstDayOfWeek();
readonly events$ = this.store.select(fromEvents.selectFilteredEvents);
- readonly accounts$ = this.store.select(fromAccounts.accounts);
+ readonly accounts$ = this.store.select(fromAccounts.selectAll);
readonly query$ = this.store.select(fromEvents.filterQuery);
readonly loading$ = this.store.select(fromEvents.isLoading);
readonly filters$ = this.store.select(fromEvents.filters);
diff --git a/src/app/events/redux/events.reducers.ts b/src/app/events/redux/events.reducers.ts
index acd70e800a..01bf1d11e7 100644
--- a/src/app/events/redux/events.reducers.ts
+++ b/src/app/events/redux/events.reducers.ts
@@ -9,7 +9,7 @@ import {
} from '@ngrx/entity';
import * as event from './events.actions';
import { Event } from '../event.model';
-import { accounts } from '../../account/redux/accounts.reducers';
+import * as fromAccounts from '../../reducers/accounts/redux/accounts.reducers';
import moment = require('moment');
/**
@@ -179,7 +179,7 @@ export const selectFilteredEvents = createSelector(
filterSelectedTypes,
filterSelectedLevels,
filterSelectedAccountIds,
- accounts,
+ fromAccounts.selectAll,
(events, query, selectedTypes, selectedLevels, selectedAccountIds, accounts) => {
const queryLower = query && query.toLowerCase();
const typeMap = selectedTypes.reduce((m, i) => ({ ...m, [i]: i }), {});
@@ -198,9 +198,10 @@ export const selectFilteredEvents = createSelector(
!!levelsMap[event.level];
};
- const selectedAccounts = accounts.filter(account => selectedAccountIds.find(id => id === account.id));
- const accountsMap = selectedAccounts.reduce((m, i) => ({...m, [i.name]: i }), {});
- const domainsMap = selectedAccounts.reduce((m, i) => ({...m, [i.domainid]: i }), {});
+ const selectedAccounts = accounts.filter(
+ account => selectedAccountIds.find(id => id === account.id));
+ const accountsMap = selectedAccounts.reduce((m, i) => ({ ...m, [i.name]: i }), {});
+ const domainsMap = selectedAccounts.reduce((m, i) => ({ ...m, [i.domainid]: i }), {});
const selectedAccountIdsFilter = event => !selectedAccountIds.length ||
(accountsMap[event.account] && domainsMap[event.domainId]);
diff --git a/src/app/account/redux/accounts.actions.ts b/src/app/reducers/accounts/redux/accounts.actions.ts
similarity index 74%
rename from src/app/account/redux/accounts.actions.ts
rename to src/app/reducers/accounts/redux/accounts.actions.ts
index 67f53690e2..4b8fbb12f9 100644
--- a/src/app/account/redux/accounts.actions.ts
+++ b/src/app/reducers/accounts/redux/accounts.actions.ts
@@ -3,6 +3,7 @@ import { Action } from '@ngrx/store';
export const LOAD_ACCOUNTS_REQUEST = '[ACCOUNTS] LOAD_ACCOUNTS_REQUEST';
export const LOAD_ACCOUNTS_RESPONSE = '[ACCOUNTS] LOAD_ACCOUNTS_RESPONSE';
export const ACCOUNT_FILTER_UPDATE = '[ACCOUNTS] ACCOUNT_FILTER_UPDATE';
+export const LOAD_SELECTED_ACCOUNT = '[ACCOUNTS] LOAD_SELECTED_ACCOUNT';
export class LoadAccountsRequest implements Action {
type = LOAD_ACCOUNTS_REQUEST;
@@ -20,6 +21,14 @@ export class LoadAccountsResponse implements Action {
}
+export class LoadSelectedAccount implements Action {
+ type = LOAD_SELECTED_ACCOUNT;
+
+ constructor(public payload: string) {
+ }
+
+}
+
export class AccountFilterUpdate implements Action {
type = ACCOUNT_FILTER_UPDATE;
@@ -29,4 +38,4 @@ export class AccountFilterUpdate implements Action {
}
-export type Actions = LoadAccountsRequest | LoadAccountsResponse | AccountFilterUpdate;
+export type Actions = LoadAccountsRequest | LoadAccountsResponse | AccountFilterUpdate | LoadSelectedAccount;
diff --git a/src/app/account/redux/accounts.effects.ts b/src/app/reducers/accounts/redux/accounts.effects.ts
similarity index 88%
rename from src/app/account/redux/accounts.effects.ts
rename to src/app/reducers/accounts/redux/accounts.effects.ts
index a12cd9b18e..8d63d64619 100644
--- a/src/app/account/redux/accounts.effects.ts
+++ b/src/app/reducers/accounts/redux/accounts.effects.ts
@@ -1,9 +1,12 @@
import { Injectable } from '@angular/core';
-import { Actions, Effect } from '@ngrx/effects';
+import {
+ Actions,
+ Effect
+} from '@ngrx/effects';
import { Observable } from 'rxjs/Observable';
import * as accountActions from './accounts.actions';
import { Action } from '@ngrx/store';
-import { AccountService } from '../../shared/services/account.service';
+import { AccountService } from '../../../shared/services/account.service';
@Injectable()
export class AccountsEffects {
diff --git a/src/app/account/redux/accounts.reducers.ts b/src/app/reducers/accounts/redux/accounts.reducers.ts
similarity index 89%
rename from src/app/account/redux/accounts.reducers.ts
rename to src/app/reducers/accounts/redux/accounts.reducers.ts
index cfd0d16bca..d6fdcb2aec 100644
--- a/src/app/account/redux/accounts.reducers.ts
+++ b/src/app/reducers/accounts/redux/accounts.reducers.ts
@@ -8,7 +8,7 @@ import {
EntityState
} from '@ngrx/entity';
import * as event from './accounts.actions';
-import { Account } from '../../shared/models/account.model';
+import { Account } from '../../../shared/models/account.model';
/**
* @ngrx/entity provides a predefined interface for handling
@@ -19,6 +19,7 @@ import { Account } from '../../shared/models/account.model';
*/
export interface State extends EntityState {
loading: boolean,
+ selectedAccountId: string | null;
filters: {
selectedDomainIds: string[],
selectedRoleNames: string[],
@@ -55,8 +56,9 @@ export const adapter: EntityAdapter = createEntityAdapter({
*/
export const initialState: State = adapter.getInitialState({
loading: false,
+ selectedAccountId: null,
filters: {
- selectedDomainIds:[],
+ selectedDomainIds: [],
selectedRoleTypes: [],
selectedRoleNames: [],
selectedStates: [],
@@ -101,6 +103,13 @@ export function reducer(
};
}
+ case event.LOAD_SELECTED_ACCOUNT: {
+ return {
+ ...state,
+ selectedAccountId: action.payload
+ };
+ }
+
default: {
return state;
@@ -128,7 +137,16 @@ export const isLoading = createSelector(
state => state.loading
);
+export const getSelectedId = createSelector(
+ getAccountsEntitiesState,
+ state => state.selectedAccountId
+);
+export const getSelectedAccount = createSelector(
+ getAccountsState,
+ getSelectedId,
+ (state, selectedId) => state.list.entities[selectedId]
+);
export const filters = createSelector(
getAccountsEntitiesState,
@@ -156,11 +174,6 @@ export const filterSelectedStates = createSelector(
state => state.selectedStates
);
-export const accounts = createSelector(
- selectAll,
- (accounts) => accounts
-);
-
export const selectFilteredAccounts = createSelector(
selectAll,
filterSelectedRoleTypes,
diff --git a/src/app/reducers/configuration/redux/configurations.actions.ts b/src/app/reducers/configuration/redux/configurations.actions.ts
new file mode 100644
index 0000000000..c63ba0559a
--- /dev/null
+++ b/src/app/reducers/configuration/redux/configurations.actions.ts
@@ -0,0 +1,44 @@
+import { Action } from '@ngrx/store';
+
+export const LOAD_CONFIGURATIONS_REQUEST = '[CONFIGURATIONS] LOAD_CONFIGURATIONS_REQUEST';
+export const LOAD_CONFIGURATIONS_RESPONSE = '[CONFIGURATIONS] LOAD_CONFIGURATIONS_RESPONSE';
+export const UPDATE_CONFIGURATIONS_REQUEST = '[CONFIGURATIONS] UPDATE_CONFIGURATIONS_REQUEST';
+export const UPDATE_CONFIGURATIONS_ERROR = '[CONFIGURATIONS] UPDATE_CONFIGURATIONS_ERROR';
+
+export class LoadConfigurationsRequest implements Action {
+ type = LOAD_CONFIGURATIONS_REQUEST;
+
+ constructor(public payload?: any) {
+ }
+
+}
+
+export class LoadConfigurationsResponse implements Action {
+ type = LOAD_CONFIGURATIONS_RESPONSE;
+
+ constructor(public payload: any ) {
+ }
+
+}
+
+export class UpdateConfigurationRequest implements Action {
+ type = UPDATE_CONFIGURATIONS_REQUEST;
+
+ constructor(public payload: any ) {
+ }
+
+}
+
+export class UpdateConfigurationError implements Action {
+ readonly type = UPDATE_CONFIGURATIONS_ERROR;
+
+ constructor(public payload: Error) {
+ }
+
+}
+
+
+export type Actions = LoadConfigurationsRequest
+ | LoadConfigurationsResponse
+ | UpdateConfigurationRequest
+ | UpdateConfigurationError;
diff --git a/src/app/reducers/configuration/redux/configurations.effects.ts b/src/app/reducers/configuration/redux/configurations.effects.ts
new file mode 100644
index 0000000000..b0c44bda96
--- /dev/null
+++ b/src/app/reducers/configuration/redux/configurations.effects.ts
@@ -0,0 +1,65 @@
+import { Injectable } from '@angular/core';
+import {
+ Actions,
+ Effect
+} from '@ngrx/effects';
+import { Observable } from 'rxjs/Observable';
+import * as configurationActions from './configurations.actions';
+import { Action } from '@ngrx/store';
+import { ConfigurationService } from '../../../shared/services/configuration.service';
+import { Configuration } from '../../../shared/models/configuration.model';
+import { DialogService } from '../../../dialog/dialog-service/dialog.service';
+
+@Injectable()
+export class ConfigurationEffects {
+
+ @Effect()
+ loadConfigurations$: Observable = this.actions$
+ .ofType(configurationActions.LOAD_CONFIGURATIONS_REQUEST)
+ .switchMap((action: configurationActions.LoadConfigurationsRequest) => {
+ return this.configurationService.getList(action.payload)
+ .map((configurations: Configuration[]) => {
+ return new configurationActions.LoadConfigurationsResponse(configurations);
+ })
+ .catch(() => Observable.of(new configurationActions.LoadConfigurationsResponse([])));
+ });
+
+ @Effect()
+ updateConfiguration$: Observable = this.actions$
+ .ofType(configurationActions.UPDATE_CONFIGURATIONS_REQUEST)
+ .switchMap((action: configurationActions.UpdateConfigurationRequest) => {
+ return this.configurationService.updateConfiguration(
+ action.payload.configuration,
+ action.payload.account)
+ .map(() => {
+ return new configurationActions.LoadConfigurationsRequest({
+ accountid: action.payload.account.id
+ })
+ })
+ .catch((error) => Observable.of(new configurationActions.UpdateConfigurationError(error)));
+ });
+
+ @Effect({ dispatch: false })
+ updateConfigurationError$: Observable = this.actions$
+ .ofType(configurationActions.UPDATE_CONFIGURATIONS_ERROR)
+ .do((action: configurationActions.UpdateConfigurationError) => {
+ this.handleError(action.payload);
+ });
+
+
+ constructor(
+ private actions$: Actions,
+ private configurationService: ConfigurationService,
+ private dialogService: DialogService
+ ) {
+ }
+
+ private handleError(error): void {
+ this.dialogService.alert({
+ message: {
+ translationToken: error.message,
+ interpolateParams: error.params
+ }
+ });
+ }
+}
diff --git a/src/app/reducers/configuration/redux/configurations.reducers.ts b/src/app/reducers/configuration/redux/configurations.reducers.ts
new file mode 100644
index 0000000000..486a97efb4
--- /dev/null
+++ b/src/app/reducers/configuration/redux/configurations.reducers.ts
@@ -0,0 +1,107 @@
+import {
+ createFeatureSelector,
+ createSelector
+} from '@ngrx/store';
+import {
+ createEntityAdapter,
+ EntityAdapter,
+ EntityState
+} from '@ngrx/entity';
+import * as event from './configurations.actions';
+import { Configuration } from '../../../shared/models/configuration.model';
+
+/**
+ * @ngrx/entity provides a predefined interface for handling
+ * a structured dictionary of records. This interface
+ * includes an array of ids, and a dictionary of the provided
+ * model type by id. This interface is extended to include
+ * any additional interface properties.
+ */
+export interface State extends EntityState {
+ loading: boolean
+}
+
+export interface ConfigurationsState {
+ list: State;
+}
+
+export const configurationReducers = {
+ list: reducer,
+};
+
+/**
+ * createEntityAdapter creates many an object of helper
+ * functions for single or multiple operations
+ * against the dictionary of records. The configuration
+ * object takes a record id selector function and
+ * a sortComparer option which is set to a compare
+ * function if the records are to be sorted.
+ */
+export const adapter: EntityAdapter = createEntityAdapter({
+ selectId: (item: Configuration) => item.name,
+ sortComparer: false
+});
+
+/** getInitialState returns the default initial state
+ * for the generated entity state. Initial state
+ * additional properties can also be defined.
+ */
+export const initialState: State = adapter.getInitialState({
+ loading: false
+});
+
+export function reducer(
+ state = initialState,
+ action: event.Actions
+): State {
+ switch (action.type) {
+ case event.LOAD_CONFIGURATIONS_REQUEST: {
+ return {
+ ...state,
+ loading: true
+ };
+ }
+
+ case event.LOAD_CONFIGURATIONS_RESPONSE: {
+
+ const configurations = action.payload;
+
+ return {
+ /**
+ * The addMany function provided by the created adapter
+ * adds many records to the entity dictionary
+ * and returns a new state including those records. If
+ * the collection is to be sorted, the adapter will
+ * sort each record upon entry into the sorted array.
+ */
+ ...adapter.addAll(configurations, state),
+ loading: false
+ };
+ }
+ default: {
+ return state;
+ }
+ }
+}
+
+
+export const getConfigurationsState = createFeatureSelector('configurations');
+
+export const getConfigurationsEntitiesState = createSelector(
+ getConfigurationsState,
+ state => state.list
+);
+
+export const {
+ selectIds,
+ selectEntities,
+ selectAll,
+ selectTotal,
+} = adapter.getSelectors(getConfigurationsEntitiesState);
+
+export const isLoading = createSelector(
+ getConfigurationsEntitiesState,
+ state => state.loading
+);
+
+
diff --git a/src/app/domains/redux/domains.actions.ts b/src/app/reducers/domains/redux/domains.actions.ts
similarity index 92%
rename from src/app/domains/redux/domains.actions.ts
rename to src/app/reducers/domains/redux/domains.actions.ts
index 243fb5b146..fd1aac0d08 100644
--- a/src/app/domains/redux/domains.actions.ts
+++ b/src/app/reducers/domains/redux/domains.actions.ts
@@ -14,8 +14,9 @@ export class LoadDomainsRequest implements Action {
export class LoadDomainsResponse implements Action {
type = LOAD_DOMAINS_RESPONSE;
- constructor(public payload: any) {
+ constructor(public payload: any ) {
}
+
}
export type Actions = LoadDomainsResponse | LoadDomainsRequest;
diff --git a/src/app/reducers/domains/redux/domains.effects.ts b/src/app/reducers/domains/redux/domains.effects.ts
new file mode 100644
index 0000000000..accc4eeb72
--- /dev/null
+++ b/src/app/reducers/domains/redux/domains.effects.ts
@@ -0,0 +1,30 @@
+import { Injectable } from '@angular/core';
+import {
+ Actions,
+ Effect
+} from '@ngrx/effects';
+import { Observable } from 'rxjs/Observable';
+import * as domainActions from './domains.actions';
+import { Action } from '@ngrx/store';
+import { DomainService } from '../../../shared/services/domain.service';
+import { Domain } from '../../../shared/models/domain.model';
+
+@Injectable()
+export class DomainsEffects {
+
+ @Effect()
+ loadDomains$: Observable = this.actions$
+ .ofType(domainActions.LOAD_DOMAINS_REQUEST)
+ .switchMap((action: domainActions.LoadDomainsRequest) => {
+ return this.domainService.getList(action.payload)
+ .map((domains: Domain[]) => {
+ return new domainActions.LoadDomainsResponse(domains);
+ })
+ .catch(() => Observable.of(new domainActions.LoadDomainsResponse([])));
+ });
+
+ constructor(
+ private actions$: Actions,
+ private domainService: DomainService
+ ) { }
+}
diff --git a/src/app/domains/redux/domains.reducers.ts b/src/app/reducers/domains/redux/domains.reducers.ts
similarity index 94%
rename from src/app/domains/redux/domains.reducers.ts
rename to src/app/reducers/domains/redux/domains.reducers.ts
index 26f1f96b68..4d4a248690 100644
--- a/src/app/domains/redux/domains.reducers.ts
+++ b/src/app/reducers/domains/redux/domains.reducers.ts
@@ -7,7 +7,7 @@ import {
EntityAdapter,
EntityState
} from '@ngrx/entity';
-import { Domain } from '../../shared/models/domain.model';
+import { Domain } from '../../../shared/models/domain.model';
import * as event from './domains.actions';
@@ -103,8 +103,3 @@ export const isLoading = createSelector(
getDomainsEntitiesState,
state => state.loading
);
-
-export const domains = createSelector(
- selectAll,
- (domainsList) => domainsList
-);
diff --git a/src/app/reducers/resource-count/redux/resource-counts.actions.ts b/src/app/reducers/resource-count/redux/resource-counts.actions.ts
new file mode 100644
index 0000000000..16ac5890ca
--- /dev/null
+++ b/src/app/reducers/resource-count/redux/resource-counts.actions.ts
@@ -0,0 +1,22 @@
+import { Action } from '@ngrx/store';
+
+export const LOAD_RESOURCE_COUNTS_REQUEST = '[RESOURCE_COUNTS] LOAD_RESOURCE_COUNTS_REQUEST';
+export const LOAD_RESOURCE_COUNTS_RESPONSE = '[RESOURCE_COUNTS] LOAD_RESOURCE_COUNTS_RESPONSE';
+
+export class LoadResourceCountsRequest implements Action {
+ type = LOAD_RESOURCE_COUNTS_REQUEST;
+
+ constructor(public payload?: any) {
+ }
+
+}
+
+export class LoadResourceCountsResponse implements Action {
+ type = LOAD_RESOURCE_COUNTS_RESPONSE;
+
+ constructor(public payload: any ) {
+ }
+
+}
+
+export type Actions = LoadResourceCountsResponse | LoadResourceCountsRequest;
diff --git a/src/app/reducers/resource-count/redux/resource-counts.effects.ts b/src/app/reducers/resource-count/redux/resource-counts.effects.ts
new file mode 100644
index 0000000000..45b2aac981
--- /dev/null
+++ b/src/app/reducers/resource-count/redux/resource-counts.effects.ts
@@ -0,0 +1,30 @@
+import { Injectable } from '@angular/core';
+import {
+ Actions,
+ Effect
+} from '@ngrx/effects';
+import { Observable } from 'rxjs/Observable';
+import * as resourceCountActions from './resource-counts.actions';
+import { Action } from '@ngrx/store';
+import { ResourceCountService } from '../../../shared/services/resource-count.service';
+import { ResourceCount } from '../../../shared/models/resource-count.model';
+
+@Injectable()
+export class ResourceCountsEffects {
+
+ @Effect()
+ loadResourceLimits$: Observable = this.actions$
+ .ofType(resourceCountActions.LOAD_RESOURCE_COUNTS_REQUEST)
+ .switchMap((action: resourceCountActions.LoadResourceCountsRequest) => {
+ return this.resourceCountService.updateResourceCount(action.payload)
+ .map((stats: ResourceCount[]) => {
+ return new resourceCountActions.LoadResourceCountsResponse(stats);
+ })
+ .catch(() => Observable.of(new resourceCountActions.LoadResourceCountsResponse([])));
+ });
+
+ constructor(
+ private actions$: Actions,
+ private resourceCountService: ResourceCountService
+ ) { }
+}
diff --git a/src/app/reducers/resource-count/redux/resource-counts.reducers.ts b/src/app/reducers/resource-count/redux/resource-counts.reducers.ts
new file mode 100644
index 0000000000..e354108860
--- /dev/null
+++ b/src/app/reducers/resource-count/redux/resource-counts.reducers.ts
@@ -0,0 +1,108 @@
+import {
+ createFeatureSelector,
+ createSelector
+} from '@ngrx/store';
+import {
+ createEntityAdapter,
+ EntityAdapter,
+ EntityState
+} from '@ngrx/entity';
+import * as event from './resource-counts.actions';
+import { ResourceCount } from '../../../shared/models/resource-count.model';
+
+/**
+ * @ngrx/entity provides a predefined interface for handling
+ * a structured dictionary of records. This interface
+ * includes an array of ids, and a dictionary of the provided
+ * model type by id. This interface is extended to include
+ * any additional interface properties.
+ */
+export interface State extends EntityState {
+ loading: boolean
+}
+
+export interface ResourceCountsState {
+ list: State;
+}
+
+export const resourceCountsReducers = {
+ list: reducer,
+};
+
+/**
+ * createEntityAdapter creates many an object of helper
+ * functions for single or multiple operations
+ * against the dictionary of records. The configuration
+ * object takes a record id selector function and
+ * a sortComparer option which is set to a compare
+ * function if the records are to be sorted.
+ */
+export const adapter: EntityAdapter = createEntityAdapter({
+ selectId: (item: ResourceCount) => item.resourcetype.toString(),
+ sortComparer: false
+});
+
+/** getInitialState returns the default initial state
+ * for the generated entity state. Initial state
+ * additional properties can also be defined.
+ */
+export const initialState: State = adapter.getInitialState({
+ loading: false
+});
+
+export function reducer(
+ state = initialState,
+ action: event.Actions
+): State {
+ switch (action.type) {
+ case event.LOAD_RESOURCE_COUNTS_REQUEST: {
+ return {
+ ...state,
+ loading: true
+ };
+ }
+ case event.LOAD_RESOURCE_COUNTS_RESPONSE: {
+
+ const resourceCounts = action.payload;
+
+ return {
+ /**
+ * The addMany function provided by the created adapter
+ * adds many records to the entity dictionary
+ * and returns a new state including those records. If
+ * the collection is to be sorted, the adapter will
+ * sort each record upon entry into the sorted array.
+ */
+ ...adapter.addAll(resourceCounts, state),
+ loading: false
+ };
+ }
+
+
+ default: {
+ return state;
+ }
+ }
+}
+
+
+export const getResourceCountsState = createFeatureSelector('resourceCounts');
+
+export const getResourceCountsEntitiesState = createSelector(
+ getResourceCountsState,
+ state => state.list
+);
+
+export const {
+ selectIds,
+ selectEntities,
+ selectAll,
+ selectTotal,
+} = adapter.getSelectors(getResourceCountsEntitiesState);
+
+export const isLoading = createSelector(
+ getResourceCountsEntitiesState,
+ state => state.loading
+);
+
+
diff --git a/src/app/reducers/resource-limit/redux/resource-limits.actions.ts b/src/app/reducers/resource-limit/redux/resource-limits.actions.ts
new file mode 100644
index 0000000000..7eb8b6bd36
--- /dev/null
+++ b/src/app/reducers/resource-limit/redux/resource-limits.actions.ts
@@ -0,0 +1,43 @@
+import { Action } from '@ngrx/store';
+
+export const LOAD_RESOURCE_LIMITS_REQUEST = '[RESOURCE_LIMITS] LOAD_RESOURCE_LIMITS_REQUEST';
+export const LOAD_RESOURCE_LIMITS_RESPONSE = '[RESOURCE_LIMITS] LOAD_RESOURCE_LIMITS_RESPONSE';
+export const UPDATE_RESOURCE_LIMITS_REQUEST = '[RESOURCE_LIMITS] UPDATE_RESOURCE_LIMITS_REQUEST';
+export const UPDATE_RESOURCE_LIMITS_ERROR = '[RESOURCE_LIMITS] UPDATE_RESOURCE_LIMITS_ERROR';
+
+export class LoadResourceLimitsRequest implements Action {
+ type = LOAD_RESOURCE_LIMITS_REQUEST;
+
+ constructor(public payload?: any) {
+ }
+
+}
+
+export class LoadResourceLimitsResponse implements Action {
+ type = LOAD_RESOURCE_LIMITS_RESPONSE;
+
+ constructor(public payload: any ) {
+ }
+
+}
+
+export class UpdateResourceLimitsRequest implements Action {
+ type = UPDATE_RESOURCE_LIMITS_REQUEST;
+
+ constructor(public payload: { limits: any[], account: any } ) {
+ }
+
+}
+
+export class UpdateResourceLimitsError implements Action {
+ readonly type = UPDATE_RESOURCE_LIMITS_ERROR;
+
+ constructor(public payload: Error) {
+ }
+
+}
+
+export type Actions = LoadResourceLimitsResponse
+ | LoadResourceLimitsRequest
+ | UpdateResourceLimitsRequest
+ | UpdateResourceLimitsError;
diff --git a/src/app/reducers/resource-limit/redux/resource-limits.effects.ts b/src/app/reducers/resource-limit/redux/resource-limits.effects.ts
new file mode 100644
index 0000000000..564088c5c6
--- /dev/null
+++ b/src/app/reducers/resource-limit/redux/resource-limits.effects.ts
@@ -0,0 +1,65 @@
+import { Injectable } from '@angular/core';
+import {
+ Actions,
+ Effect
+} from '@ngrx/effects';
+import { Observable } from 'rxjs/Observable';
+import * as resourceLimitActions from './resource-limits.actions';
+import { Action } from '@ngrx/store';
+import { ResourceLimitService } from '../../../shared/services/resource-limit.service';
+import { ResourceLimit } from '../../../shared/models/resource-limit.model';
+import { DialogService } from '../../../dialog/dialog-service/dialog.service';
+
+@Injectable()
+export class ResourceLimitsEffects {
+
+ @Effect()
+ loadResourseLimits$: Observable = this.actions$
+ .ofType(resourceLimitActions.LOAD_RESOURCE_LIMITS_REQUEST)
+ .switchMap((action: resourceLimitActions.LoadResourceLimitsRequest) => {
+ return this.resourceLimitService.getList(action.payload)
+ .map((limits: ResourceLimit[]) => {
+ return new resourceLimitActions.LoadResourceLimitsResponse(limits);
+ })
+ .catch(() => Observable.of(new resourceLimitActions.LoadResourceLimitsResponse([])));
+ });
+
+ @Effect()
+ updateResourceLimits$: Observable = this.actions$
+ .ofType(resourceLimitActions.UPDATE_RESOURCE_LIMITS_REQUEST)
+ .switchMap((action: resourceLimitActions.UpdateResourceLimitsRequest) => {
+ const observes = action.payload.limits.map(limit =>
+ this.resourceLimitService.updateResourceLimit(limit, action.payload.account));
+ return Observable.forkJoin(observes)
+ .map(() => {
+ return new resourceLimitActions.LoadResourceLimitsRequest({
+ domainid: action.payload.account.domainid,
+ account: action.payload.account.name
+ });
+ })
+ .catch((error) => Observable.of(new resourceLimitActions.UpdateResourceLimitsError(error)));
+ });
+
+ @Effect({ dispatch: false })
+ updateResourceLimitsError$: Observable = this.actions$
+ .ofType(resourceLimitActions.UPDATE_RESOURCE_LIMITS_ERROR)
+ .do((action: resourceLimitActions.UpdateResourceLimitsError) => {
+ this.handleError(action.payload);
+ });
+
+ constructor(
+ private actions$: Actions,
+ private resourceLimitService: ResourceLimitService,
+ private dialogService: DialogService
+ ) { }
+
+ private handleError(error): void {
+ this.dialogService.alert({
+ message: {
+ translationToken: error.message,
+ interpolateParams: error.params
+ }
+ });
+ }
+
+}
diff --git a/src/app/reducers/resource-limit/redux/resource-limits.reducers.ts b/src/app/reducers/resource-limit/redux/resource-limits.reducers.ts
new file mode 100644
index 0000000000..00f8b1d035
--- /dev/null
+++ b/src/app/reducers/resource-limit/redux/resource-limits.reducers.ts
@@ -0,0 +1,106 @@
+import {
+ createFeatureSelector,
+ createSelector
+} from '@ngrx/store';
+import {
+ createEntityAdapter,
+ EntityAdapter,
+ EntityState
+} from '@ngrx/entity';
+import * as event from './resource-limits.actions';
+import { ResourceLimit } from '../../../shared/models/resource-limit.model';
+
+/**
+ * @ngrx/entity provides a predefined interface for handling
+ * a structured dictionary of records. This interface
+ * includes an array of ids, and a dictionary of the provided
+ * model type by id. This interface is extended to include
+ * any additional interface properties.
+ */
+export interface State extends EntityState {
+ loading: boolean
+}
+
+export interface ResourceLimitsState {
+ list: State;
+}
+
+export const resourceLimitsReducers = {
+ list: reducer,
+};
+
+/**
+ * createEntityAdapter creates many an object of helper
+ * functions for single or multiple operations
+ * against the dictionary of records. The configuration
+ * object takes a record id selector function and
+ * a sortComparer option which is set to a compare
+ * function if the records are to be sorted.
+ */
+export const adapter: EntityAdapter = createEntityAdapter({
+ selectId: (item: ResourceLimit) => item.resourcetype.toString(),
+ sortComparer: false
+});
+
+/** getInitialState returns the default initial state
+ * for the generated entity state. Initial state
+ * additional properties can also be defined.
+ */
+export const initialState: State = adapter.getInitialState({
+ loading: false
+});
+
+export function reducer(
+ state = initialState,
+ action: event.Actions
+): State {
+ switch (action.type) {
+ case event.LOAD_RESOURCE_LIMITS_REQUEST: {
+ return {
+ ...state,
+ loading: true
+ };
+ }
+ case event.LOAD_RESOURCE_LIMITS_RESPONSE: {
+
+ const resourceLimits = action.payload;
+
+ return {
+ /**
+ * The addMany function provided by the created adapter
+ * adds many records to the entity dictionary
+ * and returns a new state including those records. If
+ * the collection is to be sorted, the adapter will
+ * sort each record upon entry into the sorted array.
+ */
+ ...adapter.addAll(resourceLimits, state),
+ loading: false
+ };
+ }
+
+
+ default: {
+ return state;
+ }
+ }
+}
+
+
+export const getResourceLimitsState = createFeatureSelector('resourceLimits');
+
+export const getResourceLimitsEntitiesState = createSelector(
+ getResourceLimitsState,
+ state => state.list
+);
+
+export const {
+ selectIds,
+ selectEntities,
+ selectAll,
+ selectTotal,
+} = adapter.getSelectors(getResourceLimitsEntitiesState);
+
+export const isLoading = createSelector(
+ getResourceLimitsEntitiesState,
+ state => state.loading
+);
diff --git a/src/app/roles/redux/roles.actions.ts b/src/app/reducers/roles/redux/roles.actions.ts
similarity index 100%
rename from src/app/roles/redux/roles.actions.ts
rename to src/app/reducers/roles/redux/roles.actions.ts
diff --git a/src/app/roles/redux/roles.effects.ts b/src/app/reducers/roles/redux/roles.effects.ts
similarity index 56%
rename from src/app/roles/redux/roles.effects.ts
rename to src/app/reducers/roles/redux/roles.effects.ts
index 622cd9989b..cfb385cca8 100644
--- a/src/app/roles/redux/roles.effects.ts
+++ b/src/app/reducers/roles/redux/roles.effects.ts
@@ -1,11 +1,13 @@
import { Injectable } from '@angular/core';
-import { Actions, Effect } from '@ngrx/effects';
+import {
+ Actions,
+ Effect
+} from '@ngrx/effects';
import { Observable } from 'rxjs/Observable';
import * as roleActions from './roles.actions';
import { Action } from '@ngrx/store';
-import { RoleService } from '../../shared/services/role.service';
-import { Role } from '../../shared/models/role.model';
-import { AuthService } from '../../shared/services/auth.service';
+import { RoleService } from '../../../shared/services/role.service';
+import { Role } from '../../../shared/models/role.model';
@Injectable()
export class RolesEffects {
@@ -14,17 +16,15 @@ export class RolesEffects {
loadRoless$: Observable = this.actions$
.ofType(roleActions.LOAD_ROLES_REQUEST)
.switchMap((action: roleActions.LoadRolesRequest) => {
- return this.authService.isAdmin() ? this.roleService.getList(action.payload)
+ return this.roleService.getList(action.payload)
.map((roles: Role[]) => {
return new roleActions.LoadRolesResponse(roles);
})
- .catch(() => Observable.of(new roleActions.LoadRolesResponse([]))):
- Observable.of(new roleActions.LoadRolesResponse([]));
+ .catch(() => Observable.of(new roleActions.LoadRolesResponse([])));
});
constructor(
private actions$: Actions,
- private roleService: RoleService,
- private authService: AuthService
+ private roleService: RoleService
) { }
}
diff --git a/src/app/roles/redux/roles.reducers.ts b/src/app/reducers/roles/redux/roles.reducers.ts
similarity index 95%
rename from src/app/roles/redux/roles.reducers.ts
rename to src/app/reducers/roles/redux/roles.reducers.ts
index 7f0a4106ea..d5321ddb5e 100644
--- a/src/app/roles/redux/roles.reducers.ts
+++ b/src/app/reducers/roles/redux/roles.reducers.ts
@@ -8,7 +8,7 @@ import {
EntityState
} from '@ngrx/entity';
import * as event from './roles.actions';
-import { Role } from '../../shared/models/role.model';
+import { Role } from '../../../shared/models/role.model';
/**
* @ngrx/entity provides a predefined interface for handling
@@ -105,13 +105,8 @@ export const isLoading = createSelector(
state => state.loading
);
-export const roles = createSelector(
- selectAll,
- (roles) => roles
-);
-
export const roleTypes = createSelector(
- roles,
+ selectAll,
roles => Array.from(new Set(roles.map(role => role.type)))
);
diff --git a/src/app/shared/actions/account-actions/account-actions.component.html b/src/app/shared/actions/account-actions/account-actions.component.html
index 45886f21af..a81b12eb72 100644
--- a/src/app/shared/actions/account-actions/account-actions.component.html
+++ b/src/app/shared/actions/account-actions/account-actions.component.html
@@ -1,6 +1,6 @@
diff --git a/src/app/shared/actions/account-actions/account-actions.component.ts b/src/app/shared/actions/account-actions/account-actions.component.ts
index bf28f10bbd..5c8e72c2c3 100644
--- a/src/app/shared/actions/account-actions/account-actions.component.ts
+++ b/src/app/shared/actions/account-actions/account-actions.component.ts
@@ -1,7 +1,11 @@
-import { Component, EventEmitter, Input, Output } from '@angular/core';
+import {
+ Component,
+ EventEmitter,
+ Input,
+ Output
+} from '@angular/core';
import { BaseAccountAction } from './actions/base-account-action';
import { AccountActionsService } from './account-actions.service';
-import { AccountService } from '../../services/account.service';
import { Account } from '../../models/account.model';
@Component({
@@ -15,14 +19,14 @@ export class AccountActionsComponent {
public actions: Array;
constructor(
- private accountActionService: AccountActionsService,
- private accountService: AccountService
+ private accountActionService: AccountActionsService
) {
this.actions = this.accountActionService.actions;
this.onAccountChanged = new EventEmitter();
- this.accountService.onAccountUpdated.subscribe(
- (account) => this.onAccountChanged.emit(account)
- );
+ }
+
+ public activateAction(action: BaseAccountAction, account: Account) {
+ action.activate(account).subscribe(() => this.onAccountChanged.emit(account));
}
}
diff --git a/src/app/shared/models/resource-count.model.ts b/src/app/shared/models/resource-count.model.ts
index 5a289abeba..972de20ae0 100644
--- a/src/app/shared/models/resource-count.model.ts
+++ b/src/app/shared/models/resource-count.model.ts
@@ -1,7 +1,6 @@
import { BaseModel } from './base.model';
-import { FieldMapper } from '../decorators/field-mapper.decorator';
-export const enum ResourceType {
+/*export const enum ResourceType {
Instance, // Number of instances a user can create
IP, // Number of public IP addresses an account can own
Volume, // Number of disk volumes an account can own
@@ -18,12 +17,12 @@ export const enum ResourceType {
@FieldMapper({
resourcetype: 'resourceType'
-})
+})*/
export class ResourceCount extends BaseModel {
public account: string;
public domain: string;
public domainid: string;
public resourcecount: number;
- public resourcetype: ResourceType;
+ public resourcetype: number;
}
diff --git a/src/app/shared/models/resource-limit.model.ts b/src/app/shared/models/resource-limit.model.ts
index b9ec602d5d..00603e9f3c 100644
--- a/src/app/shared/models/resource-limit.model.ts
+++ b/src/app/shared/models/resource-limit.model.ts
@@ -1,5 +1,4 @@
import { BaseModel } from './base.model';
-import { FieldMapper } from '../decorators/field-mapper.decorator';
export const enum ResourceType {
Instance, // Number of instances a user can create
@@ -16,11 +15,8 @@ export const enum ResourceType {
SecondaryStorage // Total secondary storage space (in GiB) a user can use
}
-@FieldMapper({
- resourcetype: 'resourceType'
-})
export class ResourceLimit extends BaseModel {
public id: string;
public max: number;
- public resourceType: ResourceType;
+ public resourcetype: number;
}
diff --git a/src/app/shared/services/account.service.ts b/src/app/shared/services/account.service.ts
index b49f397235..d96fbda050 100644
--- a/src/app/shared/services/account.service.ts
+++ b/src/app/shared/services/account.service.ts
@@ -4,7 +4,6 @@ import { Account } from '../models/account.model';
import { BaseBackendService } from './base-backend.service';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
-import { Subject } from 'rxjs/Subject';
@Injectable()
@BackendResource({
@@ -12,7 +11,6 @@ import { Subject } from 'rxjs/Subject';
entityModel: Account
})
export class AccountService extends BaseBackendService {
- public onAccountUpdated = new Subject();
constructor(protected http: HttpClient) {
super(http);
@@ -29,7 +27,7 @@ export class AccountService extends BaseBackendService {
public removeAccount(account: Account): Observable {
return this.sendCommand('delete', {
id: account.id,
- }).map(() => this.onAccountUpdated.next(account));
+ });
}
public disableAccount(account: Account): Observable {
@@ -37,7 +35,7 @@ export class AccountService extends BaseBackendService {
account: account.name,
lock: false,
domainid: account.domainid
- }).map(() => this.onAccountUpdated.next(account));
+ });
}
public lockAccount(account: Account): Observable {
@@ -45,13 +43,13 @@ export class AccountService extends BaseBackendService {
account: account.name,
lock: true,
domainid: account.domainid
- }).map(() => this.onAccountUpdated.next(account));
+ });
}
public enableAccount(account: Account): Observable {
return this.sendCommand('enable', {
account: account.name,
domainid: account.domainid
- }).map(() => this.onAccountUpdated.next(account));
+ });
}
}
diff --git a/src/app/shared/services/configuration.service.ts b/src/app/shared/services/configuration.service.ts
index 09aadb274a..7ffdf68f83 100644
--- a/src/app/shared/services/configuration.service.ts
+++ b/src/app/shared/services/configuration.service.ts
@@ -5,7 +5,6 @@ import { BaseBackendService } from './base-backend.service';
import { Configuration } from '../models/configuration.model';
import { Observable } from 'rxjs/Observable';
import { Account } from '../models/account.model';
-import { AsyncJobService } from './async-job.service';
@Injectable()
@BackendResource({
@@ -13,17 +12,13 @@ import { AsyncJobService } from './async-job.service';
entityModel: Configuration
})
export class ConfigurationService extends BaseBackendService {
- constructor(protected http: HttpClient, private asyncJob: AsyncJobService) {
+ constructor(protected http: HttpClient) {
super(http);
}
- /*public update(accountid: string, name: string, value: any): Observable {
- return this.postRequest('update', { accountid, name, value });
- }*/
-
public updateConfiguration(
configuration: Configuration,
- account?: Account
+ account: Account
): Observable {
return this.sendCommand('update', {
accountid: account.id,
diff --git a/src/app/shared/services/resource-count.service.ts b/src/app/shared/services/resource-count.service.ts
index b007d0ef40..82c87bdc3d 100644
--- a/src/app/shared/services/resource-count.service.ts
+++ b/src/app/shared/services/resource-count.service.ts
@@ -3,7 +3,6 @@ import { BaseBackendCachedService } from './base-backend-cached.service';
import { BackendResource } from '../decorators/backend-resource.decorator';
import { Observable } from 'rxjs/Observable';
import { HttpClient } from '@angular/common/http';
-import { Account } from '../models/account.model';
import { ResourceCount } from '../models/resource-count.model';
@@ -18,11 +17,8 @@ export class ResourceCountService extends BaseBackendCachedService> {
- return this.sendCommand('update', {
- domainid: account.domainid,
- account: account.name
- }).map(response => this.formatGetListResponse(response).list);
+ return this.sendCommand('update', params).map(response => this.formatGetListResponse(response).list);
}
}
diff --git a/src/app/shared/services/resource-limit.service.ts b/src/app/shared/services/resource-limit.service.ts
index e682741cd4..f0eb0b8397 100644
--- a/src/app/shared/services/resource-limit.service.ts
+++ b/src/app/shared/services/resource-limit.service.ts
@@ -19,7 +19,7 @@ export class ResourceLimitService extends BaseBackendCachedService> {
return super.getList(params)
- .map(result => result.sort((a, b) => a.resourceType - b.resourceType));
+ .map(result => result.sort((a, b) => a.resourcetype - b.resourcetype));
}
public updateResourceLimit(
@@ -27,7 +27,7 @@ export class ResourceLimitService extends BaseBackendCachedService {
return this.sendCommand('update', {
- resourceType: resourceLimit.resourceType,
+ resourceType: resourceLimit.resourcetype,
max: resourceLimit.max,
domainid: account.domainid,
account: account.name
diff --git a/src/app/ssh-keys/containers/ssh-key-list.container.ts b/src/app/ssh-keys/containers/ssh-key-list.container.ts
index 1b9307308f..a8adc96a69 100644
--- a/src/app/ssh-keys/containers/ssh-key-list.container.ts
+++ b/src/app/ssh-keys/containers/ssh-key-list.container.ts
@@ -14,9 +14,9 @@ import { FilterService } from '../../shared/services/filter.service';
import { SSHKeyPair } from '../../shared/models/ssh-keypair.model';
import * as fromSshKeys from '../redux/ssh-key.reducers';
+import * as fromAccounts from '../../reducers/accounts/redux/accounts.reducers';
import * as sshKeyActions from '../redux/ssh-key.actions';
-import * as accountAction from '../../account/redux/accounts.actions';
-import * as fromAccounts from '../../account/redux/accounts.reducers';
+import * as accountActions from '../../reducers/accounts/redux/accounts.actions';
export const sshKeyListFilters = 'sshKeyListFilters';
@@ -27,7 +27,7 @@ export const sshKeyListFilters = 'sshKeyListFilters';
export class SshKeyListContainerComponent extends WithUnsubscribe() implements OnInit {
readonly sshKeyList$ = this.store.select(fromSshKeys.selectFilteredSshKeys);
readonly filters$ = this.store.select(fromSshKeys.filters);
- readonly accounts$ = this.store.select(fromAccounts.accounts);
+ readonly accounts$ = this.store.select(fromAccounts.selectAll);
readonly selectedGroupings$ = this.store.select(fromSshKeys.filterSelectedGroupings);
readonly selectedAccountIds$ = this.store.select(fromSshKeys.filterSelectedAccountIds);
@@ -62,7 +62,7 @@ export class SshKeyListContainerComponent extends WithUnsubscribe() implements O
}
public ngOnInit(): void {
- this.store.dispatch(new accountAction.LoadAccountsRequest());
+ this.store.dispatch(new accountActions.LoadAccountsRequest());
this.initFilters();
this.filters$
.takeUntil(this.unsubscribe$)
diff --git a/src/app/ssh-keys/redux/ssh-key.reducers.ts b/src/app/ssh-keys/redux/ssh-key.reducers.ts
index ec39f0c444..67072dc7ec 100644
--- a/src/app/ssh-keys/redux/ssh-key.reducers.ts
+++ b/src/app/ssh-keys/redux/ssh-key.reducers.ts
@@ -8,7 +8,8 @@ import {
createFeatureSelector,
createSelector
} from '@ngrx/store';
-import { accounts } from '../../account/redux/accounts.reducers';
+
+import * as fromAccounts from '../../reducers/accounts/redux/accounts.reducers';
import * as sshKey from './ssh-key.actions';
@@ -193,12 +194,13 @@ export const filterSelectedAccountIds = createSelector(
export const selectFilteredSshKeys = createSelector(
selectAll,
filterSelectedAccountIds,
- accounts,
+ fromAccounts.selectAll,
(sshKeys, selectedAccountIds, accounts) => {
- const selectedAccounts = accounts.filter(account => selectedAccountIds.find(id => id === account.id));
- const accountsMap = selectedAccounts.reduce((m, i) => ({...m, [i.name]: i }), {});
- const domainsMap = selectedAccounts.reduce((m, i) => ({...m, [i.domainid]: i }), {});
+ const selectedAccounts = accounts.filter(
+ account => selectedAccountIds.find(id => id === account.id));
+ const accountsMap = selectedAccounts.reduce((m, i) => ({ ...m, [i.name]: i }), {});
+ const domainsMap = selectedAccounts.reduce((m, i) => ({ ...m, [i.domainid]: i }), {});
const selectedAccountIdsFilter = sshKey => !selectedAccountIds.length ||
(accountsMap[sshKey.account] && domainsMap[sshKey.domainid]);
diff --git a/src/app/ssh-keys/ssh-key-list-item/ssh-key-list-item.component.ts b/src/app/ssh-keys/ssh-key-list-item/ssh-key-list-item.component.ts
index 1a8db24c06..b1146faae7 100644
--- a/src/app/ssh-keys/ssh-key-list-item/ssh-key-list-item.component.ts
+++ b/src/app/ssh-keys/ssh-key-list-item/ssh-key-list-item.component.ts
@@ -1,4 +1,10 @@
-import { Component, EventEmitter, Input, Output, ViewChild } from '@angular/core';
+import {
+ Component,
+ EventEmitter,
+ Input,
+ Output,
+ ViewChild
+} from '@angular/core';
import { MatMenuTrigger } from '@angular/material';
import { SSHKeyPair } from '../../shared/models/ssh-keypair.model';
@@ -12,12 +18,12 @@ export class SshKeyListItemComponent {
@Input() public item: SSHKeyPair;
@Output() public onClick = new EventEmitter();
@Output() public onRemove = new EventEmitter();
- @ViewChild(MatMenuTrigger) public mdMenuTrigger: MatMenuTrigger;
+ @ViewChild(MatMenuTrigger) public matMenuTrigger: MatMenuTrigger;
public onClicked(e: MouseEvent): void {
e.stopPropagation();
- if (!this.mdMenuTrigger || !this.mdMenuTrigger.menuOpen) {
+ if (!this.matMenuTrigger || !this.matMenuTrigger.menuOpen) {
this.onClick.emit(this.item);
}
}
diff --git a/src/app/tags/tag/tag.component.scss b/src/app/tags/tag/tag.component.scss
index 3c5538cbd8..a2afef7419 100644
--- a/src/app/tags/tag/tag.component.scss
+++ b/src/app/tags/tag/tag.component.scss
@@ -9,7 +9,6 @@
overflow: hidden;
text-overflow: ellipsis;
cursor: pointer;
- max-width: 34% !important;
text-align: right;
white-space: nowrap;
}
@@ -21,14 +20,11 @@
}
.left {
- max-width: 66% !important;
- min-width: 66% !important;
margin-right: 15px;
}
.buttons {
display: none;
- min-width: 68px;
margin-left: 10px;
}
@@ -43,5 +39,5 @@
}
.container:hover .buttons {
- display: inline-block;
+ display: flex;
}
diff --git a/src/app/template/template/template.component.ts b/src/app/template/template/template.component.ts
index 7d247e8087..d6e72fdb8d 100644
--- a/src/app/template/template/template.component.ts
+++ b/src/app/template/template/template.component.ts
@@ -25,7 +25,7 @@ export class TemplateComponent implements OnChanges {
@Input() public searchQuery: () => string;
@Output() public deleteTemplate = new EventEmitter();
@Output() public onClick = new EventEmitter();
- @ViewChild(MatMenuTrigger) public mdMenuTrigger: MatMenuTrigger;
+ @ViewChild(MatMenuTrigger) public matMenuTrigger: MatMenuTrigger;
public query: string;
@@ -40,7 +40,7 @@ export class TemplateComponent implements OnChanges {
public handleClick(e: MouseEvent): void {
e.stopPropagation();
- if (!this.mdMenuTrigger || !this.mdMenuTrigger.menuOpen) {
+ if (!this.matMenuTrigger || !this.matMenuTrigger.menuOpen) {
this.onClick.emit(this.item);
}
}
diff --git a/src/app/vm/vm-list/vm-list-item.component.ts b/src/app/vm/vm-list/vm-list-item.component.ts
index 541db9c57a..baad849b89 100644
--- a/src/app/vm/vm-list/vm-list-item.component.ts
+++ b/src/app/vm/vm-list/vm-list-item.component.ts
@@ -46,7 +46,7 @@ export class VmListItemComponent implements OnInit, OnChanges {
@Input() public item: VirtualMachine;
@Input() public isSelected: (vm: VirtualMachine) => boolean;
@Output() public onClick = new EventEmitter();
- @ViewChild(MatMenuTrigger) public mdMenuTrigger: MatMenuTrigger;
+ @ViewChild(MatMenuTrigger) public matMenuTrigger: MatMenuTrigger;
public color: Color;
public gigabyte = Math.pow(2, 10); // to compare with RAM which is in megabytes
@@ -103,7 +103,7 @@ export class VmListItemComponent implements OnInit, OnChanges {
public handleClick(e: MouseEvent): void {
e.stopPropagation();
- if (!this.mdMenuTrigger.menuOpen) {
+ if (!this.matMenuTrigger.menuOpen) {
this.onClick.emit(this.item);
}
}
diff --git a/src/app/volume/volume-item/volume-item.component.ts b/src/app/volume/volume-item/volume-item.component.ts
index 381e0a7d6a..003b7190a4 100644
--- a/src/app/volume/volume-item/volume-item.component.ts
+++ b/src/app/volume/volume-item/volume-item.component.ts
@@ -1,7 +1,19 @@
-import { Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges, ViewChild } from '@angular/core';
+import {
+ Component,
+ EventEmitter,
+ Input,
+ OnChanges,
+ OnInit,
+ Output,
+ SimpleChanges,
+ ViewChild
+} from '@angular/core';
import { MatMenuTrigger } from '@angular/material';
import { VolumeActionsService } from '../../shared/actions/volume-actions/volume-actions.service';
-import { DiskOffering, Volume } from '../../shared/models';
+import {
+ DiskOffering,
+ Volume
+} from '../../shared/models';
import { VolumeType } from '../../shared/models/volume.model';
import { DiskOfferingService } from '../../shared/services/disk-offering.service';
import { ZoneService } from '../../shared/services/zone.service';
@@ -18,7 +30,7 @@ export class VolumeItemComponent extends VolumeItem implements OnInit, OnChanges
@Input() public searchQuery: () => string;
@Input() public item: Volume;
@Output() public onClick = new EventEmitter();
- @ViewChild(MatMenuTrigger) public mdMenuTrigger: MatMenuTrigger;
+ @ViewChild(MatMenuTrigger) public matMenuTrigger: MatMenuTrigger;
public diskOfferings: Array;
public query: string;
@@ -61,7 +73,7 @@ export class VolumeItemComponent extends VolumeItem implements OnInit, OnChanges
public handleClick(e: MouseEvent): void {
e.stopPropagation();
- if (!this.mdMenuTrigger.menuOpen) {
+ if (!this.matMenuTrigger.menuOpen) {
this.onClick.emit(this.item);
}
}