"tslib": "^1.9.0"
}
},
+ "ng-bootstrap-form-validation": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/ng-bootstrap-form-validation/-/ng-bootstrap-form-validation-4.0.0.tgz",
+ "integrity": "sha512-Whoc9To21hKMtI+yZRVsS19TJMKd5OFVsxJS42LvcOls/uNQBT7LYmS3CGWlwDSGOo85utx3hDHuGzjb78AIoA==",
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ },
"ng2-charts": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/ng2-charts/-/ng2-charts-1.6.0.tgz",
"lodash": "4.17.11",
"moment": "2.24.0",
"ng-block-ui": "2.1.1",
+ "ng-bootstrap-form-validation": "4.0.0",
"ng2-charts": "1.6.0",
"ng2-tree": "2.0.0-rc.11",
"ngx-bootstrap": "4.3.0",
import { JwtModule } from '@auth0/angular-jwt';
import { I18n } from '@ngx-translate/i18n-polyfill';
import { BlockUIModule } from 'ng-block-ui';
+import { NgBootstrapFormValidationModule } from 'ng-bootstrap-form-validation';
import { AccordionModule } from 'ngx-bootstrap/accordion';
import { BsDropdownModule } from 'ngx-bootstrap/dropdown';
import { TabsModule } from 'ngx-bootstrap/tabs';
config: {
tokenGetter: jwtTokenGetter
}
- })
+ }),
+ NgBootstrapFormValidationModule.forRoot()
],
exports: [SharedModule],
providers: [
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { RouterModule, Routes } from '@angular/router';
+import { NgBootstrapFormValidationModule } from 'ng-bootstrap-form-validation';
import { TreeModule } from 'ng2-tree';
import { BsDatepickerModule } from 'ngx-bootstrap/datepicker';
import { BsDropdownModule } from 'ngx-bootstrap/dropdown';
ModalModule.forRoot(),
SharedModule,
RouterModule,
- TreeModule
+ TreeModule,
+ NgBootstrapFormValidationModule
],
declarations: [
RbdListComponent,
novalidate>
<div class="modal-body">
<!-- User -->
- <div class="form-group row"
- [ngClass]="{':invalid': discoveryForm.showError('user', formDir)}">
+ <div class="form-group row">
<label class="col-form-label col-sm-4"
for="user"
i18n>User</label>
class="form-control"
formControlName="user"
type="text">
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="discoveryForm.showError('user', formDir, 'required')"
i18n>This field is required.</span>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="discoveryForm.showError('user', formDir, 'pattern')"
i18n>Usernames must have a length of 8 to 64 characters and
can only contain letters, '.', '@', '-', '_' or ':'.</span>
</div>
<!-- Password -->
- <div class="form-group row"
- [ngClass]="{':invalid': discoveryForm.showError('password', formDir)}">
+ <div class="form-group row">
<label class="col-form-label col-sm-4"
for="password"
i18n>Password</label>
</button>
</span>
</div>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="discoveryForm.showError('password', formDir, 'required')"
i18n>This field is required.</span>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="discoveryForm.showError('password', formDir, 'pattern')"
i18n>Passwords must have a length of 12 to 16 characters
and can only contain letters, '@', '-', '_' or '/'.</span>
</div>
<!-- mutual_user -->
- <div class="form-group row"
- [ngClass]="{':invalid': discoveryForm.showError('mutual_user', formDir)}">
+ <div class="form-group row">
<label class="col-form-label col-sm-4"
for="mutual_user">
<ng-container i18n>Mutual User</ng-container>
formControlName="mutual_user"
type="text">
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="discoveryForm.showError('mutual_user', formDir, 'required')"
i18n>This field is required.</span>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="discoveryForm.showError('mutual_user', formDir, 'pattern')"
i18n>Usernames must have a length of 8 to 64 characters and
can only contain letters, '.', '@', '-', '_' or ':'.</span>
</div>
<!-- mutual_password -->
- <div class="form-group row"
- [ngClass]="{':invalid': discoveryForm.showError('mutual_password', formDir)}">
+ <div class="form-group row">
<label class="col-form-label col-sm-4"
for="mutual_password"
i18n>Mutual Password</label>
</button>
</span>
</div>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="discoveryForm.showError('mutual_password', formDir, 'required')"
i18n>This field is required.</span>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="discoveryForm.showError('mutual_password', formDir, 'pattern')"
i18n>Passwords must have a length of 12 to 16 characters and
can only contain letters, '@', '-', '_' or '/'.</span>
<div class="card-body">
<!-- Target IQN -->
- <div class="form-group row"
- [ngClass]="{':invalid': targetForm.showError('target_iqn', formDir)}">
+ <div class="form-group row">
<label class="col-form-label col-sm-3"
for="target_iqn">
<ng-container i18n>Target IQN</ng-container>
</span>
</div>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="targetForm.showError('target_iqn', formDir, 'required')"
i18n>This field is required.</span>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="targetForm.showError('target_iqn', formDir, 'pattern')"
i18n>IQN has wrong pattern.</span>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="targetForm.showError('target_iqn', formDir, 'iqn')">
<ng-container i18n>An IQN has the following notation
'iqn.$year-$month.$reversedAddress:$definedName'</ng-container>
</div>
<!-- Portals -->
- <div class="form-group row"
- [ngClass]="{':invalid': targetForm.showError('portals', formDir)}">
+ <div class="form-group row">
<label class="col-form-label col-sm-3"
for="portals">
<ng-container i18n>Portals</ng-container>
</div>
</ng-container>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="targetForm.showError('portals', formDir, 'minGateways')"
i18n>At least {{ minimum_gateways }} gateways are required.</span>
</div>
<!-- Images -->
- <div class="form-group row"
- [ngClass]="{':invalid': targetForm.showError('disks', formDir)}">
+ <div class="form-group row">
<label class="col-form-label col-sm-3"
for="disks"
i18n>Images</label>
</span>
</ng-container>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="targetForm.showError('disks', formDir, 'required')"
i18n>At least 1 image is required.</span>
</div>
<div class="card-body">
<!-- Initiator: Name -->
- <div class="form-group row"
- [ngClass]="{':invalid': initiator.showError('client_iqn', formDir)}">
+ <div class="form-group row">
<label class="col-form-label col-sm-3"
for="client_iqn">
<ng-container i18n>Client IQN</ng-container>
formControlName="client_iqn"
(blur)="updatedInitiatorSelector()">
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="initiator.showError('client_iqn', formDir, 'notUnique')"
i18n>Initiator IQN needs to be unique.</span>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="initiator.showError('client_iqn', formDir, 'required')"
i18n>This field is required.</span>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="initiator.showError('client_iqn', formDir, 'pattern')"
i18n>IQN has wrong pattern.</span>
</div>
<ng-container formGroupName="auth">
<!-- Initiator: User -->
- <div class="form-group row"
- [ngClass]="{':invalid': initiator.showError('user', formDir)}">
+ <div class="form-group row">
<label class="col-form-label col-sm-3"
for="user"
i18n>User</label>
class="form-control"
formControlName="user"
type="text">
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="initiator.showError('user', formDir, 'required')"
i18n>This field is required.</span>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="initiator.showError('user', formDir, 'pattern')"
i18n>Usernames must have a length of 8 to 64 characters and
can only contain letters, '.', '@', '-', '_' or ':'.</span>
</div>
<!-- Initiator: Password -->
- <div class="form-group row"
- [ngClass]="{':invalid': initiator.showError('password', formDir)}">
+ <div class="form-group row">
<label class="col-form-label col-sm-3"
for="password"
i18n>Password</label>
</button>
</span>
</div>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="initiator.showError('password', formDir, 'required')"
i18n>This field is required.</span>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="initiator.showError('password', formDir, 'pattern')"
i18n>Passwords must have a length of 12 to 16 characters
and can only contain letters, '@', '-', '_' or '/'.</span>
<!-- Initiator: mutual_user -->
- <div class="form-group row"
- [ngClass]="{':invalid': initiator.showError('mutual_user', formDir)}">
+ <div class="form-group row">
<label class="col-form-label col-sm-3"
for="mutual_user">
<ng-container i18n>Mutual User</ng-container>
formControlName="mutual_user"
type="text">
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="initiator.showError('mutual_user', formDir, 'required')"
i18n>This field is required.</span>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="initiator.showError('mutual_user', formDir, 'pattern')"
i18n>Usernames must have a length of 8 to 64 characters and
can only contain letters, '.', '@', '-', '_' or ':'.</span>
</div>
<!-- Initiator: mutual_password -->
- <div class="form-group row"
- [ngClass]="{':invalid': initiator.showError('mutual_password', formDir)}">
+ <div class="form-group row">
<label class="col-form-label col-sm-3"
for="mutual_password"
i18n>Mutual Password</label>
</button>
</span>
</div>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="initiator.showError('mutual_password', formDir, 'required')"
i18n>This field is required.</span>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="initiator.showError('mutual_password', formDir, 'pattern')"
i18n>Passwords must have a length of 12 to 16 characters and
can only contain letters, '@', '-', '_' or '/'.</span>
</ng-container>
<!-- Initiator: Images -->
- <div class="form-group row"
- [ngClass]="{':invalid': initiator.showError('luns', formDir)}">
+ <div class="form-group row">
<label class="col-form-label col-sm-3"
for="luns"
i18n>Images</label>
<!-- Groups -->
<div class="form-group row"
- *ngIf="targetForm.getValue('acl_enabled')"
- [ngClass]="{':invalid': targetForm.showError('groups', formDir)}">
+ *ngIf="targetForm.getValue('acl_enabled')">
<label class="col-form-label col-sm-3"
for="initiators"
i18n>Groups</label>
</div>
<!-- Group: members -->
- <div class="form-group row"
- [ngClass]="{':invalid': group.showError('members', formDir)}">
+ <div class="form-group row">
<label class="col-form-label col-sm-3"
for="members">
<ng-container i18n>Initiators</ng-container>
</div>
<!-- Group: disks -->
- <div class="form-group row"
- [ngClass]="{':invalid': group.showError('disks', formDir)}">
+ <div class="form-group row">
<label class="col-form-label col-sm-3"
for="disks">
<ng-container i18n>Images</ng-container>
i18n>Changing these parameters from their default values is usually not necessary.</p>
<div class="form-group row"
- *ngFor="let setting of settingsForm.controls | keyvalue"
- [ngClass]="{':invalid': settingsForm.showError(setting.key, formDir)}">
+ *ngFor="let setting of settingsForm.controls | keyvalue">
<div class="col-sm-12">
<label class="col-form-label"
for="{{ setting.key }}">{{ setting.key }}</label>
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { RouterModule } from '@angular/router';
+import { NgBootstrapFormValidationModule } from 'ng-bootstrap-form-validation';
import { TreeModule } from 'ng2-tree';
import { AlertModule } from 'ngx-bootstrap/alert';
import { BsDropdownModule } from 'ngx-bootstrap/dropdown';
ModalModule.forRoot(),
AlertModule.forRoot(),
TooltipModule.forRoot(),
- TreeModule
+ TreeModule,
+ NgBootstrapFormValidationModule
],
declarations: [
DaemonListComponent,
<kbd>Update</kbd>.</ng-container>
</p>
- <div class="form-group"
- [ngClass]="{':invalid': editModeForm.showError('mirrorMode', formDir)}">
+ <div class="form-group">
<label class="col-form-label"
for="mirrorMode">
<span i18n>Mode</span>
<option *ngFor="let mirrorMode of mirrorModes"
[value]="mirrorMode.id">{{ mirrorMode.name }}</option>
</select>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="editModeForm.showError('mirrorMode', formDir, 'cannotDisable')"
i18n>Peer clusters must be removed prior to disabling mirror.</span>
</div>
<kbd>Submit</kbd>.</ng-container>
</p>
- <div class="form-group"
- [ngClass]="{':invalid': editPeerForm.showError('clusterName', formDir)}">
+ <div class="form-group">
<label class="col-form-label"
for="clusterName">
<span i18n>Cluster Name</span>
name="clusterName"
formControlName="clusterName"
autofocus>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="editPeerForm.showError('clusterName', formDir, 'required')"
i18n>This field is required.</span>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="editPeerForm.showError('clusterName', formDir, 'invalidClusterName')"
i18n>The cluster name is not valid.</span>
</div>
- <div class="form-group"
- [ngClass]="{':invalid': editPeerForm.showError('clientID', formDir)}">
+ <div class="form-group">
<label class="col-form-label"
for="clientID">
<span i18n>CephX ID</span>
id="clientID"
name="clientID"
formControlName="clientID">
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="editPeerForm.showError('clientID', formDir, 'required')"
i18n>This field is required.</span>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="editPeerForm.showError('clientID', formDir, 'invalidClientID')"
i18n>The CephX ID is not valid.</span>
</div>
- <div class="form-group"
- [ngClass]="{':invalid': editPeerForm.showError('monAddr', formDir)}">
+ <div class="form-group">
<label class="col-form-label"
for="monAddr">
<span i18n>Monitor Addresses</span>
id="monAddr"
name="monAddr"
formControlName="monAddr">
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="editPeerForm.showError('monAddr', formDir, 'invalidMonAddr')"
i18n>The monitory address is not valid.</span>
</div>
- <div class="form-group"
- [ngClass]="{':invalid': editPeerForm.showError('key', formDir)}">
+ <div class="form-group">
<label class="col-form-label"
for="key">
<span i18n>CephX Key</span>
id="key"
name="key"
formControlName="key">
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="editPeerForm.showError('key', formDir, 'invalidKey')"
i18n>CephX key must be base64 encoded.</span>
</div>
-<fieldset #cfgFormGroup [formGroup]="form.get('configuration')">
+<fieldset #cfgFormGroup
+ [formGroup]="form.get('configuration')">
<legend i18n>RBD Configuration</legend>
- <div *ngFor="let section of rbdConfigurationService.sections" class="col-12">
+ <div *ngFor="let section of rbdConfigurationService.sections"
+ class="col-12">
<h3 class="cd-header">
- <span
- (click)="toggleSectionVisibility(section.class)"
+ <span (click)="toggleSectionVisibility(section.class)"
class="collapsible">{{ section.heading }} <i [ngClass]="!sectionVisibility[section.class] ? icons.addCircle : icons.minusCircle" aria-hidden="true"></i></span>
</h3>
- <div class="{{ section.class }}" [hidden]="!sectionVisibility[section.class]">
- <div
- class="form-group row"
- *ngFor="let option of section.options"
- [ngClass]="{':invalid': form.showError('configuration.' + option.name, cfgFormGroup)}">
- <label
- class="col-form-label col-sm-3"
- [for]="option.name">{{ option.displayName }}<cd-helper>{{ option.description }}</cd-helper></label>
+ <div class="{{ section.class }}"
+ [hidden]="!sectionVisibility[section.class]">
+ <div class="form-group row"
+ *ngFor="let option of section.options">
+ <label class="col-form-label col-sm-3"
+ [for]="option.name">{{ option.displayName }}<cd-helper>{{ option.description }}</cd-helper></label>
<div class="col-sm-9 {{ section.heading }}">
<div class="input-group">
<ng-container [ngSwitch]="option.type">
<ng-container *ngSwitchCase="configurationType.milliseconds">
- <input
- [id]="option.name"
- [name]="option.name"
- [formControlName]="option.name"
- type="text"
- class="form-control"
- [ngDataReady]="ngDataReady"
- cdMilliseconds>
+ <input [id]="option.name"
+ [name]="option.name"
+ [formControlName]="option.name"
+ type="text"
+ class="form-control"
+ [ngDataReady]="ngDataReady"
+ cdMilliseconds>
</ng-container>
<ng-container *ngSwitchCase="configurationType.bps">
- <input
- [id]="option.name"
- [name]="option.name"
- [formControlName]="option.name"
- type="text"
- class="form-control"
- defaultUnit="b"
- [ngDataReady]="ngDataReady"
- cdDimlessBinaryPerSecond>
+ <input [id]="option.name"
+ [name]="option.name"
+ [formControlName]="option.name"
+ type="text"
+ class="form-control"
+ defaultUnit="b"
+ [ngDataReady]="ngDataReady"
+ cdDimlessBinaryPerSecond>
</ng-container>
<ng-container *ngSwitchCase="configurationType.iops">
- <input
- [id]="option.name"
- [name]="option.name"
- [formControlName]="option.name"
- type="text"
- class="form-control"
- [ngDataReady]="ngDataReady"
- cdIops>
+ <input [id]="option.name"
+ [name]="option.name"
+ [formControlName]="option.name"
+ type="text"
+ class="form-control"
+ [ngDataReady]="ngDataReady"
+ cdIops>
</ng-container>
</ng-container>
<span class="input-group-append">
- <button
- class="btn btn-light"
- type="button"
- data-toggle="button"
- [ngClass]="{'active': isDisabled(option.name)}"
- title="Remove the local configuration value. The parent configuration value will be inherited and used instead."
- i18n-title
- (click)="reset(option.name)">
+ <button class="btn btn-light"
+ type="button"
+ data-toggle="button"
+ [ngClass]="{'active': isDisabled(option.name)}"
+ title="Remove the local configuration value. The parent configuration value will be inherited and used instead."
+ i18n-title
+ (click)="reset(option.name)">
<i [ngClass]="[icons.erase]"
aria-hidden="true"></i>
</button>
</span>
</div>
- <span
- i18n
- class="form-text text-muted"
- *ngIf="form.showError('configuration.' + option.name, cfgFormGroup, 'min')">The mininum value is 0</span>
+ <span i18n
+ class="invalid-feedback"
+ *ngIf="form.showError('configuration.' + option.name, cfgFormGroup, 'min')">The mininum value is 0</span>
</div>
</div>
</div>
</div>
<!-- Name -->
- <div class="form-group row"
- [ngClass]="{':invalid': rbdForm.showError('name', formDir)}">
+ <div class="form-group row">
<label class="col-form-label col-sm-3"
for="name">
<ng-container i18n>Name</ng-container>
name="name"
formControlName="name"
autofocus>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="rbdForm.showError('name', formDir, 'required')">
<ng-container i18n>This field is required.</ng-container>
</span>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="rbdForm.showError('name', formDir, 'pattern')">
<ng-container i18n>'/' and '@' are not allowed.</ng-container>
</span>
<!-- Pool -->
<div class="form-group row"
- [ngClass]="{':invalid': rbdForm.showError('pool', formDir)}"
(change)="onPoolChange($event.target.value)">
<label class="col-form-label col-sm-3"
for="pool">
[value]="pool.pool_name">{{ pool.pool_name }}</option>
</select>
<span *ngIf="rbdForm.showError('pool', formDir, 'required')"
- class="form-text text-muted"
+ class="invalid-feedback"
i18n>This field is required.</span>
</div>
</div>
<!-- Data Pool -->
<div class="form-group row"
- [ngClass]="{':invalid': rbdForm.showError('dataPool', formDir)}"
*ngIf="rbdForm.getValue('useDataPool')">
<label class="col-form-label col-sm-3"
for="dataPool">
<option *ngFor="let dataPool of dataPools"
[value]="dataPool.pool_name">{{ dataPool.pool_name }}</option>
</select>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="rbdForm.showError('dataPool', formDir, 'required')"
i18n>This field is required.</span>
</div>
</div>
<!-- Size -->
- <div class="form-group row"
- [ngClass]="{':invalid': rbdForm.showError('size', formDir)}">
+ <div class="form-group row">
<label class="col-form-label col-sm-3"
for="size">
<ng-container i18n>Size</ng-container>
placeholder="e.g., 10GiB"
defaultUnit="GiB"
cdDimlessBinary>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="rbdForm.showError('size', formDir, 'required')"
i18n>This field is required.</span>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="rbdForm.showError('size', formDir, 'invalidSizeObject')"
i18n>You have to increase the size.</span>
</div>
<!-- Features -->
<div class="form-group row"
- [ngClass]="{':invalid': (formDir.submitted || rbdForm.get('features').dirty) && rbdForm.get('features').invalid}"
formGroupName="features">
<label i18n
class="col-sm-3 col-form-label"
i18n>Striping</h3>
<!-- Object Size -->
- <div class="form-group row"
- [ngClass]="{':invalid': rbdForm.showError('obj_size', formDir)}">
+ <div class="form-group row">
<label i18n
class="col-form-label col-sm-3"
for="size">Object size</label>
</div>
<!-- stripingUnit -->
- <div class="form-group row"
- [ngClass]="{':invalid': rbdForm.showError('stripingUnit', formDir)}">
+ <div class="form-group row">
<label class="col-form-label col-sm-3"
for="stripingUnit">
<span i18n>Stripe unit</span>
<option *ngFor="let objectSize of objectSizes"
[value]="objectSize">{{ objectSize }}</option>
</select>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="rbdForm.showError('stripingUnit', formDir, 'required')"
i18n>This field is required because stripe count is defined!</span>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="rbdForm.showError('stripingUnit', formDir, 'invalidStripingUnit')"
i18n>Stripe unit is greater than object size.</span>
</div>
</div>
<!-- Stripe Count -->
- <div class="form-group row"
- [ngClass]="{':invalid': rbdForm.showError('stripingCount', formDir)}">
+ <div class="form-group row">
<label class="col-form-label col-sm-3"
for="stripingCount">
<span i18n>Stripe count</span>
formControlName="stripingCount"
class="form-control"
type="number">
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="rbdForm.showError('stripingCount', formDir, 'required')"
i18n>This field is required because stripe unit is defined!</span>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="rbdForm.showError('stripingCount', formDir, 'min')"
i18n>Stripe count must be greater than 0.</span>
</div>
<div class="modal-body">
<!-- Name -->
- <div class="form-group row"
- [ngClass]="{':invalid': snapshotForm.showError('snapshotName', formDir)}">
+ <div class="form-group row">
<label class="col-form-label col-sm-3"
for="snapshotName">
<ng-container i18n>Name</ng-container>
name="snapshotName"
formControlName="snapshotName"
autofocus>
- <span class="form-text text-muted"
- *ngIf="snapshotForm.showError('snapshotName', formDir, 'required')">
+ <span class="invalid-feedback"
+ *ngIf="snapshotForm.showError('snapshotName', formDir, 'required')"
i18n>This field is required.</span>
</div>
</div>
<p i18n>To move <kbd>{{ poolName }}/{{ imageName }}</kbd> to trash,
click <kbd>Move Image</kbd>. Optionally, you can pick an expiration date.</p>
- <div class="form-group"
- [ngClass]="{':invalid': moveForm.showError('expiresAt', formDir)}">
+ <div class="form-group">
<label for="expires"
i18n>Protection expires at</label>
<input type="text"
[bsConfig]="bsConfig"
formControlName="expiresAt"
bsDatepicker>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="moveForm.showError('expiresAt', formDir, 'format')"
i18n>Wrong date format. Please use "YYYY-MM-DD HH:mm:ss".</span>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="moveForm.showError('expiresAt', formDir, 'expired')"
i18n>Protection has already expired. Please pick a future date or leave it empty.</span>
</div>
<kbd i18n>Restore Image</kbd>.
</p>
- <div class="form-group"
- [ngClass]="{':invalid': restoreForm.showError('name', formDir)}">
+ <div class="form-group">
<label for="name"
i18n>New Name</label>
<input type="text"
autocomplete="off"
formControlName="name"
autofocus>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="restoreForm.showError('name', formDir, 'required')"
i18n>This field is required.</span>
</div>
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { RouterModule } from '@angular/router';
+import { NgBootstrapFormValidationModule } from 'ng-bootstrap-form-validation';
import { TreeModule } from 'ng2-tree';
import { AlertModule } from 'ngx-bootstrap/alert';
import { BsDatepickerModule } from 'ngx-bootstrap/datepicker';
MgrModulesModule,
TypeaheadModule.forRoot(),
TimepickerModule.forRoot(),
- BsDatepickerModule.forRoot()
+ BsDatepickerModule.forRoot(),
+ NgBootstrapFormValidationModule
],
declarations: [
HostsComponent,
</div>
<div class="form-group row"
- [ngClass]="{':invalid': configForm.showError(section, formDir)}"
*ngIf="type !== 'bool'">
<label class="col-form-label col-sm-3"
[for]="section">{{ section }}
[placeholder]="humanReadableType"
[formControlName]="section"
[step]="getStep(type, this.configForm.getValue(section))">
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="configForm.showError(section, formDir, 'pattern')">
{{ patternHelpText }}
</span>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="configForm.showError(section, formDir, 'invalidUuid')">
{{ patternHelpText }}
</span>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="configForm.showError(section, formDir, 'max')"
i18n>The entered value is too high! It must not be greater than {{ maxValue }}.</span>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="configForm.showError(section, formDir, 'min')"
i18n>The entered value is too low! It must not be lower than {{ minValue }}.</span>
</div>
i18n>Edit Manager module</div>
<div class="card-body">
<div class="form-group row"
- [ngClass]="{':invalid': mgrModuleForm.showError(moduleOption.value.name, frm)}"
*ngFor="let moduleOption of moduleOptions | keyvalue">
<!-- Field label -->
{{ value }}
</option>
</select>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="mgrModuleForm.showError(moduleOption.value.name, frm, 'invalidUuid')"
i18n>The entered value is not a valid UUID, e.g.: 67dcac9f-2c03-4d6c-b7bd-1210b3a259a8</span>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="mgrModuleForm.showError(moduleOption.value.name, frm, 'pattern')"
i18n>The entered value needs to be a valid IP address.</span>
</div>
formControlName="{{ moduleOption.value.name }}"
min="{{ moduleOption.value.min }}"
max="{{ moduleOption.value.max }}">
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="mgrModuleForm.showError(moduleOption.value.name, frm, 'required')"
i18n>This field is required.</span>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="mgrModuleForm.showError(moduleOption.value.name, frm, 'max')"
i18n>The entered value is too high! It must be lower or equal to {{ moduleOption.value.max }}.</span>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="mgrModuleForm.showError(moduleOption.value.name, frm, 'min')"
i18n>The entered value is too low! It must be greater or equal to {{ moduleOption.value.min }}.</span>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="mgrModuleForm.showError(moduleOption.value.name, frm, 'pattern')"
i18n>The entered value needs to be a number.</span>
</div>
class="form-control"
type="number"
formControlName="{{ moduleOption.value.name }}">
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="mgrModuleForm.showError(moduleOption.value.name, frm, 'required')"
i18n>This field is required.</span>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="mgrModuleForm.showError(moduleOption.value.name, frm, 'pattern')"
i18n>The entered value needs to be a number or decimal.</span>
</div>
import { NgModule } from '@angular/core';
import { ReactiveFormsModule } from '@angular/forms';
+import { NgBootstrapFormValidationModule } from 'ng-bootstrap-form-validation';
import { TabsModule } from 'ngx-bootstrap/tabs';
import { AppRoutingModule } from '../../../app-routing.module';
CommonModule,
ReactiveFormsModule,
SharedModule,
- TabsModule.forRoot()
+ TabsModule.forRoot(),
+ NgBootstrapFormValidationModule
],
declarations: [MgrModuleListComponent, MgrModuleFormComponent, MgrModuleDetailsComponent]
})
novalidate>
<div class="modal-body">
<!-- Priority -->
- <div class="form-group row"
- [ngClass]="{':invalid': osdRecvSpeedForm.showError('priority', formDir)}">
+ <div class="form-group row">
<label class="col-form-label col-sm-6"
for="priority">
<ng-container i18n>Priority</ng-container>
{{ priority.text }}
</option>
</select>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="osdRecvSpeedForm.showError('priority', formDir, 'required')"
i18n>This field is required.</span>
</div>
<!-- Priority values -->
<div class="form-group row"
- *ngFor="let attr of priorityAttrs | keyvalue"
- [ngClass]="{':invalid': osdRecvSpeedForm.getValue('customizePriority') &&
- osdRecvSpeedForm.showError(attr.key, formDir)}">
+ *ngFor="let attr of priorityAttrs | keyvalue">
<label class="col-form-label col-sm-6"
[for]="attr.key">{{ attr.value.text }}
<cd-helper *ngIf="attr.value.desc">{{ attr.value.desc }}</cd-helper>
[id]="attr.key"
[formControlName]="attr.key"
[readonly]="!osdRecvSpeedForm.getValue('customizePriority')">
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="osdRecvSpeedForm.getValue('customizePriority') &&
osdRecvSpeedForm.showError(attr.key, formDir, 'required')"
i18n>This field is required!</span>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="osdRecvSpeedForm.getValue('customizePriority') &&
osdRecvSpeedForm.showError(attr.key, formDir, 'pattern')"
i18n>{{ attr.value.patternHelpText }}</span>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="osdRecvSpeedForm.getValue('customizePriority') &&
osdRecvSpeedForm.showError(attr.key, formDir, 'max')"
i18n>The entered value is too high! It must not be greater than {{ attr.value.maxValue }}.</span>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="osdRecvSpeedForm.getValue('customizePriority') &&
osdRecvSpeedForm.showError(attr.key, formDir, 'min')"
i18n>The entered value is too low! It must not be lower than {{ attr.value.minValue }}.</span>
<ng-container class="modal-content">
<form [formGroup]="reweightForm">
- <div class="modal-body" [ngClass]="{':invalid': weight.errors}">
+ <div class="modal-body">
<div class="row">
<label for="weight" class="col-sm-2 col-form-label">Weight</label>
<div class="col-sm-10">
<input id="weight" class="form-control" type="number"
step="0.1" formControlName="weight" min="0" max="1"
[value]="currentWeight">
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="weight.errors">
<span *ngIf="weight.errors?.required"
i18n>This field is required.</span>
<div class="card-body">
<!-- Addresses -->
- <div class="form-group row"
- [ngClass]="{ ':invalid': showError(index, 'addresses', formDir) }">
+ <div class="form-group row">
<label i18n
class="col-sm-3 col-form-label"
for="addresses">Addresses</label>
id="addresses"
formControlName="addresses"
placeholder="192.168.0.10, 192.168.1.0/8">
- <span class="form-text text-muted">
+ <span class="invalid-feedback">
<span *ngIf="showError(index, 'addresses', formDir, 'required')"
i18n>Required field</span>
<div class="card-body">
<!-- cluster_id -->
<div class="form-group row"
- [ngClass]="{':invalid': nfsForm.showError('cluster_id', formDir)}"
*ngIf="!isDefaultCluster">
<label class="col-sm-3 col-form-label"
for="cluster_id">
<option *ngFor="let cluster of allClusters"
[value]="cluster">{{ cluster }}</option>
</select>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="nfsForm.showError('cluster_id', formDir, 'required')"
i18n>Required field</span>
</div>
</div>
<!-- daemons -->
- <div class="form-group row"
- [ngClass]="{':invalid': nfsForm.showError('daemons', formDir)}">
+ <div class="form-group row">
<label class="col-sm-3 col-form-label"
for="daemons">
<ng-container i18n>Daemons</ng-container>
<!-- FSAL -->
<div formGroupName="fsal">
<!-- Name -->
- <div class="form-group row"
- [ngClass]="{':invalid': nfsForm.showError('name', formDir)}">
+ <div class="form-group row">
<label class="col-sm-3 col-form-label"
for="name">
<ng-container i18n>Storage Backend</ng-container>
<option *ngFor="let fsal of allFsals"
[value]="fsal.value">{{ fsal.descr }}</option>
</select>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="nfsForm.showError('name', formDir, 'required')"
i18n>Required field</span>
</div>
<!-- RGW user -->
<div class="form-group row"
- [ngClass]="{':invalid': nfsForm.showError('rgw_user_id', formDir)}"
*ngIf="nfsForm.getValue('name') === 'RGW'">
<label class="col-sm-3 col-form-label"
for="rgw_user_id">
<option *ngFor="let rgwUserId of allRgwUsers"
[value]="rgwUserId">{{ rgwUserId }}</option>
</select>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="nfsForm.showError('rgw_user_id', formDir, 'required')"
i18n>Required field</span>
</div>
<!-- CephFS user_id -->
<div class="form-group row"
- [ngClass]="{':invalid': nfsForm.showError('user_id', formDir)}"
*ngIf="nfsForm.getValue('name') === 'CEPH'">
<label class="col-sm-3 col-form-label"
for="user_id">
<option *ngFor="let client of allCephxClients"
[value]="client">{{ client }}</option>
</select>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="nfsForm.showError('user_id', formDir, 'required')"
i18n>Required field</span>
</div>
<!-- CephFS fs_name -->
<div class="form-group row"
- [ngClass]="{':invalid': nfsForm.showError('fs_name', formDir)}"
*ngIf="nfsForm.getValue('name') === 'CEPH'">
<label class="col-sm-3 col-form-label"
for="fs_name">
<option *ngFor="let filesystem of allFsNames"
[value]="filesystem.name">{{ filesystem.name }}</option>
</select>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="nfsForm.showError('fs_name', formDir, 'required')"
i18n>Required field</span>
</div>
<!-- Secutiry Label -->
<div class="form-group row"
- [ngClass]="{':invalid': nfsForm.showError('security_label', formDir)}"
*ngIf="nfsForm.getValue('name') === 'CEPH'">
<label class="col-sm-3 col-form-label"
for="security_label">
id="sec_label_xattr"
formControlName="sec_label_xattr">
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="nfsForm.showError('sec_label_xattr', formDir, 'required')"
i18n>Required field</span>
</div>
<!-- Path -->
<div class="form-group row"
- [ngClass]="{':invalid': nfsForm.showError('path', formDir)}"
*ngIf="nfsForm.getValue('name') === 'CEPH'">
<label class="col-sm-3 col-form-label"
for="path">
[typeahead]="pathDataSource"
(typeaheadOnSelect)="pathChangeHandler()"
(blur)="pathChangeHandler()">
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="nfsForm.showError('path', formDir, 'required')"
i18n>Required field</span>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="nfsForm.showError('path', formDir, 'pattern')"
i18n>Path need to start with a '/' and can be followed by a word</span>
<span class="form-text text-muted"
<!-- Bucket -->
<div class="form-group row"
- [ngClass]="{':invalid': nfsForm.showError('path', formDir)}"
*ngIf="nfsForm.getValue('name') === 'RGW'">
<label class="col-sm-3 col-form-label"
for="path">
(typeaheadOnSelect)="bucketChangeHandler()"
(blur)="bucketChangeHandler()">
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="nfsForm.showError('path', formDir, 'required')"
i18n>Required field</span>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="nfsForm.showError('path', formDir, 'pattern')"
i18n>Path can only be a single '/' or a word</span>
</div>
<!-- NFS Protocol -->
- <div class="form-group row"
- [ngClass]="{':invalid': nfsForm.showError('protocolNfsv3', formDir) || nfsForm.showError('protocolNfsv4', formDir)}">
+ <div class="form-group row">
<label class="col-sm-3 col-form-label"
for="protocols">
<ng-container i18n>NFS Protocol</ng-container>
class="custom-control-label"
for="protocolNfsv4">NFSv4</label>
</div>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="nfsForm.showError('protocolNfsv3', formDir, 'required') ||
nfsForm.showError('protocolNfsv4', formDir, 'required')"
i18n>Required field</span>
<!-- Pseudo -->
<div class="form-group row"
- [ngClass]="{':invalid': nfsForm.showError('pseudo', formDir)}"
*ngIf="nfsForm.getValue('protocolNfsv4')">
<label class="col-sm-3 col-form-label"
for="pseudo">
name="pseudo"
id="pseudo"
formControlName="pseudo">
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="nfsForm.showError('pseudo', formDir, 'required')"
i18n>Required field</span>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="nfsForm.showError('pseudo', formDir, 'pattern')"
i18n>Pseudo needs to start with a '/' and can't contain any of the following: >, <, |, &, ( or ).</span>
</div>
</div>
<!-- Access Type -->
- <div class="form-group row"
- [ngClass]="{':invalid': nfsForm.showError('access_type', formDir)}">
+ <div class="form-group row">
<label class="col-sm-3 col-form-label"
for="access_type">
<ng-container i18n>Access Type</ng-container>
*ngIf="nfsForm.getValue('access_type')">
{{ getAccessTypeHelp(nfsForm.getValue('access_type')) }}
</span>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="nfsForm.showError('access_type', formDir, 'required')"
i18n>Required field</span>
</div>
</div>
<!-- Squash -->
- <div class="form-group row"
- [ngClass]="{':invalid': nfsForm.showError('squash', formDir)}">
+ <div class="form-group row">
<label class="col-sm-3 col-form-label"
for="squash">
<ng-container i18n>Squash</ng-container>
[value]="squash">{{ squash }}</option>
</select>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="nfsForm.showError('squash', formDir,'required')"
i18n>Required field</span>
</div>
</div>
<!-- Transport Protocol -->
- <div class="form-group row"
- [ngClass]="{':invalid': nfsForm.showError('transportUDP', formDir) || nfsForm.showError('transportTCP', formDir)}">
+ <div class="form-group row">
<label class="col-sm-3 col-form-label"
for="transports">
<ng-container i18n>Transport Protocol</ng-container>
class="custom-control-label"
i18n>TCP</label>
</div>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="nfsForm.showError('transportUDP', formDir, 'required') ||
nfsForm.showError('transportTCP', formDir, 'required')"
i18n>Required field</span>
import { ReactiveFormsModule } from '@angular/forms';
import { RouterModule } from '@angular/router';
+import { NgBootstrapFormValidationModule } from 'ng-bootstrap-form-validation';
import { TabsModule } from 'ngx-bootstrap/tabs';
import { TypeaheadModule } from 'ngx-bootstrap/typeahead';
SharedModule,
TabsModule.forRoot(),
CommonModule,
- TypeaheadModule.forRoot()
+ TypeaheadModule.forRoot(),
+ NgBootstrapFormValidationModule
],
declarations: [
NfsListComponent,
[formGroup]="form"
novalidate>
<div class="modal-body">
- <div class="form-group row"
- [ngClass]="{':invalid': form.showError('name', frm)}">
+ <div class="form-group row">
<label for="name"
class="col-form-label col-sm-3">
<ng-container i18n>Name</ng-container>
placeholder="Name..."
formControlName="name"
autofocus>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="form.showError('name', frm, 'required')"
i18n>This field is required!</span>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="form.showError('name', frm, 'pattern')"
i18n>The name can only consist of alphanumeric characters, dashes and underscores.</span>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="form.showError('name', frm, 'uniqueName')"
i18n>The chosen erasure code profile name is already in use.</span>
</div>
{{ plugin }}
</option>
</select>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="form.showError('name', frm, 'required')"
i18n>This field is required!</span>
</div>
</div>
- <div class="form-group row"
- [ngClass]="{':invalid': form.showError('k', frm)}">
+ <div class="form-group row">
<label for="k"
class="col-form-label col-sm-3">
<ng-container i18n>Data chunks (k)</ng-container>
ng-model="$ctrl.erasureCodeProfile.k"
placeholder="Data chunks..."
formControlName="k">
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="form.showError('k', frm, 'required')"
i18n>This field is required!</span>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="form.showError('k', frm, 'min')"
i18n>Must be equal to or greater than 2.</span>
</div>
</div>
- <div class="form-group row"
- [ngClass]="{':invalid': form.showError('m', frm)}">
+ <div class="form-group row">
<label for="m"
class="col-form-label col-sm-3">
<ng-container i18n>Coding chunks (m)</ng-container>
class="form-control"
placeholder="Coding chunks..."
formControlName="m">
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="form.showError('m', frm, 'required')"
i18n>This field is required!</span>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="form.showError('m', frm, 'min')"
i18n>Must be equal to or greater than 1.</span>
</div>
</div>
<div class="form-group row"
- *ngIf="plugin === 'shec'"
- [ngClass]="{':invalid': form.showError('c', frm)}">
+ *ngIf="plugin === 'shec'">
<label for="c"
class="col-form-label col-sm-3">
<ng-container i18n>Durability estimator (c)</ng-container>
class="form-control"
placeholder="Coding chunks..."
formControlName="c">
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="form.showError('c', frm, 'min')"
i18n>Must be equal to or greater than 1.</span>
</div>
</div>
<div class="form-group row"
- *ngIf="plugin === PLUGIN.LRC"
- [ngClass]="{':invalid': form.showError('l', frm)}">
+ *ngIf="plugin === PLUGIN.LRC">
<label for="l"
class="col-form-label col-sm-3">
<ng-container i18n>Locality (l)</ng-container>
class="form-control"
placeholder="Coding chunks..."
formControlName="l">
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="form.showError('l', frm, 'required')"
i18n>This field is required!</span>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="form.showError('l', frm, 'min')"
i18n>Must be equal to or greater than 1.</span>
</div>
</div>
<div class="form-group row"
- *ngIf="plugin === PLUGIN.JERASURE"
- [ngClass]="{':invalid': form.showError('packetSize', frm)}">
+ *ngIf="plugin === PLUGIN.JERASURE">
<label for="packetSize"
class="col-form-label col-sm-3">
<ng-container i18n>Packetsize</ng-container>
class="form-control"
placeholder="Packetsize..."
formControlName="packetSize">
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="form.showError('packetSize', frm, 'min')"
i18n>Must be equal to or greater than 1.</span>
</div>
</div>
- <div class="form-group row"
- [ngClass]="{':invalid': form.showError('crushRoot', frm)}">
+ <div class="form-group row">
<label for="crushRoot"
class="col-form-label col-sm-3">
<ng-container i18n>Crush root</ng-container>
import { By } from '@angular/platform-browser';
import { RouterTestingModule } from '@angular/router/testing';
+import { NgBootstrapFormValidationModule } from 'ng-bootstrap-form-validation';
import { BsModalRef } from 'ngx-bootstrap/modal';
import { ToastrModule } from 'ngx-toastr';
import { of } from 'rxjs';
let data: {};
configureTestBed({
- imports: [HttpClientTestingModule, RouterTestingModule, ToastrModule.forRoot(), PoolModule],
+ imports: [
+ HttpClientTestingModule,
+ RouterTestingModule,
+ ToastrModule.forRoot(),
+ PoolModule,
+ NgBootstrapFormValidationModule.forRoot()
+ ],
providers: [ErasureCodeProfileService, BsModalRef, i18nProviders]
});
<div class="card-body">
<!-- Name -->
- <div class="form-group row"
- [ngClass]="{':invalid': form.showError('name', formDir)}">
+ <div class="form-group row">
<label class="col-form-label col-sm-3"
for="name">
<ng-container i18n>Name</ng-container>
i18n-placeholder
formControlName="name"
autofocus>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="form.showError('name', formDir, 'required')"
i18n>This field is required!</span>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="form.showError('name', formDir, 'uniqueName')"
i18n>The chosen Ceph pool name is already in use.</span>
</div>
</div>
<!-- Pool type selection -->
- <div class="form-group row"
- [ngClass]="{':invalid': form.showError('poolType', formDir)}">
+ <div class="form-group row">
<label class="col-form-label col-sm-3"
for="poolType">
<ng-container i18n>Pool type</ng-container>
{{ poolType }}
</option>
</select>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="form.showError('poolType', formDir, 'required')"
i18n>This field is required!</span>
</div>
<div *ngIf="form.getValue('poolType')">
<!-- Pg number -->
- <div class="form-group row"
- [ngClass]="{':invalid': form.showError('pgNum', formDir)}">
+ <div class="form-group row">
<label class="col-form-label col-sm-3"
for="pgNum">
<ng-container i18n>Placement groups</ng-container>
(focus)="externalPgChange = false"
(blur)="alignPgs()"
required>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="form.showError('pgNum', formDir, 'required')"
i18n>This field is required!</span>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="form.showError('pgNum', formDir, 'min')"
i18n>At least one placement group is needed!</span>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="form.showError('pgNum', formDir, '34')"
i18n>Your cluster can't handle this many PGs. Please recalculate the PG amount needed.</span>
<span class="form-text text-muted">
<!-- Crush ruleset selection -->
<div class="form-group row"
- [ngClass]="{':invalid': form.showError('crushRule', formDir)}"
*ngIf="form.getValue('poolType') && current.rules.length > 0">
<label class="col-form-label col-sm-3"
for="crushRule"
</tab>
</tabset>
</span>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="form.showError('crushRule', formDir, 'tooFewOsds')"
i18n>The rule can't be used in the current cluster as it has
to few OSDs to meet the minimum required OSD by this rule.</span>
<!-- Replica Size -->
<div class="form-group row"
- [ngClass]="{':invalid': form.showError('size', formDir)}"
*ngIf="form.getValue('poolType') === 'replicated'">
<label class="col-form-label col-sm-3"
for="size">
name="size"
type="number"
formControlName="size">
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="form.showError('size', formDir)">
<ul class="list-inline">
<li i18n>Minimum: {{ getMinSize() }}</li>
<li i18n>Maximum: {{ getMaxSize() }}</li>
</ul>
</span>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="form.showError('size', formDir)"
i18n>The size specified is out of range. A value from
{{ getMinSize() }} to {{ getMaxSize() }} is valid.</span>
</div>
<div *ngIf="hasCompressionEnabled()">
<!-- Compression algorithm selection -->
- <div class="form-group row"
- [ngClass]="{':invalid': form.showError('algorithm', formDir)}">
+ <div class="form-group row">
<label i18n
class="col-form-label col-sm-3"
for="algorithm">Algorithm</label>
</div>
</div>
- <!-- Compression min blob size -->
- <div class="form-group row"
- [ngClass]="{':invalid': form.showError('minBlobSize', formDir)}">
- <label i18n
- class="col-form-label col-sm-3"
- for="minBlobSize">Minimum blob size</label>
- <div class="col-sm-9">
- <input id="minBlobSize"
- name="minBlobSize"
- formControlName="minBlobSize"
- type="text"
- min="0"
- class="form-control"
- i18n-placeholder
- placeholder="e.g., 128KiB"
- defaultUnit="KiB"
- cdDimlessBinary>
- <span class="form-text text-muted"
- *ngIf="form.showError('minBlobSize', formDir, 'min')"
- i18n>Value should be greater than 0</span>
- <span class="form-text text-muted"
- *ngIf="form.showError('minBlobSize', formDir, 'maximum')"
- i18n>Value should be less than the maximum blob size</span>
+ <!-- Compression min blob size -->
+ <div class="form-group row">
+ <label i18n
+ class="col-form-label col-sm-3"
+ for="minBlobSize">Minimum blob size</label>
+ <div class="col-sm-9">
+ <input id="minBlobSize"
+ name="minBlobSize"
+ formControlName="minBlobSize"
+ type="text"
+ min="0"
+ class="form-control"
+ i18n-placeholder
+ placeholder="e.g., 128KiB"
+ defaultUnit="KiB"
+ cdDimlessBinary>
+ <span class="invalid-feedback"
+ *ngIf="form.showError('minBlobSize', formDir, 'min')"
+ i18n>Value should be greater than 0</span>
+ <span class="invalid-feedback"
+ *ngIf="form.showError('minBlobSize', formDir, 'maximum')"
+ i18n>Value should be less than the maximum blob size</span>
</div>
</div>
<!-- Compression max blob size -->
- <div class="form-group row"
- [ngClass]="{':invalid': form.showError('maxBlobSize', formDir)}">
+ <div class="form-group row">
<label i18n
class="col-form-label col-sm-3"
for="maxBlobSize">Maximum blob size</label>
placeholder="e.g., 512KiB"
defaultUnit="KiB"
cdDimlessBinary>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="form.showError('maxBlobSize', formDir, 'min')"
i18n>Value should be greater than 0</span>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="form.showError('maxBlobSize', formDir, 'minimum')"
i18n>Value should be greater than the minimum blob size</span>
</div>
</div>
<!-- Compression ratio -->
- <div class="form-group row"
- [ngClass]="{':invalid': form.showError('ratio', formDir)}">
+ <div class="form-group row">
<label i18n
class="col-form-label col-sm-3"
for="ratio">Ratio</label>
class="form-control"
i18n-placeholder
placeholder="Compression ratio">
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="form.showError('ratio', formDir, 'min') || form.showError('ratio', formDir, 'max')"
i18n>Value should be between 0.0 and 1.0</span>
</div>
</cd-rbd-configuration-form>
</div>
- <div class="form-group :invalid">
+ <div class="form-group">
<div class="offset-sm-3 col-sm-9"
*ngIf="form.hasError('rbdPool')">
<br>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
i18n>It's not possible to create an RBD pool with '/' in the name.</span>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
i18n>Please change the name or remove 'rbd' from the applications list.</span>
</div>
</div>
import { ActivatedRoute, Router, Routes } from '@angular/router';
import { RouterTestingModule } from '@angular/router/testing';
+import { NgBootstrapFormValidationModule } from 'ng-bootstrap-form-validation';
import { BsModalService } from 'ngx-bootstrap/modal';
import { TabsModule } from 'ngx-bootstrap/tabs';
import { ToastrModule } from 'ngx-toastr';
RouterTestingModule.withRoutes(routes),
ToastrModule.forRoot(),
TabsModule.forRoot(),
- PoolModule
+ PoolModule,
+ NgBootstrapFormValidationModule.forRoot()
],
providers: [
ErasureCodeProfileService,
import { ReactiveFormsModule } from '@angular/forms';
import { RouterModule, Routes } from '@angular/router';
+import { NgBootstrapFormValidationModule } from 'ng-bootstrap-form-validation';
import { BsDropdownModule } from 'ngx-bootstrap/dropdown';
import { PopoverModule } from 'ngx-bootstrap/popover';
import { TabsModule } from 'ngx-bootstrap/tabs';
ReactiveFormsModule,
BsDropdownModule,
TooltipModule.forRoot(),
- BlockModule
+ BlockModule,
+ NgBootstrapFormValidationModule
],
exports: [PoolListComponent, PoolFormComponent],
declarations: [
</div>
<!-- Name -->
- <div class="form-group row"
- [ngClass]="{':invalid': bucketForm.showError('bid', frm)}">
+ <div class="form-group row">
<label class="col-form-label col-sm-3"
for="bid">
<ng-container i18n>Name</ng-container>
formControlName="bid"
[readonly]="editing"
autofocus>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="bucketForm.showError('bid', frm, 'required')"
i18n>This field is required.</span>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="bucketForm.showError('bid', frm, 'bucketNameInvalid')"
i18n>The value is not valid.</span>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="bucketForm.showError('bid', frm, 'bucketNameExists')"
i18n>The chosen name is already in use.</span>
</div>
</div>
<!-- Owner -->
- <div class="form-group row"
- [ngClass]="{':invalid': bucketForm.showError('owner', frm)}">
+ <div class="form-group row">
<label class="col-form-label col-sm-3"
for="owner">
<ng-container i18n>Owner</ng-container>
<option *ngFor="let owner of owners"
[value]="owner">{{ owner }}</option>
</select>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="bucketForm.showError('owner', frm, 'required')"
i18n>This field is required.</span>
</div>
<div class="modal-body">
<!-- Type -->
- <div class="form-group row"
- [ngClass]="{':invalid': formGroup.showError('type', frm)}">
+ <div class="form-group row">
<label class="col-form-label col-sm-3"
for="type">
<ng-container i18n>Type</ng-container>
<option *ngFor="let type of types"
[value]="type">{{ type }}</option>
</select>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="formGroup.showError('type', frm, 'required')"
i18n>This field is required.</span>
</div>
</div>
<!-- Permission -->
- <div class="form-group row"
- [ngClass]="{':invalid': formGroup.showError('perm', frm)}">
+ <div class="form-group row">
<label class="col-form-label col-sm-3"
for="perm">
<ng-container i18n>Permission</ng-container>
{{ perm }}
</option>
</select>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="formGroup.showError('perm', frm, 'required')"
i18n>This field is required.</span>
</div>
<div class="card-body">
<!-- Username -->
- <div class="form-group row"
- [ngClass]="{':invalid': userForm.showError('uid', frm)}">
+ <div class="form-group row">
<label class="col-form-label col-sm-3"
for="uid">
<ng-container i18n>Username</ng-container>
formControlName="uid"
[readonly]="editing"
autofocus>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="userForm.showError('uid', frm, 'required')"
i18n>This field is required.</span>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="userForm.showError('uid', frm, 'notUnique')"
i18n>The chosen user ID is already in use.</span>
</div>
</div>
<!-- Full name -->
- <div class="form-group row"
- [ngClass]="{':invalid': userForm.showError('display_name', frm)}">
+ <div class="form-group row">
<label class="col-form-label col-sm-3"
for="display_name">
<ng-container i18n>Full name</ng-container>
class="form-control"
type="text"
formControlName="display_name">
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="userForm.showError('display_name', frm, 'required')"
i18n>This field is required.</span>
</div>
</div>
<!-- Email address -->
- <div class="form-group row"
- [ngClass]="{':invalid': userForm.showError('email', frm)}">
+ <div class="form-group row">
<label class="col-form-label col-sm-3"
for="email"
i18n>Email address</label>
class="form-control"
type="text"
formControlName="email">
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="userForm.showError('email', frm, 'email')"
i18n>This is not a valid email address.</span>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="userForm.showError('email', frm, 'notUnique')"
i18n>The chosen email address is already in use.</span>
</div>
</div>
<!-- Max. buckets -->
- <div class="form-group row"
- [ngClass]="{':invalid': userForm.showError('max_buckets', frm)}">
+ <div class="form-group row">
<label class="col-form-label col-sm-3"
for="max_buckets">
<ng-container i18n>Max. buckets</ng-container>
class="form-control"
type="number"
formControlName="max_buckets">
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="userForm.showError('max_buckets', frm, 'required')"
i18n>This field is required.</span>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="userForm.showError('max_buckets', frm, 'min')"
i18n>The entered value must be >= 0.</span>
</div>
<!-- Access key -->
<div class="form-group row"
- [ngClass]="{':invalid': userForm.showError('access_key', frm)}"
*ngIf="!editing && !userForm.getValue('generate_key')">
<label class="col-form-label col-sm-3"
for="access_key">
</button>
</span>
</div>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="userForm.showError('access_key', frm, 'required')"
i18n>This field is required.</span>
</div>
<!-- Secret key -->
<div class="form-group row"
- [ngClass]="{':invalid': userForm.showError('secret_key', frm)}"
*ngIf="!editing && !userForm.getValue('generate_key')">
<label class="col-form-label col-sm-3"
for="secret_key">
</button>
</span>
</div>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="userForm.showError('secret_key', frm, 'required')"
i18n>This field is required.</span>
</div>
<!-- Maximum size -->
<div class="form-group row"
- [ngClass]="{':invalid': userForm.showError('user_quota_max_size', frm)}"
*ngIf="userForm.controls.user_quota_enabled.value && !userForm.getValue('user_quota_max_size_unlimited')">
<label class="col-form-label col-sm-3"
for="user_quota_max_size">
type="text"
formControlName="user_quota_max_size"
cdDimlessBinary>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="userForm.showError('user_quota_max_size', frm, 'required')"
i18n>This field is required.</span>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="userForm.showError('user_quota_max_size', frm, 'quotaMaxSize')"
i18n>The value is not valid.</span>
</div>
<!-- Maximum objects -->
<div class="form-group row"
- [ngClass]="{':invalid': userForm.showError('user_quota_max_objects', frm)}"
*ngIf="userForm.controls.user_quota_enabled.value && !userForm.getValue('user_quota_max_objects_unlimited')">
<label class="col-form-label col-sm-3"
for="user_quota_max_objects">
class="form-control"
type="number"
formControlName="user_quota_max_objects">
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="userForm.showError('user_quota_max_objects', frm, 'required')"
i18n>This field is required.</span>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="userForm.showError('user_quota_max_objects', frm, 'min')"
i18n>The entered value must be >= 0.</span>
</div>
<!-- Maximum size -->
<div class="form-group row"
- [ngClass]="{':invalid': userForm.showError('bucket_quota_max_size', frm)}"
*ngIf="userForm.controls.bucket_quota_enabled.value && !userForm.getValue('bucket_quota_max_size_unlimited')">
<label class="col-form-label col-sm-3"
for="bucket_quota_max_size">
type="text"
formControlName="bucket_quota_max_size"
cdDimlessBinary>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="userForm.showError('bucket_quota_max_size', frm, 'required')"
i18n>This field is required.</span>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="userForm.showError('bucket_quota_max_size', frm, 'quotaMaxSize')"
i18n>The value is not valid.</span>
</div>
<!-- Maximum objects -->
<div class="form-group row"
- [ngClass]="{':invalid': userForm.showError('bucket_quota_max_objects', frm)}"
*ngIf="userForm.controls.bucket_quota_enabled.value && !userForm.getValue('bucket_quota_max_objects_unlimited')">
<label class="col-form-label col-sm-3"
for="bucket_quota_max_objects">
class="form-control"
type="number"
formControlName="bucket_quota_max_objects">
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="userForm.showError('bucket_quota_max_objects', frm, 'required')"
i18n>This field is required.</span>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="userForm.showError('bucket_quota_max_objects', frm, 'min')"
i18n>The entered value must be >= 0.</span>
</div>
<div class="modal-body">
<!-- Username -->
- <div class="form-group row"
- [ngClass]="{':invalid': formGroup.showError('user', frm)}">
+ <div class="form-group row">
<label class="col-form-label col-sm-3"
for="user">
<ng-container i18n>Username</ng-container>
<option *ngFor="let userCandidate of userCandidates"
[value]="userCandidate">{{ userCandidate }}</option>
</select>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="formGroup.showError('user', frm, 'required')"
i18n>This field is required.</span>
</div>
<!-- Access key -->
<div class="form-group row"
- [ngClass]="{':invalid': formGroup.showError('access_key', frm)}"
*ngIf="!formGroup.getValue('generate_key')">
<label class="col-form-label col-sm-3"
for="access_key">
</button>
</span>
</div>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="formGroup.showError('access_key', frm, 'required')"
i18n>This field is required.</span>
</div>
<!-- Secret key -->
<div class="form-group row"
- [ngClass]="{':invalid': formGroup.showError('secret_key', frm)}"
*ngIf="!formGroup.getValue('generate_key')">
<label class="col-form-label col-sm-3"
for="secret_key">
</button>
</span>
</div>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="formGroup.showError('secret_key', frm, 'required')"
i18n>This field is required.</span>
</div>
<div class="modal-body">
<!-- Username -->
- <div class="form-group row"
- [ngClass]="{':invalid': formGroup.showError('uid', frm)}">
+ <div class="form-group row">
<label class="col-form-label col-sm-3"
for="uid"
i18n>Username</label>
</div>
<!-- Subuser -->
- <div class="form-group row"
- [ngClass]="{':invalid': formGroup.showError('subuid', frm)}">
+ <div class="form-group row">
<label class="col-form-label col-sm-3"
for="subuid">
<ng-container i18n>Subuser</ng-container>
formControlName="subuid"
[readonly]="editing"
autofocus>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="formGroup.showError('subuid', frm, 'required')"
i18n>This field is required.</span>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="formGroup.showError('subuid', frm, 'subuserIdExists')"
i18n>The chosen subuser ID is already in use.</span>
</div>
</div>
<!-- Permission -->
- <div class="form-group row"
- [ngClass]="{':invalid': formGroup.showError('perm', frm)}">
+ <div class="form-group row">
<label class="col-form-label col-sm-3"
for="perm">
<ng-container i18n>Permission</ng-container>
<option i18n
value="full-control">full</option>
</select>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="formGroup.showError('perm', frm, 'required')"
i18n>This field is required.</span>
</div>
<!-- Secret key -->
<div class="form-group row"
- [ngClass]="{':invalid': formGroup.showError('secret_key', frm)}"
*ngIf="!editing && !formGroup.getValue('generate_secret')">
<label class="col-form-label col-sm-3"
for="secret_key">
</button>
</span>
</div>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="formGroup.showError('secret_key', frm, 'required')"
i18n>This field is required.</span>
</div>
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { RouterModule, Routes } from '@angular/router';
+import { NgBootstrapFormValidationModule } from 'ng-bootstrap-form-validation';
import { AlertModule } from 'ngx-bootstrap/alert';
import { BsDropdownModule } from 'ngx-bootstrap/dropdown';
import { ModalModule } from 'ngx-bootstrap/modal';
TabsModule.forRoot(),
TooltipModule.forRoot(),
ModalModule.forRoot(),
- RouterModule
+ RouterModule,
+ NgBootstrapFormValidationModule
],
exports: [
Rgw501Component,
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { RouterModule, Routes } from '@angular/router';
+import { NgBootstrapFormValidationModule } from 'ng-bootstrap-form-validation';
import { BsDropdownModule } from 'ngx-bootstrap/dropdown';
import { PopoverModule } from 'ngx-bootstrap/popover';
import { TabsModule } from 'ngx-bootstrap/tabs';
ReactiveFormsModule,
SharedModule,
TabsModule.forRoot(),
- RouterModule
+ RouterModule,
+ NgBootstrapFormValidationModule
],
declarations: [
LoginComponent,
</div>
<!-- Username -->
- <div class="form-group has-feedback"
- [ngClass]="{':invalid': (loginForm.submitted || username.dirty) && username.invalid}">
+ <div class="form-group has-feedback">
<input name="username"
[(ngModel)]="model.username"
#username="ngModel"
class="form-control"
required
autofocus>
- <div class="form-text text-muted"
+ <div class="invalid-feedback"
*ngIf="(loginForm.submitted || username.dirty) && username.invalid"
i18n>Username is required</div>
</div>
<!-- Password -->
- <div class="form-group has-feedback"
- [ngClass]="{':invalid': (loginForm.submitted || password.dirty) && password.invalid}">
+ <div class="form-group has-feedback">
<div class="input-group">
<input id="password"
name="password"
</button>
</span>
</div>
- <div class="form-text text-muted"
+ <div class="invalid-feedback"
*ngIf="(loginForm.submitted || password.dirty) && password.invalid"
i18n>Password is required</div>
</div>
<div class="card-body">
<!-- Name -->
- <div class="form-group row"
- [ngClass]="{':invalid': roleForm.showError('name', formDir)}">
+ <div class="form-group row">
<label class="col-form-label col-sm-3"
for="name">
<ng-container i18n>Name</ng-container>
name="name"
formControlName="name"
autofocus>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="roleForm.showError('name', formDir, 'required')"
i18n>This field is required.</span>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="roleForm.showError('name', formDir, 'notUnique')"
i18n>The chosen name is already in use.</span>
</div>
</div>
<!-- Description -->
- <div class="form-group row"
- [ngClass]="{':invalid': roleForm.showError('description', formDir)}">
+ <div class="form-group row">
<label i18n
class="col-form-label col-sm-3"
for="description">Description</label>
<div class="card-body">
<!-- Username -->
- <div class="form-group row"
- [ngClass]="{':invalid': userForm.showError('username', formDir)}">
+ <div class="form-group row">
<label class="col-form-label col-sm-3"
for="username">
<ng-container i18n>Username</ng-container>
name="username"
formControlName="username"
autofocus>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="userForm.showError('username', formDir, 'required')"
i18n>This field is required.</span>
</div>
</div>
<!-- Password -->
- <div class="form-group row"
- [ngClass]="{':invalid': userForm.showError('password', formDir)}">
+ <div class="form-group row">
<label i18n
class="col-form-label col-sm-3"
for="password">Password</label>
</button>
</span>
</div>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="userForm.showError('password', formDir, 'required')"
i18n>This field is required.</span>
</div>
</div>
<!-- Confirm password -->
- <div class="form-group row"
- [ngClass]="{':invalid': userForm.showError('confirmpassword', formDir)}">
+ <div class="form-group row">
<label i18n
class="col-form-label col-sm-3"
for="confirmpassword">Confirm password</label>
</button>
</span>
</div>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="userForm.showError('confirmpassword', formDir, 'required')"
i18n>This field is required.</span>
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="userForm.showError('confirmpassword', formDir, 'match')"
i18n>Password confirmation doesn't match the password.</span>
</div>
</div>
<!-- Email -->
- <div class="form-group row"
- [ngClass]="{':invalid': userForm.showError('email', formDir)}">
+ <div class="form-group row">
<label i18n
class="col-form-label col-sm-3"
for="email">Email</label>
name="email"
formControlName="email">
- <span class="form-text text-muted"
+ <span class="invalid-feedback"
*ngIf="userForm.showError('email', formDir, 'email')"
i18n>Invalid email.</span>
</div>
import { NgModule } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
+import { NgBootstrapFormValidationModule } from 'ng-bootstrap-form-validation';
import { ChartsModule } from 'ng2-charts/ng2-charts';
import { AlertModule } from 'ngx-bootstrap/alert';
import { BsDropdownModule } from 'ngx-bootstrap/dropdown';
PipesModule,
ModalModule.forRoot(),
DirectivesModule,
- BsDropdownModule
+ BsDropdownModule,
+ NgBootstrapFormValidationModule
],
declarations: [
ViewCacheComponent,
<div class="question">
<p i18n>Are you sure that you want to
{{ actionDescription | lowercase }} the selected {{ itemDescription }}?</p>
- <div class="form-group"
- [ngClass]="{':invalid': deletionForm.showError('confirmation', formDir)}">
+ <div class="form-group">
<div class="custom-control custom-checkbox">
<input type="checkbox"
class="custom-control-input"
#formDir="ngForm"
[formGroup]="form"
novalidate>
- <div [ngClass]="{':invalid': form.showError('filter', formDir)}">
+ <div>
<input type="text"
formControlName="filter"
i18n-placeholder
(keyup)="$event.keyCode == 13 ? selectOption() : updateFilter()"
class="form-control text-center" />
<ng-container *ngFor="let error of Object.keys(messages.customValidations)">
- <span class="form-text text-muted text-center"
+ <span class="invalid-feedback text-center"
*ngIf="form.showError('filter', formDir) && filter.hasError(error)">
{{ messages.customValidations[error] }}
</span>
{{ messages.add }} '{{ filter.value }}'
</div>
</div>
- <div class=":invalid"
+ <div class="is-invalid"
*ngIf="data.length === selectionLimit">
<span class="form-text text-muted text-center text-warning"
[tooltip]="messages.selectionLimit.tooltip"
'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
$badge-font-size: 1rem;
+$form-feedback-font-size: 100%;
@import '~bootstrap/scss/bootstrap';
@import '~fork-awesome/scss/fork-awesome';
@import 'app/ceph/dashboard/info-card/info-card-popover.scss';
+/* Reset checkbox success color */
+.was-validated .custom-control-input:valid,
+.custom-control-input.is-valid {
+ ~ .custom-control-label {
+ color: initial;
+ }
+
+ &:checked ~ .custom-control-label::before {
+ border-color: $custom-control-indicator-checked-border-color;
+ background-color: $component-active-bg;
+ }
+
+ ~ .custom-control-label::before {
+ border-color: $custom-control-indicator-border-color;
+ }
+
+ &:focus ~ .custom-control-label::before {
+ box-shadow: $custom-control-indicator-focus-box-shadow;
+ }
+
+ &:focus:not(:checked) ~ .custom-control-label::before {
+ border-color: $custom-control-indicator-focus-border-color;
+ }
+}
+
/* Basics */
html {
background-color: $color-app-bg;
@extend .p-2;
// @extend my-2;
}
+
+bfv-messages {
+ display: none;
+}