Commit f4faa22c authored by AlexKarpov's avatar AlexKarpov
Browse files

NAS-113116: Refactor ServiceWebdavComponent to use ix forms

parent a98de752
base DOCS DOCS-3538 NAS-010101 NAS-100796 NAS-105865 NAS-108939 NAS-110488 NAS-110533 NAS-110571 NAS-110777 NAS-110800 NAS-111872 NAS-111962-master NAS-111989 NAS-112060 NAS-112189 NAS-112307 NAS-112334 NAS-112343 NAS-112371 NAS-112767 NAS-112767-alt2 NAS-112767-mocks NAS-112795 NAS-112921 NAS-112945 NAS-112995-22.12 NAS-113044 NAS-113053 NAS-113219 NAS-113238 NAS-113292 NAS-113293-reproduction NAS-113363-3 NAS-113370 NAS-113375 NAS-113377 NAS-113378 NAS-113464 NAS-113464-alt NAS-113474 NAS-113486 NAS-113490 NAS-113511 NAS-113590 NAS-113598 NAS-113651 NAS-113671 NAS-113675 NAS-113679 NAS-113695 NAS-113701 NAS-113706 NAS-113708 NAS-113709 NAS-113723-22.02-RC.2 NAS-113733 NAS-113734 NAS-113738-22.02 NAS-113760 NAS-113790 NAS-113817 NAS-113821 NAS-113837 NAS-113860 NAS-113867 NAS-113876 NAS-113903 NAS-113903-2 NAS-113904-2 NAS-113953 NAS-114032 NAS-114045 NAS-114058 NAS-114084 NAS-114087 NAS-114088 NAS-114098 NAS-114171 NAS-114173 NAS-114179 NAS-114179-2 NAS-114204 NAS-114214 NAS-114215 NAS-114241 NAS-114338 NAS-114347 NAS-114389 NAS-114410 NAS-114413-2 NAS-114420 NAS-114428 NAS-114447 NAS-114448 NAS-114448-bluefin NAS-114471 NAS-114546 NAS-114549 NAS-114554 NAS-114607 NAS-114622 NAS-114639 NAS-114659 NAS-114660 NAS-114751 NAS-114769 NAS-114806 NAS-114845 NAS-114846 NAS-114881 NAS-114915 NAS-114950 NAS-115146 NAS-115162 NAS-115254 NAS-115271 NAS-115339 NAS-115340 NAS-115357 NAS-115488 NAS-115546 NAS-115547 NAS-115593 NAS-115593-2 NAS-115593-3 NAS-115593-4 NAS-115593-5 NAS-115593-6 NAS-115593-7 NAS-115713-22-12 NAS-115759 NAS-115759-22.12 NAS-115887-22.02.1 NAS-115942-22.02 NAS-116151 NAS-116162 NAS-116334-1 NAS-116334-2 NAS-116393 NAS-116395 NAS-116397 NAS-116397-2 NAS-116397-3 NAS-116398 NAS-116405 NAS-116406 NAS-116410 NAS-116422 NAS-116450 NAS-116469 NAS-116609 NAS-116715 NAS-116715-mobile NAS-116715-v2 NAS-116724 NAS-116915 NAS-116916 NAS-117017 NAS-117019 NAS-117028-22.12-BETA.2 NAS-117060 NAS-117098 NAS-117149-22.12 NAS-117216 NAS-117233 NAS-117239 NAS-117253 NAS-117278 NAS-117317 NAS-117323 NAS-117333 NAS-117401 NAS-117439 NAS-117475 NAS-117476 NAS-117481-test NAS-117520 NAS-117573-v2 NAS-117594 NAS-117628 NAS-117688-bluefin NAS-117700 NAS-117713-12 NAS-117714 NAS-117718 NAS-117734 NAS-117768 NAS-117813 NAS-117823 NAS-117841-2 NAS-117846 NAS-117959 NAS-118036 NAS-118044 NAS-118113 NAS-118165 NAS-118303 NAS-118454-22.12 NAS-118465 NAS-118505-22.12 NAS-118545 NAS-118548 NAS-119131 NAS-119140 NAS-119180-22.12.1 NAS-119431 NAS-119556-23.10 NAS-119615-22.12.1 NAS-119668 NAS-119695 NAS-119749-bluefin NAS-119750-22.12.1 NAS-119806 NAS-119812 NAS-119886-22.12.1 NAS-119996 NAS-119996-bluefin NAS-120045 NAS-120047 NAS-120057 NAS-120173-22.12.1 NAS-120181-22.12.1 NAS-120264-22.12.1 NAS-120274 NAS-120296-22.12.1 NAS-120326-22.12.1 NAS-120490_ NAS-120503 NAS-121006-22.12.2 NAS-121124 NAS-121128-22.12.2 NAS-121128-release-22.12.2 NAS-121136 NAS-121177 NAS-121218-22.12.3 NAS-121300 NAS-121316 NAS-121541 NAS-121542 NAS-121686 NAS-121721-22.12.3 NAS-121778 NAS-121827 NAS-121884-22.12.3 NAS-122267-22.12.4 NAS-122372 NAS-122601 NAS-122686 NAS-122706 NAS-122721 NAS-122751-23.10-BETA.1 NAS-122759 NAS-122781 NAS-122794-23.10 NAS-122855 NAS-122870-bluefin NAS-122969 NAS-122993-22.12.4 NAS-123055-22.12.4 NAS-123278 NAS-123295 NAS-123437 NAS-123478-22.12.4 NAS-123484 NAS-123492 NAS-123526-22.12.4 NAS-123651 NAS-123651-23.10-BETA.1 NAS-123666 NAS-123723 NAS-123723-cobia NAS-123762 NAS-123762-23.10 NAS-123778-23.10 NAS-123778-23.10-RC.1 NAS-123778-RC.1 NAS-123801 NAS-123810-23.10 NAS-123813-22.12.4 NAS-123836 NAS-123836-23.10-BETA.1 NAS-123836-24.04 NAS-123861 NAS-123911-23.10-BETA.1 NAS-123928-23.10 NAS-123931-22.12.4 NAS-123945 NAS-124044 NAS-124077 NAS-124131-23.10 NAS-124137 NAS-124183 NAS-124231 NAS-124232 NAS-124237-23.10 NAS-124325-23.10.0 NAS-124335 NAS-124354 NAS-124430 NAS-124454 NAS-124481-23.10.0 NAS-124481-23.10.1 NAS-124555-23.10.0 NAS-124555-23.10.1 NAS-124666 NAS-124707-23.10.0 NAS-124707-23.10.1 NAS-124716 NAS-124846-23.10.0 NAS-124846-23.10.1 NAS-124892 NAS-124895-23.10.1 NAS-124908 NAS-124951 NAS-124964 NAS-124999 NAS-125092 NAS-125213-23.10.1 NAS-125307 NAS-125532 NAS-125568 NAS-125607-validator NAS-125616-23.10.2 NAS-125654 NAS-125703-23.10.2 NAS-125728 NAS-125931 NAS-126699 NAS-126774-24.04-RC.1 NAS-126774-dragonfish NAS-126795 NAS-126795-test NAS-126795-test2 NAS-127001 NAS-127002-24.04-RC.1 NAS-127022 NAS-127041-24.04-BETA.1 NAS-127049-24.04-RC.1 NAS-127297-24.04-RC.1 NAS-127297-24.10 NAS-127369 NAS-127551 NAS-127551-alt NAS-127589-24.04.0 NAS-127593 NAS-127615-24.04.0 NAS-127660 NAS-127794 NAS-127829-24.10 NAS-127854-24.04.0 NAS-128030 NAS-128045 NAS-128071 NAS-128173 NAS-128209 NAS-128287 NAS-128289 TE-1553-dragonfish TE-1628 auto-129 back bugfix/NAS-117859-sidebar-menu-fix bugfix/NAS-117941-error-when-removing-pools-and-visit-datasets bugfix/NAS-118171-rsynk-task-local-path bugfix/NAS-118260-boot-env-keep-table-row bugfix/NAS-118282-search-input-fixes bugfix/NAS-118404-dataset-icon-role-double-toooltip bugfix/NAS-118414-warning-modal-icon bugfix/NAS-118415-tree-select-undefined bugfix/NAS-118454-acl-manager-after-dataset-creation-fix bugfix/NAS-118470-multiselext-styles-are-broken bugfix/NAS-118503-datasets-glitch-fix bugfix/NAS-118504-redirect-to-correct-dataset-after-permissions-submit bugfix/NAS-118510-redirect-url-fix-after-manual-change bugfix/NAS-118530-advanced-settings-box-duplicates bugfix/NAS-118541-progress-bar-oberflows bugfix/NAS-118557-replication-task-forbid-custom-retention-policy-cases bugfix/NAS-118600-smb-share-redirect bugfix/NAS-118601-remove-mixed-for-zfs-datasets cpu-pinning dataset-tree-tooltips developer/lyy feature/NAS-117754-font-rendering feature/NAS-117968-tooltips-to-status-icons-on-pools feature/NAS-118058-improve-dashboard-icons-sync-pool-and-storage feature/NAS-118147-html-refactoring feature/NAS-118269-improve-ui feature/NAS-118303 feature/NAS-118333-storage-dashboard-icons-update feature/NAS-118334-screentype-enum feature/NAS-118335-improve-spinners-look feature/NAS-118349-datasets-long-names feature/NAS-118360-handle-clipboard-api-not-available feature/NAS-118412-pool-processing-modal feature/NAS-118466-root-path-mnt feature/NAS-118543-user-password-field feauture/NAS-117474-datasets-table-header-sticky l10n_master llll master master-old metrics-enable patch-1 patch-235 q5sys-3838 rel-v0.0.1 release-test/22.02.3 release/22.02 release/22.02-RC.2 release/22.02-test release/22.02.1 release/22.02.2 release/22.02.3 release/22.02.4 release/22.12 release/22.12-BETA.1 release/22.12-BETA.2 release/22.12-RC.1 release/22.12.1 release/22.12.2 release/22.12.3 release/22.12.4 release/23.10-BETA.1 release/23.10-RC.1 release/23.10.0 release/23.10.1 release/23.10.1.1 release/23.10.1.2 release/23.10.1.3 release/23.10.2 release/24.04-BETA.1 release/24.04-RC.1 release/24.04.0 renediepenbroek/master revert-6783-NAS-116405 revert-7745-NAS-120274 stable/angelfish stable/bluefin stable/cobia stable/dragonfish t1356-scaleuitest test-xxxyyy testing-refine-branchout-process testing-refine-branchout-process2 v0.0.2 TS-24.04-RC.1 TS-24.04-BETA.1 TS-23.10.2 TS-23.10.1.3 TS-23.10.1.2 TS-23.10.1.1 TS-23.10.1 TS-23.10.0.1 TS-23.10.0 TS-23.10-RC.1 TS-23.10-BETA.1 TS-22.12.4.2 TS-22.12.4.1 TS-22.12.4 TS-22.12.3.3 TS-22.12.3.2 TS-22.12.3.1 TS-22.12.3 TS-22.12.2 TS-22.12.1 TS-22.12.0 TS-22.12-RC.1 TS-22.12-BETA.2 TS-22.12-BETA.1 TS-22.12-ALPHA.1 TS-22.02.4 TS-22.02.3 TS-22.02.2.1 TS-22.02.2 TS-22.02.1 TS-22.02.0.1 TS-22.02.0 TS-22.2.0 TS-22.02.RELEASE.1 TS-22.02-RC.2 TS-12.12.3 DN110M-CS-v2.0
No related merge requests found
Showing with 464 additions and 150 deletions
+464 -150
......@@ -13,16 +13,30 @@
<input
matInput
[class.prefix-padding]="prefixIcon"
[class.security-disc]="isSecurity()"
[required]="required"
[disabled]="isDisabled"
[type]="type"
type="getType()"
[(ngModel)]="value"
(ngModelChange)="onChange($event)"
(blur)="onTouch()"
[autocomplete]="autocomplete"
[autocapitalize]="autocapitalize"
>
<span *ngIf="shouldShowResetInput()" class="reset-input">
<mat-icon (click)="resetInput()" role="img" fontSet="mdi-set" fontIcon="mdi-close-circle"></mat-icon>
</span>
<button
*ngIf="shouldShowToggle()"
mat-icon-button type="button"
class="toggle_pw"
(click)="togglePW()"
ix-auto
ix-auto-type="button"
ix-auto-identifier="{{label}}_toggle-pw">
<i class="material-icons" matTooltip="Hide" *ngIf="showPassword">visibility</i>
<i class="material-icons" matTooltip="Show" *ngIf="!showPassword">visibility_off</i>
</button>
</div>
<ix-form-errors [control]="controlDirective.control" [label]="label"></ix-form-errors>
<mat-hint *ngIf="hint">{{hint}}</mat-hint>
......@@ -76,3 +76,14 @@
max-width: 16px;
width: auto;
}
.input-container .mat-icon-button {
height: 24px;
line-height: 24px;
opacity: 0.5;
width: 24px;
}
.security-disc {
-webkit-text-security: disc;
}
......@@ -19,9 +19,13 @@ export class IxInputComponent implements ControlValueAccessor {
@Input() tooltip: string;
@Input() required: boolean;
@Input() type: string;
@Input() togglePw: boolean;
@Input() autocomplete = 'off';
@Input() autocapitalize = 'off';
value = '';
isDisabled = false;
showPassword = false;
onChange: (value: string | number) => void = (): void => {};
onTouch: () => void = (): void => {};
......@@ -46,8 +50,20 @@ export class IxInputComponent implements ControlValueAccessor {
this.onTouch = onTouched;
}
shouldShowToggle(): boolean {
return this.type === 'password' && this.togglePw;
}
shouldShowResetInput(): boolean {
return !this.isDisabled && this.hasValue();
return !this.isDisabled && this.hasValue() && !this.shouldShowToggle();
}
getType(): string {
return this.type === 'password' ? 'text' : this.type;
}
isSecurity(): boolean {
return this.type === 'password' && !this.showPassword;
}
hasValue(): boolean {
......@@ -63,4 +79,8 @@ export class IxInputComponent implements ControlValueAccessor {
this.isDisabled = isDisabled;
this.cdr.markForCheck();
}
togglePW(): void {
this.showPassword = !this.showPassword;
}
}
<mat-card class="form-card">
<mat-card-content>
<form [formGroup]="form" class="ix-form-container" (submit)="onSubmit()">
<ix-fieldset [title]="helptext.fieldset_title">
<ix-select
[formControlName]="protocol.fcName"
[label]="protocol.label"
[tooltip]="protocol.tooltip"
[options]="protocol.options"
(ngModelChange)="onChangeProtocal($event)"
></ix-select>
<ix-input
*ngIf="!tcpport.hidden"
[formControlName]="tcpport.fcName"
[label]="tcpport.label"
[tooltip]="tcpport.tooltip"
></ix-input>
<ix-input
*ngIf="!tcpportssl.hidden"
[formControlName]="tcpportssl.fcName"
[label]="tcpportssl.label"
[tooltip]="tcpportssl.tooltip"
></ix-input>
<ix-select
*ngIf="!certssl.hidden"
[formControlName]="certssl.fcName"
[label]="certssl.label"
[tooltip]="certssl.tooltip"
[options]="certssl.options"
></ix-select>
<ix-select
[formControlName]="htauth.fcName"
[label]="htauth.label"
[tooltip]="htauth.tooltip"
[options]="htauth.options"
(ngModelChange)="onChangeHtAuth($event)"
></ix-select>
<ix-input
*ngIf="pwdRequired"
[formControlName]="password.fcName"
[label]="password.label"
[tooltip]="password.tooltip"
type="password"
[togglePw]="true"
></ix-input>
<ix-input
*ngIf="pwdRequired"
[formControlName]="password2.fcName"
[label]="password2.label"
type="password"
></ix-input>
</ix-fieldset>
<div class="form-actions">
<button
mat-button
type="submit"
[disabled]="form.invalid || isFormLoading"
color="primary"
>{{ 'Save' }}</button>
<button
mat-button
color="accent"
class="ml-05"
(click)="cancel()"
>{{ 'Cancel' }}</button>
</div>
</form>
</mat-card-content>
</mat-card>
\ No newline at end of file
.form-actions {
margin: 8px 10px;
}
import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { ReactiveFormsModule } from '@angular/forms';
import { MatButtonHarness } from '@angular/material/button/testing';
import { createComponentFactory, mockProvider, Spectator } from '@ngneat/spectator/jest';
import { Observable, of } from 'rxjs';
import { mockCall, mockWebsocket } from 'app/core/testing/utils/mock-websocket.utils';
import { Certificate } from 'app/interfaces/certificate.interface';
import { WebdavConfig } from 'app/interfaces/webdav-config.interface';
import { IxFormsModule } from 'app/pages/common/ix-forms/ix-forms.module';
import { FormErrorHandlerService } from 'app/pages/common/ix-forms/services/form-error-handler.service';
import { IxFormHarness } from 'app/pages/common/ix-forms/testing/ix-form.harness';
import { ServiceWebdavComponent } from 'app/pages/services/components/service-webdav/service-webdav.component';
import {
AppLoaderService, DialogService, SystemGeneralService, WebSocketService,
} from 'app/services';
describe('ServiceWebdavComponent', () => {
let spectator: Spectator<ServiceWebdavComponent>;
let loader: HarnessLoader;
let ws: WebSocketService;
const createComponent = createComponentFactory({
component: ServiceWebdavComponent,
imports: [
IxFormsModule,
ReactiveFormsModule,
],
providers: [
mockWebsocket([
mockCall('webdav.config', {
protocol: 'HTTPHTTPS',
tcpport: 8080,
tcpportssl: 8081,
certssl: 1,
htauth: 'BASIC',
password: 'pleasechange',
id: 1,
} as WebdavConfig),
mockCall('kerberos.update'),
]),
mockProvider(FormErrorHandlerService),
mockProvider(SystemGeneralService, {
getCertificates(): Observable<Certificate[]> {
return of([
{
CA_type_existing: false,
CA_type_intermediate: false,
CA_type_internal: false,
CSR: null,
DN: '/C=US/O=iXsystems/CN=localhost/emailAddress=info@ixsystems.com/ST=Tennessee/L=Maryville/subjectAltName=DNS:localhost',
can_be_revoked: false,
cert_type: 'CERTIFICATE',
cert_type_CSR: false,
cert_type_existing: true,
cert_type_internal: false,
certificate: '-----BEGIN CERTIFICATE-----\nMIID....XlGxqmLs\n-----END CERTIFICATE-----\n',
certificate_path: '/etc/certificates/freenas_default.crt',
chain: false,
chain_list: ['-----BEGIN CERTIFICATE-----\nMIIDrTCCApWgAwIBAgIECg…DoVkBf/Sh1NB2cXlGxqmLs\n-----END CERTIFICATE-----\n'],
city: 'Maryville',
common: 'localhost',
country: 'US',
csr_path: '/etc/certificates/freenas_default.csr',
digest_algorithm: 'SHA256',
email: 'info@ixsystems.com',
extensions: { SubjectAltName: 'DNS:localhost', ExtendedKeyUsage: 'TLS Web Server Authentication' },
fingerprint: '88:0D:D0:12:BC:47:47:96:05:6A:8E:B8:C3:86:E5:6B:5B:E8:E9:1C',
from: 'Fri Oct 29 14:11:19 2021',
id: 1,
internal: 'NO',
issuer: 'external',
key_length: 2048,
key_type: 'RSA',
lifetime: 397,
name: 'freenas_default',
organization: 'iXsystems',
organizational_unit: null,
parsed: true,
privatekey: '-----BEGIN PRIVATE KEY-----\nMIIE....URCL/n\nH9Vn5+0sIJoZ5pZMg/H9RMWdYg==\n-----END PRIVATE KEY-----\n',
privatekey_path: '/etc/certificates/freenas_default.key',
revoked: false,
revoked_date: null,
root_path: '/etc/certificates',
san: ['DNS:localhost'],
serial: 168294129,
signedby: null,
state: 'Tennessee',
subject_name_hash: 3193428416,
type: 8,
until: 'Wed Nov 30 13:11:19 2022',
},
]);
},
}),
mockProvider(AppLoaderService),
mockProvider(DialogService),
],
});
beforeEach(() => {
spectator = createComponent();
loader = TestbedHarnessEnvironment.loader(spectator.fixture);
ws = spectator.inject(WebSocketService);
});
it('loads current webdav config and show them', async () => {
const form = await loader.getHarness(IxFormHarness);
const values = await form.getValues();
expect(ws.call).toHaveBeenCalledWith('webdav.config');
expect(values).toEqual({
Protocol: 'HTTP+HTTPS',
'HTTP Port': '8080',
'HTTPS Port': '8081',
'Webdav SSL Certificate': 'freenas_default',
'HTTP Authentication': 'Basic Authentication',
'Webdav Password': 'pleasechange',
'Confirm Password': '',
});
});
it('sends an update payload to websocket when settings are updated and saved', async () => {
const form = await loader.getHarness(IxFormHarness);
await form.fillForm({
Protocol: 'HTTP+HTTPS',
'HTTP Port': '8000',
'HTTPS Port': '8001',
'Webdav SSL Certificate': 'freenas_default',
'HTTP Authentication': 'Digest Authentication',
'Webdav Password': 'oh, got it',
'Confirm Password': 'oh, got it',
});
const saveButton = await loader.getHarness(MatButtonHarness.with({ text: 'Save' }));
await saveButton.click();
expect(ws.call).toHaveBeenCalledWith('webdav.update', [{
protocol: 'HTTPHTTPS',
tcpport: '8000',
tcpportssl: '8001',
certssl: 1,
htauth: 'DIGEST',
password: 'oh, got it',
}]);
});
});
import {
ApplicationRef, Component, Injector,
ChangeDetectionStrategy,
ChangeDetectorRef, Component, OnInit,
} from '@angular/core';
import { FormControl } from '@angular/forms';
import {
Validators,
} from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router';
import { FormBuilder } from '@ngneat/reactive-forms';
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
import * as _ from 'lodash';
import { Observable } from 'rxjs';
import { Observable, of } from 'rxjs';
import { map } from 'rxjs/operators';
import helptext from 'app/helptext/services/components/service-webdav';
import { FormConfiguration } from 'app/interfaces/entity-form.interface';
import { Option } from 'app/interfaces/option.interface';
import { WebdavConfig, WebdavConfigUpdate } from 'app/interfaces/webdav-config.interface';
import { EntityFormComponent } from 'app/pages/common/entity/entity-form/entity-form.component';
import { FieldConfig, FormSelectConfig } from 'app/pages/common/entity/entity-form/models/field-config.interface';
import { FieldSet } from 'app/pages/common/entity/entity-form/models/fieldset.interface';
import { SystemGeneralService, WebSocketService, ValidationService } from 'app/services';
import { EntityUtils } from 'app/pages/common/entity/utils';
import { FormErrorHandlerService } from 'app/pages/common/ix-forms/services/form-error-handler.service';
import {
SystemGeneralService, WebSocketService, ValidationService, DialogService, AppLoaderService,
} from 'app/services';
@UntilDestroy()
@Component({
selector: 'webdav-edit',
template: '<entity-form [conf]="this"></entity-form>',
providers: [SystemGeneralService],
templateUrl: './service-webdav.component.html',
styleUrls: ['./service-webdav.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ServiceWebdavComponent implements FormConfiguration {
queryCall = 'webdav.config' as const;
editCall = 'webdav.update' as const;
route_success: string[] = ['services'];
title = helptext.formTitle;
fieldConfig: FieldConfig[] = [];
fieldSets: FieldSet[] = [
{
name: helptext.fieldset_title,
width: '100%',
label: true,
config: [
{
type: 'select',
name: 'protocol',
placeholder: helptext.protocol_placeholder,
tooltip: helptext.protocol_tooltip,
options: helptext.protocol_options,
},
{
type: 'input',
name: 'tcpport',
placeholder: helptext.tcpport_placeholder,
tooltip: helptext.tcpport_tooltip,
},
{
type: 'input',
name: 'tcpportssl',
placeholder: helptext.tcpportssl_placeholder,
tooltip: helptext.tcpportssl_tooltip,
},
{
type: 'select',
name: 'certssl',
placeholder: helptext.certssl_placeholder,
tooltip: helptext.certssl_tooltip,
options: [{ label: '---', value: null }],
},
{
type: 'select',
name: 'htauth',
placeholder: helptext.htauth_placeholder,
tooltip: helptext.htauth_tooltip,
options: helptext.htauth_options,
},
{
type: 'input',
name: 'password',
placeholder: helptext.password_placeholder,
togglePw: true,
tooltip: helptext.password_tooltip,
inputType: 'password',
},
{
type: 'input',
name: 'password2',
placeholder: helptext.password2_placeholder,
inputType: 'password',
validation: this.validationService.matchOtherValidator('password'),
},
],
}];
private webdav_protocol: FormControl;
private webdav_tcpport: FieldConfig;
private webdav_tcpportssl: FieldConfig;
private webdav_certssl: FormSelectConfig;
private webdav_htauth: FormControl;
private webdav_password: FieldConfig;
private webdav_password2: FieldConfig;
private entityForm: EntityFormComponent;
export class ServiceWebdavComponent implements OnInit {
isFormLoading = false;
form = this.fb.group({
protocol: [''],
tcpport: [null as number, [Validators.min(1), Validators.max(65535)]],
tcpportssl: [null as number, [Validators.min(1), Validators.max(65535)]],
certssl: [null as any],
htauth: [''],
password: [''],
password2: ['', [this.validationService.matchOtherValidator('password')]],
});
readonly helptext = helptext;
protocol: {
readonly fcName: 'protocol';
label: string;
tooltip: string;
options: Observable<Option[]>;
} = {
fcName: 'protocol',
label: helptext.protocol_placeholder,
tooltip: helptext.protocol_tooltip,
options: of(helptext.protocol_options),
};
tcpport: {
readonly fcName: 'tcpport';
label: string;
tooltip: string;
hidden: boolean;
} = {
fcName: 'tcpport',
label: helptext.tcpport_placeholder,
tooltip: helptext.tcpport_tooltip,
hidden: false,
};
tcpportssl: {
readonly fcName: 'tcpportssl';
label: string;
tooltip: string;
hidden: boolean;
} = {
fcName: 'tcpportssl',
label: helptext.tcpportssl_placeholder,
tooltip: helptext.tcpportssl_tooltip,
hidden: false,
};
certssl: {
readonly fcName: 'certssl';
label: string;
tooltip: string;
options: Observable<Option[]>;
hidden: boolean;
} = {
fcName: 'certssl',
label: helptext.certssl_placeholder,
tooltip: helptext.certssl_tooltip,
options: this.systemGeneralService.getCertificates().pipe(
map((certificates) => {
const options = certificates.map((certificate) => ({
label: certificate.name,
value: certificate.id,
}));
return [
{ label: '---', value: null },
...options,
];
}),
),
hidden: false,
};
htauth: {
readonly fcName: 'htauth';
label: string;
tooltip: string;
options: Observable<Option[]>;
} = {
fcName: 'htauth',
label: helptext.htauth_placeholder,
tooltip: helptext.htauth_tooltip,
options: of(helptext.htauth_options),
};
password: {
readonly fcName: 'password';
label: string;
tooltip: string;
} = {
fcName: 'password',
label: helptext.password_placeholder,
tooltip: helptext.password_tooltip,
};
password2: {
readonly fcName: 'password2';
label: string;
} = {
fcName: 'password2',
label: helptext.password2_placeholder,
};
pwdRequired = true;
constructor(
private fb: FormBuilder,
protected router: Router,
protected route: ActivatedRoute,
protected ws: WebSocketService,
protected _injector: Injector,
protected _appRef: ApplicationRef,
protected systemGeneralService: SystemGeneralService,
protected validationService: ValidationService,
private cdr: ChangeDetectorRef,
private dialogService: DialogService,
private loader: AppLoaderService,
private errorHandler: FormErrorHandlerService,
) {}
resourceTransformIncomingRestData(data: WebdavConfig): any {
const transformed = { ...data };
const certificate = data['certssl'];
if (certificate && certificate.id) {
transformed['certssl'] = certificate.id;
}
delete transformed['password'];
return transformed;
}
ngOnInit(): void {
this.isFormLoading = true;
this.loader.open();
afterInit(entityForm: EntityFormComponent): void {
this.entityForm = entityForm;
this.entityForm.submitFunction = this.submitFunction;
this.webdav_tcpport = _.find(this.fieldConfig, { name: 'tcpport' });
this.webdav_tcpportssl = _.find(this.fieldConfig, { name: 'tcpportssl' });
this.webdav_password = _.find(this.fieldConfig, { name: 'password' });
this.webdav_password2 = _.find(this.fieldConfig, { name: 'password2' });
this.webdav_htauth = entityForm.formGroup.controls['htauth'] as FormControl;
this.webdav_protocol = entityForm.formGroup.controls['protocol'] as FormControl;
this.handleProtocol(this.webdav_protocol.value);
this.handleAuth(this.webdav_htauth.value);
this.webdav_protocol.valueChanges
.pipe(untilDestroyed(this))
.subscribe((value: string) => {
this.handleProtocol(value);
});
this.webdav_htauth.valueChanges
.pipe(untilDestroyed(this))
.subscribe((value: string) => {
this.handleAuth(value);
});
this.webdav_certssl = _.find(this.fieldConfig, { name: 'certssl' }) as FormSelectConfig;
this.systemGeneralService.getCertificates().pipe(untilDestroyed(this)).subscribe((res) => {
if (res.length > 0) {
res.forEach((item) => {
this.webdav_certssl.options.push(
{ label: item.name, value: item.id },
);
});
}
});
this.ws.call('webdav.config').pipe(untilDestroyed(this)).subscribe(
(config: WebdavConfig) => {
this.form.patchValue(config);
this.isFormLoading = false;
this.loader.close();
this.cdr.markForCheck();
},
(error) => {
this.isFormLoading = false;
this.loader.close();
new EntityUtils().handleWSError(null, error, this.dialogService);
},
);
}
handleProtocol(value: string): void {
if (value === 'HTTP') {
this.webdav_tcpport['isHidden'] = false;
this.webdav_tcpportssl['isHidden'] = true;
this.webdav_certssl['isHidden'] = true;
} else if (value === 'HTTPS') {
this.webdav_tcpport['isHidden'] = true;
this.webdav_tcpportssl['isHidden'] = false;
this.webdav_certssl['isHidden'] = false;
} else if (value === 'HTTPHTTPS') {
this.webdav_tcpport['isHidden'] = false;
this.webdav_tcpportssl['isHidden'] = false;
this.webdav_certssl['isHidden'] = false;
onChangeProtocal(value: string): void {
switch (value) {
case 'HTTP':
this.tcpport.hidden = false;
this.tcpportssl.hidden = true;
this.certssl.hidden = true;
break;
case 'HTTPS':
this.tcpport.hidden = true;
this.tcpportssl.hidden = false;
this.certssl.hidden = false;
break;
case 'HTTPHTTPS':
this.tcpport.hidden = false;
this.tcpportssl.hidden = false;
this.certssl.hidden = false;
break;
default:
break;
}
}
handleAuth(value: string): void {
onChangeHtAuth(value: string): void {
if (value === 'NONE') {
this.entityForm.setDisabled('password', true, true);
this.entityForm.setDisabled('password2', true, true);
this.form.controls.password.setValue('');
this.form.controls.password2.setValue('');
this.pwdRequired = false;
} else {
this.entityForm.setDisabled('password', false, false);
this.entityForm.setDisabled('password2', false, false);
this.pwdRequired = true;
}
}
submitFunction(body: WebdavConfigUpdate & { password2?: string }): Observable<WebdavConfig> {
delete body['password2'];
return this.ws.call('webdav.update', [body]);
onSubmit(): void {
this.isFormLoading = true;
this.loader.open();
const values = this.form.value;
delete values.password2;
this.ws.call('webdav.update', [values] as [WebdavConfigUpdate]).pipe(untilDestroyed(this)).subscribe(() => {
this.isFormLoading = false;
this.loader.close();
this.router.navigate(['/', 'services']);
}, (error) => {
this.isFormLoading = false;
this.loader.close();
this.errorHandler.handleWsFormError(error, this.form);
this.cdr.markForCheck();
});
}
cancel(): void {
this.router.navigate(['/', 'services']);
}
}
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { TranslateModule } from '@ngx-translate/core';
import { NgxDatatableModule } from '@swimlane/ngx-datatable';
import { MaterialModule } from 'app/app-material.module';
import { CommonDirectivesModule } from 'app/directives/common/common-directives.module';
import { IxFormsModule } from 'app/pages/common/ix-forms/ix-forms.module';
import { ServiceDDNSComponent } from 'app/pages/services/components/service-dynamicdns/service-dynamicdns.component';
import { ServiceFTPComponent } from 'app/pages/services/components/service-ftp/service-ftp.component';
import { ServiceLLDPComponent } from 'app/pages/services/components/service-lldp/service-lldp.component';
......@@ -38,6 +39,8 @@ import { routing } from './services.routing';
NgxDatatableModule,
TranslateModule,
CommonDirectivesModule,
IxFormsModule,
ReactiveFormsModule,
],
declarations: [
ServicesComponent,
......
......@@ -189,6 +189,10 @@ samp {
margin-left: 1rem !important;
}
.ml-05 {
margin-left: 0.5rem !important;
}
.mb-05 {
margin-bottom: 0.5rem !important;
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment