Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
truenas-rk3588
webui
Commits
b8f7350e
Unverified
Commit
b8f7350e
authored
3 years ago
by
RehanY147
Committed by
GitHub
3 years ago
Browse files
Options
Download
Email Patches
Plain Diff
NAS-115487 / 22.12 / SMB form refactor (#6605)
parent
8b6b0099
base
DOCS
DOCS-3538
NAS-010101
NAS-110800
NAS-111962-master
NAS-112995-22.12
NAS-114179
NAS-114179-2
NAS-115546
NAS-115593-6
NAS-115593-7
NAS-115759-22.12
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-116469
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-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-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
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
metrics-enable
patch-1
patch-235
rel-v0.0.1
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/bluefin
stable/cobia
stable/dragonfish
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-12.12.3
DN110M-CS-v2.0
No related merge requests found
Changes
113
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
src/app/helptext/sharing/smb/smb.ts
+2
-0
src/app/helptext/sharing/smb/smb.ts
src/app/interfaces/smb-share.interface.ts
+10
-1
src/app/interfaces/smb-share.interface.ts
src/app/modules/entity/table/expandable-table/expandable-table.component.html
+1
-1
...ty/table/expandable-table/expandable-table.component.html
src/app/modules/entity/table/expandable-table/expandable-table.component.ts
+3
-1
...tity/table/expandable-table/expandable-table.component.ts
src/app/modules/ix-forms/components/ix-chips/ix-chips.component.html
+2
-0
...ules/ix-forms/components/ix-chips/ix-chips.component.html
src/app/modules/ix-forms/components/ix-explorer/ix-explorer.component.html
+1
-1
...x-forms/components/ix-explorer/ix-explorer.component.html
src/app/modules/ix-forms/components/ix-explorer/ix-explorer.component.ts
+5
-0
.../ix-forms/components/ix-explorer/ix-explorer.component.ts
src/app/modules/ix-forms/components/ix-input/ix-input.component.html
+1
-1
...ules/ix-forms/components/ix-input/ix-input.component.html
src/app/modules/ix-forms/components/ix-input/ix-input.component.ts
+4
-2
...odules/ix-forms/components/ix-input/ix-input.component.ts
src/app/pages/sharing/components/shares-dashboard/shares-dashboard.component.html
+4
-4
...mponents/shares-dashboard/shares-dashboard.component.html
src/app/pages/sharing/components/shares-dashboard/shares-dashboard.component.ts
+57
-104
...components/shares-dashboard/shares-dashboard.component.ts
src/app/pages/sharing/iscsi/target/target-form/target-form.component.ts
+1
-0
...sharing/iscsi/target/target-form/target-form.component.ts
src/app/pages/sharing/nfs/nfs-form/nfs-form.component.ts
+2
-0
src/app/pages/sharing/nfs/nfs-form/nfs-form.component.ts
src/app/pages/sharing/sharing.module.ts
+4
-0
src/app/pages/sharing/sharing.module.ts
src/app/pages/sharing/smb/smb-form/restart-smb-dialog/restart-smb-dialog.component.html
+18
-0
...form/restart-smb-dialog/restart-smb-dialog.component.html
src/app/pages/sharing/smb/smb-form/restart-smb-dialog/restart-smb-dialog.component.ts
+45
-0
...b-form/restart-smb-dialog/restart-smb-dialog.component.ts
src/app/pages/sharing/smb/smb-form/smb-form.component.html
+154
-0
src/app/pages/sharing/smb/smb-form/smb-form.component.html
src/app/pages/sharing/smb/smb-form/smb-form.component.scss
+7
-0
src/app/pages/sharing/smb/smb-form/smb-form.component.scss
src/app/pages/sharing/smb/smb-form/smb-form.component.spec.ts
+427
-0
...app/pages/sharing/smb/smb-form/smb-form.component.spec.ts
src/app/pages/sharing/smb/smb-form/smb-form.component.ts
+396
-575
src/app/pages/sharing/smb/smb-form/smb-form.component.ts
with
1144 additions
and
690 deletions
+1144
-690
src/app/helptext/sharing/smb/smb.ts
View file @
b8f7350e
...
...
@@ -220,4 +220,6 @@ export const helptextSharingSmb = {
action
:
T
(
'
I Understand
'
),
},
restartPt1
:
T
(
'
The following changes to this SMB Share require the SMB Service to be restarted before they can take effect.
'
),
restartPt2
:
T
(
'
Would you like to restart the SMB Service?
'
),
};
This diff is collapsed.
Click to expand it.
src/app/interfaces/smb-share.interface.ts
View file @
b8f7350e
...
...
@@ -20,7 +20,7 @@ export interface SmbShare {
name
:
string
;
path
:
string
;
path_suffix
:
string
;
purpose
:
string
;
// Possibly enum: "DEFAULT_SHARE"
purpose
:
SmbPresetType
;
recyclebin
:
boolean
;
ro
:
boolean
;
shadowcopy
:
boolean
;
...
...
@@ -29,6 +29,15 @@ export interface SmbShare {
vuid
:
string
;
}
export
enum
SmbPresetType
{
NoPresets
=
'
NO_PRESET
'
,
DefaultShareParameters
=
'
DEFAULT_SHARE
'
,
MultiUserTimeMachine
=
'
ENHANCED_TIMEMACHINE
'
,
MultiProtocolShares
=
'
MULTI_PROTOCOL_NFS
'
,
PrivateSmbDatasets
=
'
PRIVATE_DATASETS
'
,
SmbWorm
=
'
WORM_DROPBOX
'
,
}
export
interface
SmbPreset
{
verbose_name
:
string
;
params
:
Partial
<
SmbShare
>
;
...
...
This diff is collapsed.
Click to expand it.
src/app/modules/entity/table/expandable-table/expandable-table.component.html
View file @
b8f7350e
...
...
@@ -28,7 +28,7 @@
</div>
</mat-panel-description>
</mat-expansion-panel-header>
<app-table
[conf]=
"tableConf"
></app-table>
<app-table
#tableComponent
[conf]=
"tableConf"
></app-table>
</mat-expansion-panel>
<div
id=
"actions-row"
[ngClass]=
"{'actions-row': isExpanded && tableConf.detailsHref}"
*ngIf=
"isExpanded && tableConf.detailsHref"
>
<div>
...
...
This diff is collapsed.
Click to expand it.
src/app/modules/entity/table/expandable-table/expandable-table.component.ts
View file @
b8f7350e
...
...
@@ -3,7 +3,7 @@ import {
Component
,
ElementRef
,
Input
,
OnInit
,
ViewChild
,
}
from
'
@angular/core
'
;
import
{
ServiceStatus
}
from
'
app/enums/service-status.enum
'
;
import
{
AppTableAction
,
AppTableConfig
}
from
'
app/modules/entity/table/table.component
'
;
import
{
AppTableAction
,
AppTableConfig
,
TableComponent
}
from
'
app/modules/entity/table/table.component
'
;
export
interface
InputExpandableTableConf
extends
AppTableConfig
{
detailsHref
?:
string
;
...
...
@@ -37,6 +37,8 @@ export class ExpandableTableComponent implements OnInit, AfterViewChecked {
@
Input
()
expandableTableState
:
ExpandableTableState
;
@
Input
()
disabled
:
boolean
;
@
ViewChild
(
'
tableComponent
'
)
tableComponent
:
TableComponent
;
@
ViewChild
(
'
appTable
'
,
{
read
:
ElementRef
})
appTable
:
ElementRef
;
...
...
This diff is collapsed.
Click to expand it.
src/app/modules/ix-forms/components/ix-chips/ix-chips.component.html
View file @
b8f7350e
...
...
@@ -8,6 +8,7 @@
<div
class=
"input-container"
[class.disabled]=
"isDisabled"
>
<mat-chip-list
[disabled]=
"isDisabled"
#chipList
class=
"form-chip"
[required]=
"required"
>
...
...
@@ -23,6 +24,7 @@
</mat-chip>
<input
[placeholder]=
"placeholder"
[disabled]=
"isDisabled"
[matChipInputFor]=
"chipList"
[matChipInputSeparatorKeyCodes]=
"separatorKeysCodes"
[matChipInputAddOnBlur]=
"true"
...
...
This diff is collapsed.
Click to expand it.
src/app/modules/ix-forms/components/ix-explorer/ix-explorer.component.html
View file @
b8f7350e
...
...
@@ -14,7 +14,7 @@
[(ngModel)]=
"value"
[required]=
"required"
[disabled]=
"isDisabled"
(ngModelChange)=
"
on
Change($event)"
(ngModelChange)=
"
value
Change
dCustom
($event)"
(blur)=
"onTouch()"
>
</div>
...
...
This diff is collapsed.
Click to expand it.
src/app/modules/ix-forms/components/ix-explorer/ix-explorer.component.ts
View file @
b8f7350e
...
...
@@ -137,6 +137,11 @@ export class IxExplorerComponent implements OnInit, ControlValueAccessor {
this
.
onChange
(
newValue
);
}
valueChangedCustom
(
value
:
string
):
void
{
this
.
value
=
value
;
this
.
onChange
(
value
);
}
/**
* Provides typing in templates
*/
...
...
This diff is collapsed.
Click to expand it.
src/app/modules/ix-forms/components/ix-input/ix-input.component.html
View file @
b8f7350e
...
...
@@ -23,7 +23,7 @@
[value]=
"formatted"
(input)=
"input(ixInput)"
(focus)=
"focus(ixInput)"
(blur)=
"blur()"
(blur)=
"blur
red
()"
[autocomplete]=
"autocomplete"
[placeholder]=
"placeholder"
>
...
...
This diff is collapsed.
Click to expand it.
src/app/modules/ix-forms/components/ix-input/ix-input.component.ts
View file @
b8f7350e
import
{
ChangeDetectionStrategy
,
ChangeDetectorRef
,
Component
,
In
put
,
ChangeDetectionStrategy
,
ChangeDetectorRef
,
Component
,
EventEmitter
,
Input
,
Out
put
,
}
from
'
@angular/core
'
;
import
{
ControlValueAccessor
,
FormControl
,
NgControl
}
from
'
@angular/forms
'
;
import
{
UntilDestroy
}
from
'
@ngneat/until-destroy
'
;
...
...
@@ -22,6 +22,7 @@ export class IxInputComponent implements ControlValueAccessor {
@
Input
()
readonly
:
boolean
;
@
Input
()
type
:
string
;
@
Input
()
autocomplete
=
'
off
'
;
@
Output
()
inputBlur
:
EventEmitter
<
unknown
>
=
new
EventEmitter
();
/** If formatted value returned by parseAndFormatInput has non-numeric letters
* and input 'type' is a number, the input will stay empty on the form */
...
...
@@ -118,7 +119,7 @@ export class IxInputComponent implements ControlValueAccessor {
}
}
blur
():
void
{
blur
red
():
void
{
this
.
onTouch
();
if
(
this
.
formatted
)
{
if
(
this
.
parse
)
{
...
...
@@ -131,6 +132,7 @@ export class IxInputComponent implements ControlValueAccessor {
this
.
onChange
(
this
.
value
);
this
.
cdr
.
markForCheck
();
this
.
inputBlur
.
emit
();
}
onPasswordToggled
():
void
{
...
...
This diff is collapsed.
Click to expand it.
src/app/pages/sharing/components/shares-dashboard/shares-dashboard.component.html
View file @
b8f7350e
<div
class=
"container"
[ngClass]=
"getContainerClass()"
>
<app-expandable-table
[ngClass]=
"getWebdavOrder()"
[expandableTableState]=
"webdavExpandableState"
[disabled]=
"true"
[conf]=
"webdavTableConf"
>
<app-expandable-table
#webdavTable
[ngClass]=
"getWebdavOrder()"
[expandableTableState]=
"webdavExpandableState"
[disabled]=
"true"
[conf]=
"webdavTableConf"
>
<ng-container
headerCustomContent
*ngTemplateOutlet=
"webdavServiceStatus === ServiceStatus.Loading ? statusLoading : statusButton; context: { status: webdavServiceStatus, count: webdavHasItems }"
...
...
@@ -9,7 +9,7 @@
*ngTemplateOutlet=
"extraAction; context:{ tableExtraActions: webdavTableConf?.tableExtraActions}"
></ng-container>
</app-expandable-table>
<app-expandable-table
[ngClass]=
"getNfsOrder()"
[expandableTableState]=
"nfsExpandableState"
[disabled]=
"true"
[conf]=
"nfsTableConf"
>
<app-expandable-table
#nfsTable
[ngClass]=
"getNfsOrder()"
[expandableTableState]=
"nfsExpandableState"
[disabled]=
"true"
[conf]=
"nfsTableConf"
>
<ng-container
headerCustomContent
*ngTemplateOutlet=
"nfsServiceStatus === ServiceStatus.Loading ? statusLoading : statusButton; context: { status: nfsServiceStatus, count: nfsHasItems }"
...
...
@@ -19,7 +19,7 @@
*ngTemplateOutlet=
"extraAction; context:{ tableExtraActions: nfsTableConf?.tableExtraActions}"
></ng-container>
</app-expandable-table>
<app-expandable-table
[ngClass]=
"getSmbOrder()"
[expandableTableState]=
"smbExpandableState"
[disabled]=
"true"
[conf]=
"smbTableConf"
>
<app-expandable-table
#smbTable
[ngClass]=
"getSmbOrder()"
[expandableTableState]=
"smbExpandableState"
[disabled]=
"true"
[conf]=
"smbTableConf"
>
<ng-container
headerCustomContent
*ngTemplateOutlet=
"smbServiceStatus === ServiceStatus.Loading ? statusLoading : statusButton; context: { status: smbServiceStatus, count: smbHasItems }"
...
...
@@ -29,7 +29,7 @@
*ngTemplateOutlet=
"extraAction; context:{ tableExtraActions: smbTableConf?.tableExtraActions}"
></ng-container>
</app-expandable-table>
<app-expandable-table
[ngClass]=
"getIscsiOrder()"
[expandableTableState]=
"iscsiExpandableState"
[disabled]=
"true"
[conf]=
"iscsiTableConf"
>
<app-expandable-table
#iscsiTable
[ngClass]=
"getIscsiOrder()"
[expandableTableState]=
"iscsiExpandableState"
[disabled]=
"true"
[conf]=
"iscsiTableConf"
>
<ng-container
headerCustomContent
*ngTemplateOutlet=
"iscsiServiceStatus === ServiceStatus.Loading ? statusLoading : statusButton; context: { status: iscsiServiceStatus, count: iscsiHasItems }"
...
...
This diff is collapsed.
Click to expand it.
src/app/pages/sharing/components/shares-dashboard/shares-dashboard.component.ts
View file @
b8f7350e
import
{
AfterViewInit
,
Component
,
Type
}
from
'
@angular/core
'
;
import
{
Validators
}
from
'
@angular/forms
'
;
import
{
AfterViewInit
,
Component
,
ViewChild
,
}
from
'
@angular/core
'
;
import
{
Router
}
from
'
@angular/router
'
;
import
{
UntilDestroy
,
untilDestroyed
}
from
'
@ngneat/until-destroy
'
;
import
{
TranslateService
}
from
'
@ngx-translate/core
'
;
...
...
@@ -15,14 +16,12 @@ import { Service } from 'app/interfaces/service.interface';
import
{
SmbShare
}
from
'
app/interfaces/smb-share.interface
'
;
import
{
WebDavShare
}
from
'
app/interfaces/web-dav-share.interface
'
;
import
{
WebsocketError
}
from
'
app/interfaces/websocket-error.interface
'
;
import
{
DialogFormConfiguration
}
from
'
app/modules/entity/entity-dialog/dialog-form-configuration.interface
'
;
import
{
EntityDialogComponent
}
from
'
app/modules/entity/entity-dialog/entity-dialog.component
'
;
import
{
ExpandableTableComponent
,
ExpandableTableState
,
InputExpandableTableConf
,
}
from
'
app/modules/entity/table/expandable-table/expandable-table.component
'
;
import
{
TableComponent
,
AppTableHeaderAction
,
}
from
'
app/modules/entity/table/table.component
'
;
import
{
EntityUtils
}
from
'
app/modules/entity/utils
'
;
...
...
@@ -36,7 +35,7 @@ import {
ModalService
,
WebSocketService
,
}
from
'
app/services
'
;
import
{
IxSlideInService
}
from
'
app/services/ix-slide-in.service
'
;
import
{
IxSlideInService
,
ResponseOnClose
}
from
'
app/services/ix-slide-in.service
'
;
enum
ShareType
{
Smb
=
'
smb
'
,
...
...
@@ -60,6 +59,11 @@ export class SharesDashboardComponent implements AfterViewInit {
smbTableConf
:
InputExpandableTableConf
=
this
.
getTableConfigForShareType
(
ShareType
.
Smb
);
iscsiTableConf
:
InputExpandableTableConf
=
this
.
getTableConfigForShareType
(
ShareType
.
Iscsi
);
@
ViewChild
(
'
webdavTable
'
,
{
static
:
false
})
webdavTable
:
ExpandableTableComponent
;
@
ViewChild
(
'
nfsTable
'
,
{
static
:
false
})
nfsTable
:
ExpandableTableComponent
;
@
ViewChild
(
'
smbTable
'
,
{
static
:
false
})
smbTable
:
ExpandableTableComponent
;
@
ViewChild
(
'
iscsiTable
'
,
{
static
:
false
})
iscsiTable
:
ExpandableTableComponent
;
webdavHasItems
=
0
;
nfsHasItems
=
0
;
smbHasItems
=
0
;
...
...
@@ -129,6 +133,41 @@ export class SharesDashboardComponent implements AfterViewInit {
if
(
this
.
iscsiHasItems
)
{
this
.
iscsiExpandableState
=
ExpandableTableState
.
Expanded
;
}
this
.
setupTableRefreshOnPanelClose
();
}
setupTableRefreshOnPanelClose
():
void
{
this
.
slideInService
.
onClose$
.
pipe
(
untilDestroyed
(
this
)).
subscribe
(({
modalType
}:
ResponseOnClose
)
=>
{
switch
(
modalType
)
{
case
WebdavFormComponent
:
if
(
!
this
.
webdavTable
.
tableComponent
)
{
this
.
refreshDashboard
();
}
this
.
webdavTable
.
tableComponent
.
getData
();
break
;
case
SmbFormComponent
:
if
(
!
this
.
smbTable
.
tableComponent
)
{
this
.
refreshDashboard
();
}
this
.
smbTable
.
tableComponent
.
getData
();
break
;
case
NfsFormComponent
:
if
(
!
this
.
nfsTable
.
tableComponent
)
{
this
.
refreshDashboard
();
}
this
.
nfsTable
.
tableComponent
.
getData
();
break
;
case
TargetFormComponent
:
if
(
!
this
.
iscsiTable
.
tableComponent
)
{
this
.
refreshDashboard
();
}
this
.
iscsiTable
.
tableComponent
.
getData
();
break
;
default
:
this
.
refreshDashboard
();
break
;
}
});
}
refreshDashboard
():
void
{
...
...
@@ -167,10 +206,11 @@ export class SharesDashboardComponent implements AfterViewInit {
],
detailsHref
:
'
/sharing/nfs
'
,
add
()
{
this
.
parent
.
add
(
this
.
tableComponent
,
ShareType
.
Nfs
);
this
.
parent
.
slideInService
.
open
(
NfsFormComponent
);
},
edit
(
row
:
NfsShare
)
{
this
.
parent
.
edit
(
this
.
tableComponent
,
ShareType
.
Nfs
,
row
.
id
);
const
form
=
this
.
parent
.
slideInService
.
open
(
NfsFormComponent
);
(
form
as
NfsFormComponent
).
setNfsShareForEdit
(
row
);
},
afterGetData
:
(
data
:
NfsShare
[])
=>
{
this
.
nfsHasItems
=
0
;
...
...
@@ -209,10 +249,11 @@ export class SharesDashboardComponent implements AfterViewInit {
},
],
add
()
{
this
.
parent
.
add
(
this
.
tableComponent
,
ShareType
.
Iscsi
);
this
.
parent
.
slideInService
.
open
(
TargetFormComponent
,
{
wide
:
true
}
);
},
edit
(
row
:
IscsiTarget
)
{
this
.
parent
.
edit
(
this
.
tableComponent
,
ShareType
.
Iscsi
,
row
.
id
);
const
targetForm
=
this
.
parent
.
slideInService
.
open
(
TargetFormComponent
,
{
wide
:
true
});
targetForm
.
setTargetForEdit
(
row
);
},
afterGetData
:
(
data
:
IscsiTarget
[])
=>
{
this
.
iscsiHasItems
=
0
;
...
...
@@ -268,11 +309,12 @@ export class SharesDashboardComponent implements AfterViewInit {
},
],
add
()
{
this
.
parent
.
add
(
this
.
tableComponent
,
ShareType
.
Web
D
av
);
this
.
parent
.
slideInService
.
open
(
Web
d
av
FormComponent
);
},
limitRowsByMaxHeight
:
true
,
edit
(
row
:
WebDavShare
)
{
this
.
parent
.
edit
(
this
.
tableComponent
,
ShareType
.
WebDav
,
row
.
id
);
const
form
=
this
.
parent
.
slideInService
.
open
(
WebdavFormComponent
);
(
form
as
WebdavFormComponent
).
setWebdavForEdit
(
row
);
},
afterGetData
:
(
data
:
WebDavShare
[])
=>
{
this
.
webdavHasItems
=
0
;
...
...
@@ -314,10 +356,11 @@ export class SharesDashboardComponent implements AfterViewInit {
],
limitRowsByMaxHeight
:
true
,
add
()
{
this
.
parent
.
add
(
this
.
tableComponent
,
ShareType
.
Smb
);
this
.
parent
.
slideInService
.
open
(
SmbFormComponent
);
},
edit
(
row
:
SmbShare
)
{
this
.
parent
.
edit
(
this
.
tableComponent
,
ShareType
.
Smb
,
row
.
id
);
const
form
=
this
.
parent
.
slideInService
.
open
(
SmbFormComponent
);
(
form
as
SmbFormComponent
).
setSmbShareForEdit
(
row
);
},
afterGetData
:
(
data
:
SmbShare
[])
=>
{
this
.
smbHasItems
=
0
;
...
...
@@ -333,71 +376,6 @@ export class SharesDashboardComponent implements AfterViewInit {
}
}
add
(
tableComponent
:
TableComponent
,
share
:
ShareType
,
id
?:
number
):
void
{
let
formComponent
:
Type
<
NfsFormComponent
|
SmbFormComponent
|
WebdavFormComponent
|
TargetFormComponent
>
;
switch
(
share
)
{
case
ShareType
.
Nfs
:
formComponent
=
NfsFormComponent
;
break
;
case
ShareType
.
Smb
:
formComponent
=
SmbFormComponent
;
break
;
case
ShareType
.
WebDav
:
formComponent
=
WebdavFormComponent
;
break
;
case
ShareType
.
Iscsi
:
formComponent
=
TargetFormComponent
;
break
;
}
if
([
ShareType
.
WebDav
,
ShareType
.
Nfs
].
includes
(
share
))
{
const
form
=
this
.
slideInService
.
open
(
formComponent
);
if
(
id
)
{
const
row
=
tableComponent
.
displayedDataSource
.
find
((
row
)
=>
row
.
id
===
id
);
if
(
share
===
ShareType
.
WebDav
)
{
(
form
as
WebdavFormComponent
).
setWebdavForEdit
(
row
);
}
else
if
(
share
===
ShareType
.
Nfs
)
{
(
form
as
NfsFormComponent
).
setNfsShareForEdit
(
row
);
}
}
this
.
slideInService
.
onClose$
.
pipe
(
untilDestroyed
(
this
)).
subscribe
(()
=>
{
if
(
!
tableComponent
)
{
this
.
refreshDashboard
();
}
else
{
tableComponent
.
getData
();
}
});
}
else
if
(
share
===
ShareType
.
Iscsi
)
{
const
targetForm
=
this
.
slideInService
.
open
(
TargetFormComponent
,
{
wide
:
true
});
if
(
id
)
{
targetForm
.
setTargetForEdit
(
tableComponent
.
displayedDataSource
.
find
((
row
)
=>
row
.
id
===
id
));
}
this
.
slideInService
.
onClose$
.
pipe
(
untilDestroyed
(
this
)).
subscribe
(()
=>
{
if
(
!
tableComponent
)
{
this
.
refreshDashboard
();
}
else
{
tableComponent
.
getData
();
}
},
(
err
)
=>
{
new
EntityUtils
().
handleWsError
(
this
,
err
,
this
.
dialog
);
});
}
else
{
this
.
modalService
.
openInSlideIn
(
formComponent
,
id
);
this
.
modalService
.
onClose$
.
pipe
(
untilDestroyed
(
this
)).
subscribe
(()
=>
{
if
(
!
tableComponent
)
{
this
.
refreshDashboard
();
}
else
{
tableComponent
.
getData
();
}
},
(
err
)
=>
{
new
EntityUtils
().
handleWsError
(
this
,
err
,
this
.
dialog
);
});
}
}
edit
(
tableComponent
:
TableComponent
,
share
:
ShareType
,
id
:
number
):
void
{
this
.
add
(
tableComponent
,
share
,
id
);
}
getTablesOrder
():
string
[]
{
const
order
:
string
[]
=
[
ShareType
.
Smb
,
ShareType
.
Nfs
,
ShareType
.
Iscsi
,
ShareType
.
WebDav
];
// Note: The order of these IFs is important. One can't come before the other
...
...
@@ -470,31 +448,6 @@ export class SharesDashboardComponent implements AfterViewInit {
}
}
showAddDialog
():
void
{
const
conf
:
DialogFormConfiguration
=
{
title
:
this
.
translate
.
instant
(
'
Add New Share
'
),
message
:
this
.
translate
.
instant
(
'
Select the type of Share you want to add
'
),
saveButtonText
:
this
.
translate
.
instant
(
'
Create
'
),
fieldConfig
:
[{
type
:
'
radio
'
,
name
:
'
share_type
'
,
options
:
[
{
label
:
'
SMB
'
,
value
:
ShareType
.
Smb
},
{
label
:
'
NFS
'
,
value
:
ShareType
.
Nfs
},
{
label
:
'
iSCSI Target
'
,
value
:
ShareType
.
Iscsi
},
{
label
:
'
WebDAV
'
,
value
:
ShareType
.
WebDav
},
],
validation
:
[
Validators
.
required
],
},
],
customSubmit
:
(
dialog
:
EntityDialogComponent
)
=>
{
dialog
.
dialogRef
.
close
();
this
.
add
(
null
,
dialog
.
formValue
.
share_type
);
},
};
this
.
dialog
.
dialogForm
(
conf
);
}
onSlideToggle
(
card
:
ShareType
,
row
:
ShareTableRow
,
param
:
'
enabled
'
|
'
ro
'
):
void
{
let
updateCall
:
keyof
ApiDirectory
;
switch
(
card
)
{
...
...
This diff is collapsed.
Click to expand it.
src/app/pages/sharing/iscsi/target/target-form/target-form.component.ts
View file @
b8f7350e
...
...
@@ -141,6 +141,7 @@ export class TargetFormComponent {
};
this
.
isLoading
=
true
;
this
.
cdr
.
markForCheck
();
let
request
$
:
Observable
<
unknown
>
;
if
(
this
.
isNew
)
{
request$
=
this
.
ws
.
call
(
'
iscsi.target.create
'
,
[
params
]);
...
...
This diff is collapsed.
Click to expand it.
src/app/pages/sharing/nfs/nfs-form/nfs-form.component.ts
View file @
b8f7350e
...
...
@@ -124,6 +124,7 @@ export class NfsFormComponent implements OnInit {
onSubmit
():
void
{
this
.
isLoading
=
true
;
this
.
cdr
.
markForCheck
();
const
nfsShare
=
this
.
form
.
value
;
let
request
$
:
Observable
<
unknown
>
;
if
(
this
.
isNew
)
{
...
...
@@ -140,6 +141,7 @@ export class NfsFormComponent implements OnInit {
.
subscribe
(
()
=>
{
this
.
isLoading
=
false
;
this
.
cdr
.
markForCheck
();
this
.
slideInService
.
close
();
},
(
error
)
=>
{
...
...
This diff is collapsed.
Click to expand it.
src/app/pages/sharing/sharing.module.ts
View file @
b8f7350e
...
...
@@ -4,6 +4,7 @@ import { FlexLayoutModule } from '@angular/flex-layout';
import
{
FormsModule
,
ReactiveFormsModule
}
from
'
@angular/forms
'
;
import
{
MatButtonModule
}
from
'
@angular/material/button
'
;
import
{
MatCardModule
}
from
'
@angular/material/card
'
;
import
{
MatDialogModule
}
from
'
@angular/material/dialog
'
;
import
{
MatFormFieldModule
}
from
'
@angular/material/form-field
'
;
import
{
MatIconModule
}
from
'
@angular/material/icon
'
;
import
{
MatListModule
}
from
'
@angular/material/list
'
;
...
...
@@ -22,6 +23,7 @@ import { TooltipModule } from 'app/modules/tooltip/tooltip.module';
import
{
AuthorizedAccessFormComponent
}
from
'
app/pages/sharing/iscsi/authorized-access/authorized-access-form/authorized-access-form.component
'
;
import
{
AuthorizedAccessListComponent
}
from
'
app/pages/sharing/iscsi/authorized-access/authorized-access-list/authorized-access-list.component
'
;
import
{
TargetGlobalConfigurationComponent
}
from
'
app/pages/sharing/iscsi/target-global-configuration/target-global-configuration.component
'
;
import
{
RestartSmbDialogComponent
}
from
'
app/pages/sharing/smb/smb-form/restart-smb-dialog/restart-smb-dialog.component
'
;
import
{
UserService
}
from
'
app/services/user.service
'
;
import
{
SharesDashboardComponent
}
from
'
./components/shares-dashboard/shares-dashboard.component
'
;
import
{
AssociatedTargetFormComponent
}
from
'
./iscsi/associated-target/associated-target-form/associated-target-form.component
'
;
...
...
@@ -62,6 +64,7 @@ import { WebdavListComponent } from './webdav/webdav-list/webdav-list.component'
MatIconModule
,
FlexLayoutModule
,
MatListModule
,
MatDialogModule
,
MatMenuModule
,
MatFormFieldModule
,
MatTooltipModule
,
...
...
@@ -80,6 +83,7 @@ import { WebdavListComponent } from './webdav/webdav-list/webdav-list.component'
WebdavFormComponent
,
SmbListComponent
,
SmbFormComponent
,
RestartSmbDialogComponent
,
SmbAclComponent
,
IscsiComponent
,
IscsiWizardComponent
,
...
...
This diff is collapsed.
Click to expand it.
src/app/pages/sharing/smb/smb-form/restart-smb-dialog/restart-smb-dialog.component.html
0 → 100644
View file @
b8f7350e
<mat-dialog-content>
<h3>
{{ 'Restart SMB Service' | translate }}
</h3>
<div>
<p>
{{ helptext.restartPt1 }}
</p>
<ul>
<li
*ngIf=
"data.homeshare"
>
{{ homeShareMessage }}
</li>
<li
*ngIf=
"data.timemachine"
>
{{ timemachineMessage }}
</li>
<li
*ngIf=
"data.hosts"
>
{{ hostsMessage }}
</li>
<li
*ngIf=
"data.path"
>
{{ pathMessage }}
</li>
</ul>
<p><strong>
{{ helptext.restartPt2 }}
</strong></p>
</div>
</mat-dialog-content>
<mat-dialog-actions
align=
"end"
>
<button
mat-button
[mat-dialog-close]=
"false"
>
{{ 'No' | translate }}
</button>
<button
mat-button
[mat-dialog-close]=
"true"
cdkFocusInitial
color=
"primary"
>
{{ 'Restart Service' | translate }}
</button>
</mat-dialog-actions>
\ No newline at end of file
This diff is collapsed.
Click to expand it.
src/app/pages/sharing/smb/smb-form/restart-smb-dialog/restart-smb-dialog.component.ts
0 → 100644
View file @
b8f7350e
import
{
Component
,
Inject
}
from
'
@angular/core
'
;
import
{
MAT_DIALOG_DATA
}
from
'
@angular/material/dialog
'
;
import
{
TranslateService
}
from
'
@ngx-translate/core
'
;
import
{
helptextSharingSmb
}
from
'
app/helptext/sharing
'
;
interface
RestartDialogData
{
homeshare
:
boolean
;
timemachine
:
boolean
;
hosts
:
boolean
;
path
:
boolean
;
isNew
:
boolean
;
}
@
Component
({
templateUrl
:
'
./restart-smb-dialog.component.html
'
,
})
export
class
RestartSmbDialogComponent
{
readonly
helptext
=
helptextSharingSmb
;
constructor
(
private
translate
:
TranslateService
,
@
Inject
(
MAT_DIALOG_DATA
)
public
data
:
RestartDialogData
,
)
{}
get
homeShareMessage
():
string
{
return
this
.
data
.
isNew
?
this
.
translate
.
instant
(
'
Enabled
\'
Use as Home Share
\'
'
)
:
this
.
translate
.
instant
(
'
Updated
\'
Use as Home Share
\'
'
);
}
get
timemachineMessage
():
string
{
return
this
.
data
.
isNew
?
this
.
translate
.
instant
(
'
Enabled
\'
Time Machine
\'
'
)
:
this
.
translate
.
instant
(
'
Update
\'
Time Machine
\'
'
);
}
get
pathMessage
():
string
{
return
this
.
translate
.
instant
(
'
Share Path updated
'
);
}
get
hostsMessage
():
string
{
return
this
.
data
.
isNew
?
this
.
translate
.
instant
(
'
\'
Hosts Allow
\'
or
\'
Hosts Deny
\'
has been set
'
)
:
this
.
translate
.
instant
(
'
\'
Hosts Allow
\'
or
\'
Hosts Deny
\'
has been updated
'
);
}
}
This diff is collapsed.
Click to expand it.
src/app/pages/sharing/smb/smb-form/smb-form.component.html
0 → 100644
View file @
b8f7350e
<ix-modal-header
[title]=
"title"
[loading]=
"isLoading"
></ix-modal-header>
<mat-card>
<mat-card-content>
<form
[formGroup]=
"form"
class=
"ix-form-container"
(submit)=
"submit()"
>
<ix-fieldset
[title]=
"'Basic' | translate"
>
<ix-explorer
formControlName=
"path"
[required]=
"true"
[tooltip]=
"helptextSharingSmb.tooltip_path | translate"
[label]=
"helptextSharingSmb.placeholder_path | translate"
[nodeProvider]=
"treeNodeProvider"
></ix-explorer>
<ix-input
formControlName=
"name"
[label]=
"helptextSharingSmb.placeholder_name | translate"
[tooltip]=
"helptextSharingSmb.tooltip_name | translate"
[required]=
"true"
(inputBlur)=
"setNameFromPath()"
></ix-input>
<ix-select
formControlName=
"purpose"
[label]=
"helptextSharingSmb.placeholder_purpose | translate"
[tooltip]=
"helptextSharingSmb.tooltip_purpose | translate"
emptyValue=
""
[required]=
"true"
[options]=
"purposeOptions$"
></ix-select>
<ix-input
formControlName=
"comment"
[label]=
"helptextSharingSmb.placeholder_comment | translate"
[tooltip]=
"helptextSharingSmb.tooltip_comment | translate"
></ix-input>
<ix-checkbox
formControlName=
"enabled"
[label]=
"helptextSharingSmb.placeholder_enabled | translate"
[tooltip]=
"helptextSharingSmb.tooltip_enabled | translate"
></ix-checkbox>
</ix-fieldset>
<ix-fieldset
*ngIf=
"isAdvancedMode"
[title]=
"'Access' | translate"
>
<ix-checkbox
formControlName=
"acl"
[label]=
"helptextSharingSmb.placeholder_acl | translate"
[tooltip]=
"helptextSharingSmb.tooltip_acl | translate"
></ix-checkbox>
<ix-checkbox
formControlName=
"ro"
[label]=
"helptextSharingSmb.placeholder_ro | translate"
[tooltip]=
"helptextSharingSmb.tooltip_ro | translate"
></ix-checkbox>
<ix-checkbox
formControlName=
"browsable"
[label]=
"helptextSharingSmb.placeholder_browsable | translate"
[tooltip]=
"helptextSharingSmb.tooltip_browsable | translate"
></ix-checkbox>
<ix-checkbox
formControlName=
"guestok"
[label]=
"helptextSharingSmb.placeholder_guestok | translate"
[tooltip]=
"helptextSharingSmb.tooltip_guestok | translate"
></ix-checkbox>
<ix-checkbox
formControlName=
"abe"
[label]=
"helptextSharingSmb.placeholder_abe | translate"
[tooltip]=
"helptextSharingSmb.tooltip_abe | translate"
></ix-checkbox>
<ix-chips
formControlName=
"hostsallow"
[label]=
"helptextSharingSmb.placeholder_hostsallow | translate"
[tooltip]=
"helptextSharingSmb.tooltip_hostsallow | translate"
></ix-chips>
<ix-chips
formControlName=
"hostsdeny"
[label]=
"helptextSharingSmb.placeholder_hostsdeny | translate"
[tooltip]=
"helptextSharingSmb.tooltip_hostsdeny | translate"
></ix-chips>
</ix-fieldset>
<ix-fieldset
*ngIf=
"isAdvancedMode"
[title]=
"'Other Options' | translate"
>
<ix-checkbox
formControlName=
"home"
[label]=
"helptextSharingSmb.placeholder_home | translate"
[tooltip]=
"helptextSharingSmb.tooltip_home | translate"
></ix-checkbox>
<ix-checkbox
formControlName=
"timemachine"
[label]=
"helptextSharingSmb.placeholder_timemachine | translate"
[tooltip]=
"helptextSharingSmb.tooltip_timemachine | translate"
></ix-checkbox>
<ix-checkbox
formControlName=
"afp"
[label]=
"helptextSharingSmb.placeholder_afp | translate"
[tooltip]=
"helptextSharingSmb.tooltip_afp | translate"
></ix-checkbox>
<ix-checkbox
formControlName=
"shadowcopy"
[label]=
"helptextSharingSmb.placeholder_shadowcopy | translate"
[tooltip]=
"helptextSharingSmb.tooltip_shadowcopy | translate"
></ix-checkbox>
<ix-checkbox
formControlName=
"recyclebin"
[label]=
"helptextSharingSmb.placeholder_recyclebin | translate"
[tooltip]=
"helptextSharingSmb.tooltip_recyclebin | translate"
></ix-checkbox>
<ix-checkbox
formControlName=
"aapl_name_mangling"
[label]=
"helptextSharingSmb.placeholder_aapl_name_mangling | translate"
[tooltip]=
"helptextSharingSmb.tooltip_aapl_name_mangling | translate"
></ix-checkbox>
<ix-checkbox
formControlName=
"streams"
[label]=
"helptextSharingSmb.placeholder_streams | translate"
[tooltip]=
"helptextSharingSmb.tooltip_streams | translate"
></ix-checkbox>
<ix-checkbox
formControlName=
"durablehandle"
[label]=
"helptextSharingSmb.placeholder_durablehandle | translate"
[tooltip]=
"helptextSharingSmb.tooltip_durablehandle | translate"
></ix-checkbox>
<ix-checkbox
formControlName=
"fsrvp"
[label]=
"helptextSharingSmb.placeholder_fsrvp | translate"
[tooltip]=
"helptextSharingSmb.tooltip_fsrvp | translate"
></ix-checkbox>
<ix-input
formControlName=
"path_suffix"
[label]=
"helptextSharingSmb.placeholder_path_suffix | translate"
[tooltip]=
"helptextSharingSmb.tooltip_path_suffix | translate"
></ix-input>
<ix-textarea
formControlName=
"auxsmbconf"
[label]=
"helptextSharingSmb.placeholder_auxsmbconf | translate"
[tooltip]=
"helptextSharingSmb.tooltip_auxsmbconf | translate"
></ix-textarea>
</ix-fieldset>
<div
class=
"form-actions"
>
<button
mat-button
type=
"submit"
[disabled]=
"form.invalid || isLoading"
color=
"primary"
>
{{ 'Save' | translate }}
</button>
<button
mat-button
type=
"button"
(click)=
"this.isAdvancedMode = !this.isAdvancedMode"
>
{{ isAdvancedMode ? ('Basic Options' | translate) : ('Advanced Options' | translate) }}
</button>
</div>
</form>
</mat-card-content>
</mat-card>
\ No newline at end of file
This diff is collapsed.
Click to expand it.
src/app/pages/sharing/smb/smb-form/smb-form.component.scss
0 → 100644
View file @
b8f7350e
.form-actions
{
margin
:
8px
10px
;
button
{
margin-right
:
5px
;
}
}
This diff is collapsed.
Click to expand it.
src/app/pages/sharing/smb/smb-form/smb-form.component.spec.ts
0 → 100644
View file @
b8f7350e
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
{
MatDialog
}
from
'
@angular/material/dialog
'
;
import
{
Router
}
from
'
@angular/router
'
;
import
{
createComponentFactory
,
mockProvider
,
Spectator
}
from
'
@ngneat/spectator/jest
'
;
import
{
of
}
from
'
rxjs
'
;
import
{
mockCall
,
mockWebsocket
}
from
'
app/core/testing/utils/mock-websocket.utils
'
;
import
{
ServiceName
}
from
'
app/enums/service-name.enum
'
;
import
{
ServiceStatus
}
from
'
app/enums/service-status.enum
'
;
import
{
helptextSharingSmb
}
from
'
app/helptext/sharing
'
;
import
{
FileSystemStat
}
from
'
app/interfaces/filesystem-stat.interface
'
;
import
{
Service
}
from
'
app/interfaces/service.interface
'
;
import
{
SmbPresets
,
SmbPresetType
,
SmbShare
}
from
'
app/interfaces/smb-share.interface
'
;
import
{
IxCheckboxHarness
}
from
'
app/modules/ix-forms/components/ix-checkbox/ix-checkbox.harness
'
;
import
{
IxExplorerHarness
}
from
'
app/modules/ix-forms/components/ix-explorer/ix-explorer.harness
'
;
import
{
IxInputHarness
}
from
'
app/modules/ix-forms/components/ix-input/ix-input.harness
'
;
import
{
IxSelectHarness
}
from
'
app/modules/ix-forms/components/ix-select/ix-select.harness
'
;
import
{
IxFormsModule
}
from
'
app/modules/ix-forms/ix-forms.module
'
;
import
{
IxFormHarness
}
from
'
app/modules/ix-forms/testing/ix-form.harness
'
;
import
{
RestartSmbDialogComponent
}
from
'
app/pages/sharing/smb/smb-form/restart-smb-dialog/restart-smb-dialog.component
'
;
import
{
AppLoaderService
,
DialogService
,
WebSocketService
}
from
'
app/services
'
;
import
{
FilesystemService
}
from
'
app/services/filesystem.service
'
;
import
{
IxSlideInService
}
from
'
app/services/ix-slide-in.service
'
;
import
{
SmbFormComponent
}
from
'
./smb-form.component
'
;
describe
(
'
SmbFormComponent
'
,
()
=>
{
const
existingShare
:
SmbShare
=
{
id
:
1
,
purpose
:
SmbPresetType
.
MultiUserTimeMachine
,
path
:
'
/mnt/pool123/ds222
'
,
path_suffix
:
'
%U
'
,
home
:
false
,
name
:
'
ds222
'
,
comment
:
''
,
ro
:
false
,
browsable
:
true
,
recyclebin
:
true
,
guestok
:
true
,
hostsallow
:
[
'
host1
'
],
hostsdeny
:
[
'
host2
'
],
auxsmbconf
:
''
,
aapl_name_mangling
:
false
,
abe
:
true
,
acl
:
true
,
durablehandle
:
true
,
streams
:
true
,
timemachine
:
true
,
vuid
:
'
a7bcb6cb-b2f3-4144-a5bb-e79dc7e282c4
'
,
shadowcopy
:
true
,
fsrvp
:
false
,
enabled
:
true
,
cluster_volname
:
''
,
locked
:
false
,
};
const
formLabels
:
{
[
key
:
string
]:
string
}
=
{
path
:
'
Path
'
,
name
:
'
Name
'
,
purpose
:
'
Purpose
'
,
comment
:
'
Description
'
,
enabled
:
'
Enabled
'
,
acl
:
'
Enable ACL
'
,
ro
:
'
Export Read Only
'
,
browsable
:
'
Browsable to Network Clients
'
,
guestok
:
'
Allow Guest Access
'
,
abe
:
'
Access Based Share Enumeration
'
,
hostsallow
:
'
Hosts Allow
'
,
hostsdeny
:
'
Hosts Deny
'
,
home
:
'
Use as Home Share
'
,
timemachine
:
'
Time Machine
'
,
afp
:
'
Legacy AFP Compatibility
'
,
shadowcopy
:
'
Enable Shadow Copies
'
,
recyclebin
:
'
Export Recycle Bin
'
,
aapl_name_mangling
:
'
Use Apple-style Character Encoding
'
,
streams
:
'
Enable Alternate Data Streams
'
,
durablehandle
:
'
Enable SMB2/3 Durable Handles
'
,
fsrvp
:
'
Enable FSRVP
'
,
path_suffix
:
'
Path Suffix
'
,
auxsmbconf
:
'
Auxiliary Parameters
'
,
};
const
presets
:
SmbPresets
=
{
NO_PRESET
:
{
verbose_name
:
'
No presets
'
,
params
:
{
auxsmbconf
:
''
,
},
},
ENHANCED_TIMEMACHINE
:
{
verbose_name
:
'
Multi-user time machine
'
,
params
:
{
path_suffix
:
'
%U
'
,
timemachine
:
true
,
auxsmbconf
:
'
zfs_core:zfs_auto_create=true
\n
zfs_core:base_user_quota=1T
'
,
},
},
PRIVATE_DATASETS
:
{
verbose_name
:
'
Private SMB Datasets and Shares
'
,
params
:
{
path_suffix
:
'
%U
'
,
auxsmbconf
:
'
zfs_core:zfs_auto_create=true
'
,
},
},
};
let
spectator
:
Spectator
<
SmbFormComponent
>
;
let
loader
:
HarnessLoader
;
let
form
:
IxFormHarness
;
let
websocket
:
WebSocketService
;
const
createComponent
=
createComponentFactory
({
component
:
SmbFormComponent
,
imports
:
[
ReactiveFormsModule
,
IxFormsModule
,
],
providers
:
[
mockWebsocket
([
mockCall
(
'
sharing.smb.create
'
),
mockCall
(
'
sharing.smb.update
'
),
mockCall
(
'
sharing.smb.query
'
,
[
{
...
existingShare
},
]),
mockCall
(
'
service.query
'
,
[{
service
:
ServiceName
.
Cifs
,
id
:
4
,
enable
:
false
,
state
:
ServiceStatus
.
Running
,
}
as
Service
]),
mockCall
(
'
filesystem.stat
'
,
{
acl
:
false
,
}
as
FileSystemStat
),
mockCall
(
'
service.update
'
),
mockCall
(
'
service.start
'
),
mockCall
(
'
service.restart
'
),
mockCall
(
'
sharing.smb.presets
'
,
{
...
presets
}),
mockCall
(
'
filesystem.acl_is_trivial
'
,
false
),
mockCall
(
'
pool.dataset.path_in_locked_datasets
'
,
false
),
]),
mockProvider
(
IxSlideInService
),
mockProvider
(
Router
),
mockProvider
(
AppLoaderService
),
mockProvider
(
FilesystemService
),
mockProvider
(
MatDialog
,
{
open
:
jest
.
fn
(()
=>
({
afterClosed
:
()
=>
of
(
true
),
})),
}),
mockProvider
(
DialogService
,
{
confirm
:
jest
.
fn
(()
=>
of
(
true
)),
info
:
jest
.
fn
(()
=>
of
(
true
)),
}),
],
});
beforeEach
(
async
()
=>
{
spectator
=
createComponent
();
loader
=
TestbedHarnessEnvironment
.
loader
(
spectator
.
fixture
);
form
=
await
loader
.
getHarness
(
IxFormHarness
);
websocket
=
spectator
.
inject
(
WebSocketService
);
});
it
(
'
shows all the fields when Advanced Options button is pressed
'
,
async
()
=>
{
const
advancedButton
=
await
loader
.
getHarness
(
MatButtonHarness
.
with
({
text
:
'
Advanced Options
'
}));
await
advancedButton
.
click
();
const
fields
=
Object
.
keys
(
await
form
.
getControlHarnessesDict
());
for
(
const
param
in
formLabels
)
{
expect
(
fields
).
toContain
(
formLabels
[
param
]);
}
});
it
(
'
sets the correct options array for purpose field
'
,
async
()
=>
{
const
purposeSelect
=
await
loader
.
getHarness
(
IxSelectHarness
.
with
({
label
:
'
Purpose
'
}));
const
optionLabels
=
await
purposeSelect
.
getOptionLabels
();
expect
(
optionLabels
).
toEqual
([
'
No presets
'
,
'
Multi-user time machine
'
,
'
Private SMB Datasets and Shares
'
,
]);
});
it
(
'
should have error for duplicate share name
'
,
async
()
=>
{
const
nameControl
=
await
loader
.
getHarness
(
IxInputHarness
.
with
({
label
:
'
Name
'
}));
await
nameControl
.
setValue
(
'
ds222
'
);
expect
(
await
nameControl
.
getErrorText
()).
toEqual
(
'
The name "ds222" is already in use.
'
);
});
it
(
'
when a preset is selected, the relevant fields should be impacted
'
,
async
()
=>
{
const
advancedButton
=
await
loader
.
getHarness
(
MatButtonHarness
.
with
({
text
:
'
Advanced Options
'
}));
await
advancedButton
.
click
();
const
purposeSelect
=
await
loader
.
getHarness
(
IxSelectHarness
.
with
({
label
:
formLabels
.
purpose
}));
const
labels
=
await
purposeSelect
.
getOptionLabels
();
const
presetKeys
=
Object
.
keys
(
presets
);
const
form
=
await
loader
.
getHarness
(
IxFormHarness
);
const
fields
=
await
form
.
getControlHarnessesDict
();
for
(
let
i
=
0
;
i
<
labels
.
length
;
i
++
)
{
await
purposeSelect
.
setValue
(
labels
[
i
]);
for
(
const
param
in
presets
[
presetKeys
[
i
]].
params
)
{
if
(
param
===
'
auxsmbconf
'
)
{
continue
;
}
const
expectedValue
=
presets
[
presetKeys
[
i
]].
params
[
param
as
keyof
SmbShare
];
const
value
=
await
fields
[
formLabels
[
param
]].
getValue
();
expect
(
value
).
toStrictEqual
(
expectedValue
);
expect
(
await
fields
[
formLabels
[
param
]].
isDisabled
()).
toBeTruthy
();
}
}
expect
(
true
).
toBeTruthy
();
});
it
(
'
should show confirmation warning when afp is checked
'
,
async
()
=>
{
const
advancedButton
=
await
loader
.
getHarness
(
MatButtonHarness
.
with
({
text
:
'
Advanced Options
'
}));
await
advancedButton
.
click
();
const
afpCheckbox
=
await
loader
.
getHarness
(
IxCheckboxHarness
.
with
({
label
:
formLabels
.
afp
}));
await
afpCheckbox
.
setValue
(
true
);
expect
(
spectator
.
inject
(
DialogService
).
confirm
).
toHaveBeenNthCalledWith
(
1
,
{
title
:
helptextSharingSmb
.
afpDialog_title
,
message
:
helptextSharingSmb
.
afpDialog_message
,
hideCheckBox
:
false
,
buttonMsg
:
helptextSharingSmb
.
afpDialog_button
,
hideCancel
:
false
,
});
});
it
(
'
shows values of existing share when editing
'
,
async
()
=>
{
spectator
.
component
.
setSmbShareForEdit
(
existingShare
);
const
advancedButton
=
await
loader
.
getHarness
(
MatButtonHarness
.
with
({
text
:
'
Advanced Options
'
}));
await
advancedButton
.
click
();
const
values
=
await
form
.
getValues
();
const
existingShareWithLabels
:
{
[
key
:
string
]:
any
}
=
{};
for
(
const
key
in
existingShare
)
{
if
(
!
formLabels
[
key
])
{
continue
;
}
existingShareWithLabels
[
formLabels
[
key
]]
=
existingShare
[
key
as
keyof
SmbShare
];
}
existingShareWithLabels
[
formLabels
.
purpose
]
=
presets
[
existingShareWithLabels
[
formLabels
.
purpose
]].
verbose_name
;
expect
(
values
).
toMatchObject
(
existingShareWithLabels
);
});
it
(
'
should show warning if aaple_name_mangling value changes when editing
'
,
async
()
=>
{
spectator
.
component
.
setSmbShareForEdit
(
existingShare
);
const
advancedButton
=
await
loader
.
getHarness
(
MatButtonHarness
.
with
({
text
:
'
Advanced Options
'
}));
await
advancedButton
.
click
();
const
aaplNameManglingCheckbox
=
await
loader
.
getHarness
(
IxCheckboxHarness
.
with
({
label
:
formLabels
.
aapl_name_mangling
}),
);
if
(
existingShare
.
aapl_name_mangling
)
{
await
aaplNameManglingCheckbox
.
setValue
(
false
);
}
else
{
await
aaplNameManglingCheckbox
.
setValue
(
true
);
}
expect
(
spectator
.
inject
(
DialogService
).
confirm
).
toHaveBeenNthCalledWith
(
2
,
{
title
:
helptextSharingSmb
.
manglingDialog
.
title
,
message
:
helptextSharingSmb
.
manglingDialog
.
message
,
hideCheckBox
:
true
,
buttonMsg
:
helptextSharingSmb
.
manglingDialog
.
action
,
hideCancel
:
true
,
});
});
it
(
'
should autofill name from path if name is empty
'
,
async
()
=>
{
const
advancedButton
=
await
loader
.
getHarness
(
MatButtonHarness
.
with
({
text
:
'
Advanced Options
'
}));
await
advancedButton
.
click
();
const
nameControl
=
await
loader
.
getHarness
(
IxInputHarness
.
with
({
label
:
formLabels
.
name
}));
await
nameControl
.
setValue
(
''
);
const
pathControl
=
await
loader
.
getHarness
(
IxExplorerHarness
.
with
({
label
:
formLabels
.
path
}));
await
pathControl
.
setValue
(
'
/mnt/pool2/ds22
'
);
expect
(
await
nameControl
.
getValue
()).
toEqual
(
'
ds22
'
);
expect
(
spectator
.
inject
(
DialogService
).
confirm
).
toHaveBeenNthCalledWith
(
3
,
{
title
:
helptextSharingSmb
.
stripACLDialog
.
title
,
message
:
helptextSharingSmb
.
stripACLDialog
.
message
,
hideCheckBox
:
true
,
buttonMsg
:
helptextSharingSmb
.
stripACLDialog
.
button
,
hideCancel
:
true
,
});
});
it
(
'
should show strip acl warning if acl is trivial when path changes
'
,
async
()
=>
{
const
advancedButton
=
await
loader
.
getHarness
(
MatButtonHarness
.
with
({
text
:
'
Advanced Options
'
}));
await
advancedButton
.
click
();
const
pathControl
=
await
loader
.
getHarness
(
IxExplorerHarness
.
with
({
label
:
formLabels
.
path
}));
await
pathControl
.
setValue
(
'
/mnt/pool2/ds22
'
);
const
purposeSelect
=
await
loader
.
getHarness
(
IxSelectHarness
.
with
({
label
:
'
Purpose
'
}));
await
purposeSelect
.
setValue
(
presets
.
NO_PRESET
.
verbose_name
);
const
aclCheckbox
=
await
loader
.
getHarness
(
IxCheckboxHarness
.
with
({
label
:
formLabels
.
acl
}));
await
(
await
aclCheckbox
.
getMatCheckboxHarness
()).
uncheck
();
expect
(
spectator
.
inject
(
DialogService
).
confirm
).
toHaveBeenNthCalledWith
(
4
,
{
title
:
helptextSharingSmb
.
stripACLDialog
.
title
,
message
:
helptextSharingSmb
.
stripACLDialog
.
message
,
hideCheckBox
:
true
,
buttonMsg
:
helptextSharingSmb
.
stripACLDialog
.
button
,
hideCancel
:
true
,
});
});
it
(
'
should show acl warning if acl is unchcekd and dataset is non-trivial
'
,
async
()
=>
{
const
advancedButton
=
await
loader
.
getHarness
(
MatButtonHarness
.
with
({
text
:
'
Advanced Options
'
}));
await
advancedButton
.
click
();
const
purposeSelect
=
await
loader
.
getHarness
(
IxSelectHarness
.
with
({
label
:
'
Purpose
'
}));
await
purposeSelect
.
setValue
(
presets
.
PRIVATE_DATASETS
.
verbose_name
);
const
pathControl
=
await
loader
.
getHarness
(
IxExplorerHarness
.
with
({
label
:
formLabels
.
path
}));
await
pathControl
.
setValue
(
'
/mnt/pool2/ds22
'
);
const
aclCheckbox
=
await
loader
.
getHarness
(
IxCheckboxHarness
.
with
({
label
:
formLabels
.
acl
}));
await
(
await
aclCheckbox
.
getMatCheckboxHarness
()).
uncheck
();
expect
(
spectator
.
inject
(
DialogService
).
confirm
).
toHaveBeenNthCalledWith
(
5
,
{
title
:
helptextSharingSmb
.
stripACLDialog
.
title
,
message
:
helptextSharingSmb
.
stripACLDialog
.
message
,
hideCheckBox
:
true
,
buttonMsg
:
helptextSharingSmb
.
stripACLDialog
.
button
,
hideCancel
:
true
,
});
});
it
(
'
should submit the form with the correct value
'
,
async
()
=>
{
const
advancedButton
=
await
loader
.
getHarness
(
MatButtonHarness
.
with
({
text
:
'
Advanced Options
'
}));
await
advancedButton
.
click
();
const
attrs
:
{
[
key
:
string
]:
unknown
}
=
{};
for
(
const
key
in
existingShare
)
{
if
(
formLabels
[
key
])
{
attrs
[
formLabels
[
key
]]
=
existingShare
[
key
as
keyof
SmbShare
];
}
}
attrs
[
formLabels
.
purpose
]
=
presets
[
attrs
[
formLabels
.
purpose
]
as
string
].
verbose_name
;
attrs
[
formLabels
.
name
]
=
'
ds223
'
;
attrs
[
formLabels
.
hostsallow
]
=
[
'
host11
'
];
attrs
[
formLabels
.
hostsdeny
]
=
[
'
host22
'
];
await
form
.
fillForm
({
...
attrs
,
});
expect
(
spectator
.
inject
(
DialogService
).
confirm
)
.
toHaveBeenNthCalledWith
(
6
,
{
title
:
helptextSharingSmb
.
stripACLDialog
.
title
,
message
:
helptextSharingSmb
.
stripACLDialog
.
message
,
hideCheckBox
:
true
,
buttonMsg
:
helptextSharingSmb
.
stripACLDialog
.
button
,
hideCancel
:
true
,
});
const
saveButton
=
await
loader
.
getHarness
(
MatButtonHarness
.
with
({
text
:
'
Save
'
}));
await
saveButton
.
click
();
expect
(
websocket
.
call
).
toHaveBeenCalledWith
(
'
sharing.smb.create
'
,
[{
path
:
'
/mnt/pool123/ds222
'
,
name
:
'
ds223
'
,
purpose
:
SmbPresetType
.
MultiUserTimeMachine
,
comment
:
''
,
enabled
:
true
,
acl
:
true
,
ro
:
false
,
browsable
:
true
,
guestok
:
true
,
abe
:
true
,
hostsallow
:
[
'
host11
'
],
hostsdeny
:
[
'
host22
'
],
home
:
false
,
afp
:
false
,
shadowcopy
:
true
,
recyclebin
:
true
,
aapl_name_mangling
:
false
,
streams
:
true
,
durablehandle
:
true
,
fsrvp
:
false
,
auxsmbconf
:
''
,
}]);
expect
(
websocket
.
call
).
toHaveBeenCalledWith
(
'
service.query
'
);
expect
(
spectator
.
inject
(
MatDialog
).
open
)
.
toHaveBeenCalledWith
(
RestartSmbDialogComponent
,
{
data
:
{
timemachine
:
true
,
homeshare
:
true
,
path
:
false
,
hosts
:
true
,
isNew
:
true
,
},
});
expect
(
websocket
.
call
).
toHaveBeenCalledWith
(
'
service.restart
'
,
[
ServiceName
.
Cifs
]);
expect
(
spectator
.
inject
(
DialogService
).
info
).
toHaveBeenCalledWith
(
helptextSharingSmb
.
restarted_smb_dialog
.
title
,
helptextSharingSmb
.
restarted_smb_dialog
.
message
,
);
const
sharePath
=
await
(
await
loader
.
getHarness
(
IxExplorerHarness
.
with
({
label
:
formLabels
.
path
}),
)).
getValue
();
expect
(
websocket
.
call
).
toHaveBeenCalledWith
(
'
filesystem.stat
'
,
[
sharePath
]);
const
homeShare
=
await
(
await
loader
.
getHarness
(
IxCheckboxHarness
.
with
({
label
:
formLabels
.
home
}),
)).
getValue
();
const
datasetId
=
sharePath
.
replace
(
'
/mnt/
'
,
''
);
const
poolName
=
datasetId
.
split
(
'
/
'
)[
0
];
expect
(
spectator
.
inject
(
Router
).
navigate
).
toHaveBeenCalledWith
([
'
/
'
].
concat
(
[
'
storage
'
,
'
id
'
,
poolName
,
'
dataset
'
,
'
acl
'
,
datasetId
],
),
{
queryParams
:
{
homeShare
}
});
});
});
This diff is collapsed.
Click to expand it.
src/app/pages/sharing/smb/smb-form/smb-form.component.ts
View file @
b8f7350e
This diff is collapsed.
Click to expand it.
Prev
1
2
3
4
5
6
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment
Menu
Projects
Groups
Snippets
Help