Skip to content

Commit e12278f

Browse files
authored
Added validation for required fields in Test console. (#475)
1 parent 756e6ad commit e12278f

File tree

5 files changed

+77
-32
lines changed

5 files changed

+77
-32
lines changed

src/components/operations/operation-details/ko/runtime/operation-console.html

Lines changed: 39 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -56,26 +56,34 @@ <h3>Authorization</h3>
5656
</div>
5757
</div>
5858
</div>
59-
59+
6060
<h4>Parameters</h4>
6161
<!-- ko if: (templateParameters && templateParameters().length > 0) || (request.queryParameters && request.queryParameters().length > 0) -->
6262
<div data-bind="foreach: { data: templateParameters, as: 'parameter' }">
6363
<div class="row flex flex-row">
6464
<div class="col-4">
6565
<div class="form-group">
66-
<input type="text" readonly autocomplete="off" class="form-control form-control-sm"
67-
placeholder="name" spellcheck="false"
68-
data-bind="event: { keyup: $component.updateRequestSummary }, textInput: parameter.name, valueUpdate: 'keyup'">
66+
<div class="input-group">
67+
<input type="text" readonly autocomplete="off" class="form-control form-control-sm"
68+
placeholder="name" spellcheck="false"
69+
data-bind="event: { keyup: $component.updateRequestSummary }, textInput: parameter.name">
70+
<span class="invalid-feedback" data-bind="validationMessage: parameter.name"></span>
71+
</div>
6972
</div>
7073
</div>
7174
<div class="col-6">
7275
<div class="form-group">
7376
<!-- ko if: parameter.options.length > 0 -->
74-
<select class="form-control" data-bind="value: parameter.value, options: parameter.options, optionsAfterRender: $component.updateRequestSummary, event:{ change: $component.updateRequestSummary }"></select>
77+
<select class="form-control"
78+
data-bind="value: parameter.value, options: parameter.options, optionsAfterRender: $component.updateRequestSummary, event:{ change: $component.updateRequestSummary }"></select>
7579
<!-- /ko -->
7680
<!-- ko if: parameter.options.length === 0 -->
77-
<input type="text" autocomplete="off" class="form-control form-control-sm" placeholder="value"
78-
spellcheck="false" data-bind="event: { keyup: $component.updateRequestSummary }, textInput: parameter.value, valueUpdate: 'keyup'">
81+
<div class="input-group">
82+
<input type="text" autocomplete="off" class="form-control form-control-sm" placeholder="value"
83+
spellcheck="false"
84+
data-bind="event: { keyup: $component.updateRequestSummary }, textInput: parameter.value">
85+
<span class="invalid-feedback" data-bind="validationMessage: parameter.value"></span>
86+
</div>
7987
<!-- /ko -->
8088
</div>
8189
</div>
@@ -85,18 +93,23 @@ <h4>Parameters</h4>
8593
<div class="row flex flex-row">
8694
<div class="col-4">
8795
<div class="form-group">
88-
<input type="text" autocomplete="off" class="form-control form-control-sm" placeholder="name"
89-
spellcheck="false" data-bind="textInput: parameter.name, valueUpdate: 'keyup'">
96+
<div class="input-group">
97+
<input type="text" autocomplete="off" class="form-control form-control-sm" placeholder="name"
98+
spellcheck="false" data-bind="textInput: parameter.name">
99+
<span class="invalid-feedback" data-bind="validationMessage: parameter.name"></span>
100+
</div>
90101
</div>
91102
</div>
92103
<div class="col-6">
93104
<div class="form-group">
94105
<!-- ko if: parameter.options.length > 0 -->
95-
<select class="form-control" data-bind="value: parameter.value, options: parameter.options, optionsAfterRender: $component.updateRequestSummary, event:{ change: $component.updateRequestSummary }"></select>
106+
<select class="form-control"
107+
data-bind="value: parameter.value, options: parameter.options, optionsAfterRender: $component.updateRequestSummary, event:{ change: $component.updateRequestSummary }"></select>
96108
<!-- /ko -->
97109
<!-- ko if: parameter.options.length === 0 -->
98110
<input type="text" autocomplete="off" class="form-control form-control-sm" placeholder="value"
99-
spellcheck="false" data-bind="event: { keyup: $component.updateRequestSummary }, textInput: parameter.value, valueUpdate: 'keyup'">
111+
spellcheck="false"
112+
data-bind="event: { keyup: $component.updateRequestSummary }, textInput: parameter.value">
100113
<!-- /ko -->
101114
</div>
102115
</div>
@@ -111,7 +124,7 @@ <h4>Parameters</h4>
111124
<i class="icon icon-plus"></i>
112125
Add parameter
113126
</a>
114-
127+
115128

116129
<!-- ko if: request.headers().length > 0 -->
117130
<h3>Headers</h3>
@@ -120,22 +133,29 @@ <h3>Headers</h3>
120133
<div class="row flex flex-row">
121134
<div class="col-4">
122135
<div class="form-group">
123-
<input type="text" autocomplete="off" class="form-control form-control-sm" placeholder="name"
124-
spellcheck="false" data-bind="textInput: header.name, valueUpdate: 'keyup'">
136+
<div class="input-group">
137+
<input type="text" autocomplete="off" class="form-control form-control-sm" placeholder="name"
138+
spellcheck="false" data-bind="textInput: header.name">
139+
<span class="invalid-feedback" data-bind="validationMessage: header.name"></span>
140+
</div>
125141
</div>
126142
</div>
127143
<div class="col-6">
128144
<div class="form-group">
129145
<!-- ko if: header.options && header.options.length > 0 -->
130-
<select class="form-control" data-bind="value: header.value, options: header.options, optionsAfterRender: $component.updateRequestSummary, event:{ change: $component.updateRequestSummary }"></select>
146+
<select class="form-control"
147+
data-bind="value: header.value, options: header.options, optionsAfterRender: $component.updateRequestSummary, event:{ change: $component.updateRequestSummary }"></select>
131148
<!-- /ko -->
132149
<!-- ko if: !header.options || header.options.length === 0 -->
133-
<input type="text" autocomplete="off" class="form-control form-control-sm" placeholder="value"
134-
spellcheck="false"
135-
data-bind="event: { keyup: $component.updateRequestSummary }, textInput: header.value, valueUpdate: 'keyup'">
150+
<div class="input-group">
151+
<input type="text" autocomplete="off" class="form-control form-control-sm" placeholder="value"
152+
spellcheck="false"
153+
data-bind="event: { keyup: $component.updateRequestSummary }, textInput: header.value">
154+
<span class="invalid-feedback" data-bind="validationMessage: header.value"></span>
155+
</div>
136156
<!-- /ko -->
137157

138-
158+
139159
</div>
140160
</div>
141161
<div class="col-2 button-remove">

src/components/operations/operation-details/ko/runtime/operation-console.ts

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import * as ko from "knockout";
2+
import * as validation from "knockout.validation";
23
import * as _ from "lodash";
34
import template from "./operation-console.html";
45
import { Component, Param, OnMounted } from "@paperbits/common/ko/decorators";
@@ -77,8 +78,13 @@ export class OperationConsole {
7778
this.sendingRequest = ko.observable(false);
7879
this.codeSample = ko.observable();
7980
this.selectedProduct = ko.observable();
80-
}
8181

82+
validation.init({
83+
insertMessages: false,
84+
errorElementClass: "is-invalid",
85+
decorateInputElement: true
86+
});
87+
}
8288

