Skip to content

Commit

Permalink
Server details page - UI should have the option to update the WebUI k…
Browse files Browse the repository at this point in the history
…ey (#6440)

* added changes to update the webui key on server details page

Signed-off-by: Vinay Sharma <vsharma@chef.io>

* added some minor changes

Signed-off-by: Vinay Sharma <vsharma@chef.io>
  • Loading branch information
vinay033 committed Apr 22, 2022
1 parent 3ef3c05 commit 6956ad1
Show file tree
Hide file tree
Showing 10 changed files with 114 additions and 129 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ export class GetServersSuccess implements Action {

export class GetServersFailure implements Action {
readonly type = ServerActionTypes.GET_ALL_FAILURE;

constructor(public payload: HttpErrorResponse) { }
}

Expand Down Expand Up @@ -79,26 +80,31 @@ export interface CreateServerPayload {

export class CreateServer implements Action {
readonly type = ServerActionTypes.CREATE;

constructor(public payload: CreateServerPayload) { }
}

export class CreateServerSuccess implements Action {
readonly type = ServerActionTypes.CREATE_SUCCESS;

constructor(public payload: ServerSuccessPayload) { }
}

export class CreateServerFailure implements Action {
readonly type = ServerActionTypes.CREATE_FAILURE;

constructor(public payload: HttpErrorResponse) { }
}

export class DeleteServer implements Action {
readonly type = ServerActionTypes.DELETE;

constructor(public payload: { id: string, name: string }) { }
}

export class DeleteServerSuccess implements Action {
readonly type = ServerActionTypes.DELETE_SUCCESS;

constructor(public payload: { id: string, name: string }) { }
}

Expand Down Expand Up @@ -136,17 +142,14 @@ export class GetUsers implements Action {

export class GetUsersSuccess implements Action {
readonly type = ServerActionTypes.GET_USERS_SUCCESS;

constructor(public payload: UsersSuccessPayload) { }
}

export class GetUsersFailure implements Action {
readonly type = ServerActionTypes.GET_USERS_FAILURE;
constructor(public payload: HttpErrorResponse) { }
}

export interface WebUIKeyPayload {
server_id: any;
key: string;
constructor(public payload: HttpErrorResponse) { }
}

export class UpdateWebUIKey implements Action {
Expand All @@ -158,7 +161,7 @@ export class UpdateWebUIKey implements Action {
export class UpdateWebUIKeySuccess implements Action {
readonly type = ServerActionTypes.UPDATE_WEB_UI_KEY_SUCCESS;

constructor(public payload: WebUIKeyPayload) { }
constructor(public payload: WebUIKey) { }
}

export class UpdateWebUIKeyFailure implements Action {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@ import {
UsersSuccessPayload,
UpdateWebUIKey,
UpdateWebUIKeySuccess,
UpdateWebUIKeyFailure,
WebUIKeyPayload
UpdateWebUIKeyFailure
} from './server.actions';

import {
Expand Down Expand Up @@ -195,17 +194,17 @@ export class ServerEffects {

UpdateWebUIKey$ = createEffect(() => this.actions$.pipe(
ofType(ServerActionTypes.UPDATE_WEB_UI_KEY),
mergeMap(({ payload}: UpdateWebUIKey) =>
mergeMap(({ payload }: UpdateWebUIKey) =>
this.requests.updateWebUIKey(payload).pipe(
map((resp: WebUIKeyPayload) => new UpdateWebUIKeySuccess(resp)),
map((resp) => new UpdateWebUIKeySuccess(resp)),
catchError((error: HttpErrorResponse) =>
observableOf(new UpdateWebUIKeyFailure(error)))))));

UpdateWebUIKeySuccess$ = createEffect(() => this.actions$.pipe(
ofType(ServerActionTypes.UPDATE_WEB_UI_KEY_SUCCESS),
map(({ payload: webuikey }: UpdateWebUIKeySuccess) => new CreateNotification({
map(() => new CreateNotification({
type: Type.info,
message: `Successfully updated Web UI Key ${webuikey.server_id}.`
message: 'Successfully updated Web UI Key.'
}))));

UpdateWebUIKeyFailure$ = createEffect(() => this.actions$.pipe(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@ export interface User {
}

export interface WebUIKey {
server_id: string;
key: string;
id: string;
webui_key: string;
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { mapKeys, snakeCase } from 'lodash/fp';

import { environment as env } from 'environments/environment';
import { Server, User, WebUIKey } from './server.model';
import { CreateServerPayload, ServerSuccessPayload, WebUIKeyPayload } from './server.actions';
import { CreateServerPayload, ServerSuccessPayload } from './server.actions';

export interface ServersResponse {
servers: Server[];
Expand Down Expand Up @@ -52,7 +52,7 @@ export class ServerRequests {

// Need to change API endpoint for update WebUIKey
public updateWebUIKey(payload): Observable<WebUIKey> {
return this.http.put<WebUIKeyPayload>
(`${env.infra_proxy_url}/servers/${payload.server_id}`, payload.key);
return this.http.post<WebUIKey>
(`${env.infra_proxy_url}/servers/update`, payload);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@
<img *ngIf="!isValid" src="../../../../assets/img/warning.png" alt="warning" />
<span *ngIf="!isValid" class="invalidStatus">Invalid</span>
<span class="update-link" data-cy="open-WebKey-slider">
<a
<a
data-cy="update-web-ui-key"
(click)="webUIKeySlider.slidePanel()"
>Update</a>
</span>
Expand Down Expand Up @@ -226,8 +227,13 @@
<p data-cy="no-records">No Organization available.</p>
</div>
</section>
<app-update-web-uikey-slider
#webUIKeySlider>
<app-update-web-uikey-slider
#webUIKeySlider
[updating]="updatingWebuiKey"
[updateWebuiKeyForm]="updateWebuiKeyForm"
[conflictErrorEvent]="conflictErrorEvent"
[updatingWebuiKey]="updatingWebuiKey"
(updateWebuiKeyClicked)="updateWebuiKey()">
</app-update-web-uikey-slider>
</main>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ import { Regex } from 'app/helpers/auth/regex';
import { LayoutFacadeService, Sidebar } from 'app/entities/layout/layout.facade';
import { pending, EntityStatus, allLoaded } from 'app/entities/entities';
import {
getStatus, serverFromRoute, updateStatus, getUsers, getUsersStatus
getStatus, serverFromRoute, updateStatus, getUsers, getUsersStatus, updateWebUIKey
} from 'app/entities/servers/server.selectors';

import { Server } from 'app/entities/servers/server.model';
import { GetServer, UpdateServer
import { Server, WebUIKey } from 'app/entities/servers/server.model';
import { GetServer, UpdateServer, UpdateWebUIKey
// , GetUsers
} from 'app/entities/servers/server.actions';
import { GetOrgs, CreateOrg, DeleteOrg } from 'app/entities/orgs/org.actions';
Expand Down Expand Up @@ -68,6 +68,12 @@ export class ChefServerDetailsComponent implements OnInit, OnDestroy {
public authFailure = false;
public isValid = false;


public updateWebuiKeyForm: FormGroup;
public updatingWebuiKey = false;
public webuiKey: WebUIKey;
public updateWebUIKeySuccessful = false;

constructor(
private fb: FormBuilder,
private store: Store<NgrxStateAtom>,
Expand All @@ -84,6 +90,10 @@ export class ChefServerDetailsComponent implements OnInit, OnDestroy {
admin_key: ['', [Validators.required]],
projects: [[]]
});

this.updateWebuiKeyForm = this.fb.group({
webUiKey: ['', [Validators.required]]
});
}

ngOnInit() {
Expand Down Expand Up @@ -220,6 +230,17 @@ export class ChefServerDetailsComponent implements OnInit, OnDestroy {
this.isUserLoaded = false;
}
});

this.store.select(updateWebUIKey).pipe(
takeUntil(this.isDestroyed),
filter(state => this.updatingWebuiKey && !pending(state)))
.subscribe((state) => {
this.updatingWebuiKey = false;
this.updateWebUIKeySuccessful = (state === EntityStatus.loadingSuccess);
if (this.updateWebUIKeySuccessful) {
this.isValid = true;
}
});
}

ngOnDestroy(): void {
Expand Down Expand Up @@ -292,4 +313,18 @@ export class ChefServerDetailsComponent implements OnInit, OnDestroy {
};
this.store.dispatch(new UpdateServer({server: updatedServer}));
}


public updateWebuiKey(): void {
this.updatingWebuiKey = true;
this.webuiKey = {
id: this.id,
webui_key: this.updateWebuiKeyForm.controls['webUiKey'].value
};
this.updatingWebuiKeyData(this.webuiKey);
this.updateWebuiKeyForm.reset();
}
private updatingWebuiKeyData(webuikey: WebUIKey) {
this.store.dispatch(new UpdateWebUIKey(webuikey));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ <h1 data-cy="title" slot="title">Update Web UI Key</h1>
<chef-icon>close</chef-icon>
</chef-button>
</div>
<form [formGroup]="updateKeyForm">
<form [formGroup]="updateWebuiKeyForm">
<div class="sidenav-body">
<div class="id-margin">
<chef-form-field>
Expand All @@ -22,11 +22,11 @@ <h1 data-cy="title" slot="title">Update Web UI Key</h1>
type="text"
autocomplete="off"
(keyup)="handleInput($event)"
data-cy="enter-key">
data-cy="enter-webui-key">
</textarea>
</label>
<chef-error class="textarea-error"
*ngIf="updateKeyForm.get('webUiKey').hasError('required') && updateKeyForm.get('webUiKey').dirty">
*ngIf="updateWebuiKeyForm.get('webUiKey').hasError('required') && updateWebuiKeyForm.get('webUiKey').dirty">
WEB UI KEY is required.
</chef-error>
</chef-form-field>
Expand All @@ -35,13 +35,13 @@ <h1 data-cy="title" slot="title">Update Web UI Key</h1>
</div>
<div class="button-bar">
<chef-button tertiary data-cy="cancel" (click)="closeUpdateModal()">Cancel</chef-button>
<chef-button primary data-cy="Upload"
[disabled]="!updateKeyForm?.valid || conflictError || updating"
<chef-button primary data-cy="update-webui-key-button"
[disabled]="!updateWebuiKeyForm?.valid || conflictError || updatingWebuiKey"
id="upload-button-object-modal"
(click)="uploadWebUIKey()">
<chef-loading-spinner *ngIf="updating"></chef-loading-spinner>
<span *ngIf="!updating">Upload Web UI Key</span>
<span *ngIf="updating">Uploading Web UI Key</span>
(click)="updateWebUIkey()">
<chef-loading-spinner *ngIf="updatingWebuiKey"></chef-loading-spinner>
<span *ngIf="!updatingWebuiKey">Upload Web UI Key</span>
<span *ngIf="updatingWebuiKey">Uploading Web UI Key</span>
</chef-button>
</div>
</form>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { Regex } from 'app/helpers/auth/regex';
import { using } from 'app/testing/spec-helpers';
import { WebUIKey } from 'app/entities/servers/server.model';
import { UpdateWebUIKeyFailure, UpdateWebUIKeySuccess, WebUIKeyPayload } from 'app/entities/servers/server.actions';
import { UpdateWebUIKeyFailure, UpdateWebUIKeySuccess } from 'app/entities/servers/server.actions';
import { HttpStatus } from 'app/types/types';
import { HttpErrorResponse } from '@angular/common/http';

Expand Down Expand Up @@ -46,11 +46,11 @@ describe('UpdateWebUIKeySliderComponent', () => {
beforeEach(() => {
fixture = TestBed.createComponent(UpdateWebUIKeySliderComponent);
component = fixture.componentInstance;
component.updateKeyForm = new FormBuilder().group({
component.updateWebuiKeyForm = new FormBuilder().group({
webuikey: ['', [Validators.required, Validators.pattern(Regex.patterns.NON_BLANK),
Validators.pattern(Regex.patterns.NO_WILDCARD_ALLOW_HYPHEN)]]
});
updateKeyForm = component.updateKeyForm;
updateKeyForm = component.updateWebuiKeyForm;
fixture.detectChanges();
});

Expand All @@ -71,6 +71,7 @@ describe('UpdateWebUIKeySliderComponent', () => {
expect(updateKeyForm.valid).toBeFalsy();
expect(errors['required']).toBeTruthy();
});
});

describe('the form should be valid', () => {
it('when all inputs are filled and valid', () => {
Expand Down Expand Up @@ -101,13 +102,8 @@ describe('UpdateWebUIKeySliderComponent', () => {
describe('#webuikey', () => {
let store: Store<NgrxStateAtom>;
const webuikey: WebUIKey = {
server_id: 'test_server',
key: 'test_webuikey'
};

const key: WebUIKeyPayload = {
server_id: 'test_server',
key: 'test_webuikey'
id: 'test_server',
webui_key: 'test_webuikey'
};

beforeEach(() => {
Expand All @@ -120,25 +116,24 @@ describe('UpdateWebUIKeySliderComponent', () => {
});

it('should be invalid when no fields are filled out', () => {
expect(component.updateKeyForm.valid).toBeFalsy();
expect(component.updateWebuiKeyForm.valid).toBeFalsy();
});

it('should be valid when all fields are filled out', () => {
component.updateKeyForm.controls['webuikey'].setValue(webuikey.key);
expect(component.updateKeyForm.valid).toBeTruthy();
component.updateWebuiKeyForm.controls['webuikey'].setValue(webuikey.webui_key);
expect(component.updateWebuiKeyForm.valid).toBeTruthy();
});

it('hide slider after updating webuikey.', () => {
component.updateKeyForm.controls['webuikey'].setValue(webuikey.key);
component.onSubmit();
component.updateWebuiKeyForm.controls['webuikey'].setValue(webuikey.webui_key);
component.updateWebUIkey();

store.dispatch(new UpdateWebUIKeySuccess(
{ server_id: key.server_id, key: key.key}));
store.dispatch(new UpdateWebUIKeySuccess(webuikey));
});

it('on create , slider is closed with failure banner', () => {
component.updateKeyForm.controls['webuikey'].setValue(webuikey.key);
component.onSubmit();
component.updateWebuiKeyForm.controls['webuikey'].setValue(webuikey.webui_key);
component.updateWebUIkey();

const error = <HttpErrorResponse>{
status: HttpStatus.INTERNAL_SERVER_ERROR,
Expand All @@ -148,5 +143,4 @@ describe('UpdateWebUIKeySliderComponent', () => {
expect(component.conflictError).toBe(false);
});
});
});
});
Loading

0 comments on commit 6956ad1

Please sign in to comment.