8389
@Param()
8490
public api: ko.Observable<Api>;
@@ -331,7 +337,18 @@ export class OperationConsole {
331337
}
332338

333339
public async validateAndSendRequest(): Promise<void> {
334-
// TODO: Add request validation.
340+
const templateParameters = this.consoleOperation().templateParameters();
341+
const queryParameters = this.consoleOperation().request.queryParameters();
342+
const headers = this.consoleOperation().request.headers();
343+
const parameters = [].concat(templateParameters, queryParameters, headers);
344+
const validationGroup = validation.group(parameters.map(x => x.value), { live: true });
345+
const clientErrors = validationGroup();
346+
347+
if (clientErrors.length > 0) {
348+
validationGroup.showAllMessages();
349+
return;
350+
}
351+
335352
this.sendRequest();
336353
}
337354

src/models/console/consoleHeader.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,12 @@ export class ConsoleHeader {
4848
this.type = contract.type;
4949
this.secret = false;
5050
this.inputTypeValue = this.secret && !this.revealed ? "password" : "text";
51+
52+
this.name.extend(<any>{ required: { message: `Name is required.` } });
53+
54+
if (this.required) {
55+
this.value.extend(<any>{ required: { message: `Value is required.` } });
56+
}
5157
}
5258

5359
public toggleSecret(): void {

src/models/console/consoleOperation.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ export class ConsoleOperation {
5454
return uri + separator + paramString;
5555
}
5656

57-
5857
public setHeader(name: string, value: string, type: string = "string", description?: string): ConsoleHeader {
5958
const header = this.createHeader(name, value, type, description);
6059

@@ -87,13 +86,14 @@ export class ConsoleOperation {
8786
parameters.forEach(parameter => {
8887
if (parameter.value()) {
8988
const parameterPlaceholder = `{${parameter.name}}`;
89+
const parameterName = encodeURIComponent(parameter.name());
9090
const parameterValue = encodeURIComponent(parameter.value());
9191

9292
if (requestUrl.indexOf(parameterPlaceholder) > -1) {
9393
requestUrl = requestUrl.replace(parameterPlaceholder, parameterValue);
9494
}
9595
else {
96-
requestUrl = this.addParam(requestUrl, parameter.name, parameterValue);
96+
requestUrl = this.addParam(requestUrl, parameterName, parameterValue);
9797
}
9898
}
9999
});
@@ -104,4 +104,5 @@ export class ConsoleOperation {
104104

105105
return `${this.api.path}${versionPath}${revision}${requestUrl}`;
106106
}
107+
107108
}
Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import * as ko from "knockout";
22
import { Parameter } from "../parameter";
33

4+
45
export class ConsoleParameter {
5-
public name: string;
6+
public name: ko.Observable<string>;
67
public value: ko.Observable<string>;
78
public required: boolean;
89
public options: string[];
@@ -11,19 +12,21 @@ export class ConsoleParameter {
1112
public custom: boolean;
1213
public inputType: string;
1314
public canRename: boolean;
15+
public error: ko.Observable<string>;
1416

1517
constructor(contract?: Parameter) {
16-
this.name = "";
18+
this.name = ko.observable();
1719
this.value = ko.observable();
1820
this.inputType = "text";
1921
this.required = false;
2022
this.options = [];
2123
this.custom = true;
2224
this.type = "string";
25+
this.error = ko.observable();
2326

2427
if (contract) {
2528
this.custom = false;
26-
this.name = contract.name;
29+
this.name(contract.name);
2730
this.value(contract.defaultValue);
2831
this.required = contract.required;
2932
this.options = contract.values;
@@ -33,13 +36,11 @@ export class ConsoleParameter {
3336
}
3437

3538
this.canRename = !this.required && this.custom;
36-
}
3739

38-
public nameIsValid(): boolean {
39-
return name !== null && name !== "";
40-
}
40+
this.name.extend(<any>{ required: { message: `Name is required.` } });
4141

42-
public valueIsValid(): boolean {
43-
return this.value() !== null && this.value() !== "";
42+
if (this.required) {
43+
this.value.extend(<any>{ required: { message: `Value is required.` } });
44+
}
4445
}
4546
}

0 commit comments

Comments
 (0)