Skip to content
GitLab
Menu
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
c542ac6a
Unverified
Commit
c542ac6a
authored
2 years ago
by
Denys Butenko
Committed by
GitHub
2 years ago
Browse files
Options
Download
Email Patches
Plain Diff
NAS-117177 / 22.12 / Finish Space Management Card (#6880)
parent
efbdf8a0
Changes
110
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
src/app/core/classes/theme-utils/theme-utils.ts
+5
-0
src/app/core/classes/theme-utils/theme-utils.ts
src/app/interfaces/api-directory.interface.ts
+2
-1
src/app/interfaces/api-directory.interface.ts
src/app/interfaces/device-nested-data-node.interface.ts
+1
-0
src/app/interfaces/device-nested-data-node.interface.ts
src/app/interfaces/pool.interface.ts
+28
-0
src/app/interfaces/pool.interface.ts
src/app/pages/dashboard/components/widget-cpu/widget-cpu.component.ts
+2
-7
...s/dashboard/components/widget-cpu/widget-cpu.component.ts
src/app/pages/dashboard/components/widget-memory/widget-memory.component.ts
+4
-19
...board/components/widget-memory/widget-memory.component.ts
src/app/pages/datasets/components/dataset-capacity-management-card/dataset-capacity-management-card.component.html
+75
-28
...ment-card/dataset-capacity-management-card.component.html
src/app/pages/datasets/components/dataset-capacity-management-card/dataset-capacity-management-card.component.scss
+22
-13
...ment-card/dataset-capacity-management-card.component.scss
src/app/pages/datasets/components/dataset-capacity-management-card/dataset-capacity-management-card.component.ts
+44
-7
...gement-card/dataset-capacity-management-card.component.ts
src/app/pages/datasets/components/dataset-details-panel/dataset-details-panel.component.html
+1
-0
...ataset-details-panel/dataset-details-panel.component.html
src/app/pages/datasets/components/dataset-details-panel/dataset-details-panel.component.ts
+4
-0
.../dataset-details-panel/dataset-details-panel.component.ts
src/app/pages/datasets/components/dataset-node/dataset-node.component.html
+2
-2
...asets/components/dataset-node/dataset-node.component.html
src/app/pages/datasets/components/space-management-chart/space-management-chart.component.html
+75
-0
...ce-management-chart/space-management-chart.component.html
src/app/pages/datasets/components/space-management-chart/space-management-chart.component.scss
+102
-0
...ce-management-chart/space-management-chart.component.scss
src/app/pages/datasets/components/space-management-chart/space-management-chart.component.ts
+115
-0
...pace-management-chart/space-management-chart.component.ts
src/app/pages/datasets/datasets.module.ts
+4
-0
src/app/pages/datasets/datasets.module.ts
src/app/pages/datasets/store/dataset-in-tree.interface.ts
+1
-0
src/app/pages/datasets/store/dataset-in-tree.interface.ts
src/app/pages/datasets/store/dataset-store.service.spec.ts
+1
-0
src/app/pages/datasets/store/dataset-store.service.spec.ts
src/app/pages/datasets/store/dataset-store.service.ts
+1
-0
src/app/pages/datasets/store/dataset-store.service.ts
src/app/pages/reports-dashboard/components/report/report.component.ts
+2
-7
...s/reports-dashboard/components/report/report.component.ts
with
491 additions
and
84 deletions
+491
-84
src/app/core/classes/theme-utils/theme-utils.ts
View file @
c542ac6a
...
...
@@ -102,6 +102,11 @@ export class ThemeUtils {
return
output
.
map
((
str
)
=>
parseFloat
(
str
));
}
rgbToString
(
rgb
:
number
[],
alpha
?:
number
):
string
{
const
a
=
alpha
?
alpha
.
toString
()
:
'
1
'
;
return
'
rgba(
'
+
rgb
.
join
(
'
,
'
)
+
'
,
'
+
a
+
'
)
'
;
}
colorFromMeta
(
meta
:
string
):
string
{
const
trimFront
=
meta
.
replace
(
'
var(--
'
,
''
);
const
trimmed
=
trimFront
.
replace
(
'
)
'
,
''
);
...
...
This diff is collapsed.
Click to expand it.
src/app/interfaces/api-directory.interface.ts
View file @
c542ac6a
...
...
@@ -170,7 +170,7 @@ import { ImportDiskParams, PoolFindResult, PoolImportParams } from 'app/interfac
import
{
CreatePoolScrubTask
,
PoolScrubTask
,
PoolScrubTaskParams
}
from
'
app/interfaces/pool-scrub.interface
'
;
import
{
PoolUnlockQuery
,
PoolUnlockResult
}
from
'
app/interfaces/pool-unlock-query.interface
'
;
import
{
CreatePool
,
Pool
,
PoolAttachParams
,
PoolExpandParams
,
PoolReplaceParams
,
UpdatePool
,
CreatePool
,
Pool
,
PoolAttachParams
,
PoolExpandParams
,
PoolInstance
,
PoolInstanceParams
,
PoolReplaceParams
,
UpdatePool
,
}
from
'
app/interfaces/pool.interface
'
;
import
{
Process
}
from
'
app/interfaces/process.interface
'
;
import
{
QueryParams
}
from
'
app/interfaces/query-api.interface
'
;
...
...
@@ -720,6 +720,7 @@ export type ApiDirectory = {
'
pool.unlock_services_restart_choices
'
:
{
params
:
[
id
:
number
];
response
:
Choices
};
'
pool.update
'
:
{
params
:
[
id
:
number
,
update
:
UpdatePool
];
response
:
Pool
};
'
pool.upgrade
'
:
{
params
:
[
id
:
number
];
response
:
boolean
};
'
pool.get_instance_by_name
'
:
{
params
:
PoolInstanceParams
;
response
:
PoolInstance
};
// Replication
'
replication.list_datasets
'
:
{
params
:
[
transport
:
TransportMode
,
credentials
?:
number
];
response
:
string
[]
};
...
...
This diff is collapsed.
Click to expand it.
src/app/interfaces/device-nested-data-node.interface.ts
View file @
c542ac6a
...
...
@@ -8,6 +8,7 @@ export interface VDevGroup {
export
type
DeviceNestedDataNode
=
VDev
|
VDevGroup
;
// eslint-disable-next-line @typescript-eslint/naming-convention
export
function
isVDev
(
obj
:
DeviceNestedDataNode
):
obj
is
VDev
{
return
'
stats
'
in
obj
;
}
This diff is collapsed.
Click to expand it.
src/app/interfaces/pool.interface.ts
View file @
c542ac6a
...
...
@@ -114,3 +114,31 @@ export type PoolExpandParams = [
id
:
number
,
params
?:
{
geli
:
{
passphrase
:
string
}
},
];
export
type
PoolInstanceParams
=
[
name
:
string
,
];
export
interface
PoolInstance
{
id
:
number
;
name
:
string
;
guid
:
string
;
encrypt
:
number
;
encryptkey
:
string
;
encryptkey_path
:
string
;
is_decrypted
:
boolean
;
status
:
string
;
path
:
string
;
scan
:
PoolScanUpdate
;
is_upgraded
:
boolean
;
healthy
:
boolean
;
warning
:
boolean
;
status_detail
:
string
;
size
:
number
;
allocated
:
number
;
free
:
number
;
freeing
:
number
;
fragmentation
:
string
;
autotrim
:
ZfsProperty
<
string
>
;
topology
:
PoolTopology
;
}
This diff is collapsed.
Click to expand it.
src/app/pages/dashboard/components/widget-cpu/widget-cpu.component.ts
View file @
c542ac6a
...
...
@@ -354,19 +354,14 @@ export class WidgetCpuComponent extends WidgetComponent implements AfterViewInit
const
bgRgb
=
this
.
utils
.
convertToRgb
((
this
.
currentTheme
[
color
as
keyof
Theme
])
as
string
).
rgb
;
ds
.
backgroundColor
=
this
.
rgbToString
(
bgRgb
as
any
,
0.85
);
ds
.
borderColor
=
this
.
rgbToString
(
bgRgb
as
any
);
ds
.
backgroundColor
=
this
.
utils
.
rgbToString
(
bgRgb
as
any
,
0.85
);
ds
.
borderColor
=
this
.
utils
.
rgbToString
(
bgRgb
as
any
);
datasets
.
push
(
ds
);
});
return
datasets
;
}
rgbToString
(
rgb
:
string
[],
alpha
?:
number
):
string
{
const
a
=
alpha
?
alpha
.
toString
()
:
'
1
'
;
return
'
rgba(
'
+
rgb
.
join
(
'
,
'
)
+
'
,
'
+
a
+
'
)
'
;
}
stripVar
(
str
:
string
):
string
{
return
str
.
replace
(
'
var(--
'
,
''
).
replace
(
'
)
'
,
''
);
}
...
...
This diff is collapsed.
Click to expand it.
src/app/pages/dashboard/components/widget-memory/widget-memory.component.ts
View file @
c542ac6a
...
...
@@ -17,7 +17,6 @@ import {
import
{
ThemeUtils
}
from
'
app/core/classes/theme-utils/theme-utils
'
;
import
{
CoreEvent
}
from
'
app/interfaces/events
'
;
import
{
MemoryStatsEventData
}
from
'
app/interfaces/events/memory-stats-event.interface
'
;
import
{
Theme
}
from
'
app/interfaces/theme.interface
'
;
import
{
WidgetComponent
}
from
'
app/pages/dashboard/components/widget/widget.component
'
;
import
{
WidgetMemoryData
}
from
'
app/pages/dashboard/interfaces/widget-data.interface
'
;
import
{
CoreService
}
from
'
app/services/core-service/core.service
'
;
...
...
@@ -48,7 +47,6 @@ export class WidgetMemoryComponent extends WidgetComponent implements AfterViewI
configurable
=
false
;
chartId
=
UUID
.
UUID
();
colorPattern
:
string
[];
currentTheme
:
Theme
;
labels
:
string
[]
=
[
this
.
translate
.
instant
(
'
Free
'
),
this
.
translate
.
instant
(
'
ZFS Cache
'
),
this
.
translate
.
instant
(
'
Services
'
)];
...
...
@@ -136,8 +134,7 @@ export class WidgetMemoryComponent extends WidgetComponent implements AfterViewI
data
:
this
.
parseMemData
(
data
),
};
this
.
memData
=
config
;
this
.
currentTheme
=
this
.
themeService
.
currentTheme
();
this
.
colorPattern
=
this
.
processThemeColors
(
this
.
currentTheme
);
this
.
colorPattern
=
this
.
themeService
.
getColorPattern
();
this
.
isReady
=
true
;
this
.
renderChart
();
}
...
...
@@ -218,26 +215,14 @@ export class WidgetMemoryComponent extends WidgetComponent implements AfterViewI
// Create the data...
data
.
forEach
((
item
,
index
)
=>
{
const
bgColor
=
this
.
colorPattern
[
index
];
const
bgColorType
=
this
.
utils
.
getValueType
(
bgColor
);
const
bgRgb
=
this
.
themeService
.
getRgbBackgroundColorByIndex
(
index
);
const
bgRgb
=
bgColorType
===
'
hex
'
?
this
.
utils
.
hexToRgb
(
bgColor
).
rgb
:
this
.
utils
.
rgbToArray
(
bgColor
);
(
ds
.
backgroundColor
as
ChartColor
[]).
push
(
this
.
rgbToString
(
bgRgb
,
0.85
));
(
ds
.
borderColor
as
ChartColor
[]).
push
(
this
.
rgbToString
(
bgRgb
));
(
ds
.
backgroundColor
as
ChartColor
[]).
push
(
this
.
utils
.
rgbToString
(
bgRgb
,
0.85
));
(
ds
.
borderColor
as
ChartColor
[]).
push
(
this
.
utils
.
rgbToString
(
bgRgb
));
});
datasets
.
push
(
ds
);
return
datasets
;
}
private
processThemeColors
(
theme
:
Theme
):
string
[]
{
return
theme
.
accentColors
.
map
((
color
)
=>
theme
[
color
]);
}
rgbToString
(
rgb
:
number
[],
alpha
?:
number
):
string
{
const
a
=
alpha
?
alpha
.
toString
()
:
'
1
'
;
return
'
rgba(
'
+
rgb
.
join
(
'
,
'
)
+
'
,
'
+
a
+
'
)
'
;
}
}
This diff is collapsed.
Click to expand it.
src/app/pages/datasets/components/dataset-capacity-management-card/dataset-capacity-management-card.component.html
View file @
c542ac6a
<mat-card
class=
"card"
>
<mat-card-header>
<h3
mat-card-title
>
{{ 'Capacity Management' | translate }}
</h3>
<button
mat-button
(click)=
"editDataset()"
[disabled]=
"isLoadingProperties"
>
{{ 'Edit' | translate }}
</button>
<h3
mat-card-title
>
<ng-container
*ngIf=
"isFilesystem"
>
{{ 'Dataset Space Management' | translate }}
</ng-container>
<ng-container
*ngIf=
"isZvol"
>
{{ 'Zvol Space Management' | translate }}
</ng-container>
</h3>
<button
mat-button
(click)=
"editDataset()"
>
{{ 'Edit' | translate }}
</button>
</mat-card-header>
<mat-card-content>
<div
class=
"legend-placeholder"
>
<ng-container
*ngIf=
"isLoadingProperties; else loaderSkel"
></ng-container>
<ng-container
*ngIf=
"isLoadingProperties; else loaderSkel"
></ng-container>
</div>
<div
class=
"chart-placeholder"
>
<ng-container
*ngIf=
"isLoadingProperties; else loaderSkel"
></ng-container>
</div>
<div
class=
"legend-placeholder"
>
<ng-container
*ngIf=
"isLoadingProperties; else loaderSkel"
></ng-container>
<ng-container
*ngIf=
"isLoadingProperties; else loaderSkel"
></ng-container>
<ng-container
*ngIf=
"isLoadingProperties; else loaderSkel"
></ng-container>
<ix-space-management-chart
[dataset]=
"dataset"
></ix-space-management-chart>
<div
class=
"chart-extra"
>
<ng-container
*ngIf=
"!isZvol"
>
<div
class=
"details-item"
*ngIf=
"!isLoadingProperties && extraProperties?.refreservation?.parsed"
>
<span
class=
"label"
>
{{ 'Reserved for Dataset' | translate }}:
</span>
<span
class=
"value"
>
{{ extraProperties.refreservation.parsed | filesize: { standard: 'iec', round: 0 } }}
</span>
</div>
<div
class=
"details-item"
*ngIf=
"!isLoadingProperties && extraProperties?.reservation?.parsed"
>
<span
class=
"label"
>
{{ 'Reserved for Dataset
&
Children' | translate }}:
</span>
<span
class=
"value"
>
{{ extraProperties.reservation.parsed | filesize: { standard: 'iec', round: 0 } }}
</span>
</div>
</ng-container>
<ng-container
*ngIf=
"isZvol"
>
<!-- TODO: Fix me please after NAS-117254 is done -->
<div
class=
"details-item"
*ngIf=
"false"
>
<span
class=
"label"
>
{{ 'Provisioning Type' | translate }}:
</span>
<span
class=
"value"
>
{{ 'Thick' | translate }}
</span>
</div>
<div
class=
"details-item"
>
<span
class=
"label"
>
{{ 'Volume Size' | translate }}:
</span>
<span
class=
"value"
*ngIf=
"!isLoadingProperties; else valuePlaceholder"
>
{{ extraProperties.volsize.parsed | filesize: { standard: 'iec', round: 0 } }}
</span>
</div>
</ng-container>
</div>
<div
*ngIf=
"!dataset.locked
"
>
<div
class=
"details
"
>
<div
class=
"details-item"
>
<span
class=
"label"
>
{{ 'User Quotas' | translate }}:
<ng-container
*ngIf=
"!isLoadingProperties; else valuePlaceholder"
>
<span
class=
"label"
>
<ng-container
*ngIf=
"isFilesystem"
>
{{ 'Space Available to Dataset' | translate }}
</ng-container>
<ng-container
*ngIf=
"isZvol"
>
{{ 'Space Available to Zvol' | translate }}
</ng-container>
:
</span>
<span
class=
"value"
>
{{ dataset.available.parsed | filesize: { standard: 'iec', round: 0 } }}
</span>
</ng-container>
</div>
<div
class=
"details-item"
*ngIf=
"isFilesystem && hasQuota"
>
<span
class=
"label"
>
{{ 'Applied Dataset Quotas' | translate }}:
</span>
<span
class=
"value"
>
{{ '{n} (applies to descendants)' | translate: { n: extraProperties.quota.parsed | filesize: { standard: 'iec', round: 0 } } }}
</span>
<span
*ngIf=
"!isLoadingQuotas; else loaderSkel"
class=
"value"
>
{{ 'Quotas set for {n} users' | translate: { n: userQuotas } }}
</div>
<div
class=
"details-item"
*ngIf=
"hasInheritedQuotas"
>
<span
class=
"label"
>
{{ 'Inherited Quotas' | translate }}:
</span>
<span
class=
"value"
>
{{ '{n} from {dataset}' | translate: { n: inheritedQuotasDataset.quota.parsed | filesize: { standard: 'iec', round: 0 }, dataset: inheritedQuotasDataset.name } }}
</span>
<a
[routerLink]=
"['/', 'datasets', dataset.id, 'user-quotas']"
>
<a
[routerLink]=
"['/', 'datasets', inheritedQuotasDataset.id]"
>
{{ 'Go To Dataset' }}
</a>
</div>
</div>
<div
class=
"details"
>
<div
class=
"details-item"
>
<span
class=
"label"
>
{{ 'User Quotas' | translate }}:
</span>
<ng-container
*ngIf=
"checkQuotas; else noneTemplate"
>
<span
class=
"value"
*ngIf=
"!isLoadingQuotas; else valuePlaceholder"
>
{{ 'Quotas set for {n} users' | translate: { n: userQuotas } }}
</span>
</ng-container>
<a
*ngIf=
"checkQuotas"
[routerLink]=
"['/', 'datasets', dataset.id, 'user-quotas']"
>
{{ 'Manage User Quotas' | translate }}
</a>
</div>
<div
class=
"details-item"
>
<span
class=
"label"
>
{{ 'Group Quotas' | translate }}:
<
/
span>
<span
*ngIf=
"!isLoadingQuotas; else loaderSkel"
class=
"value"
>
{{ 'Quotas set for {n} groups' | translate: { n: groupQuotas } }}
</
span
>
<a
[routerLink]=
"['/', 'datasets', dataset.id, 'group-quotas']"
>
<span
class=
"label"
>
{{ 'Group Quotas' | translate }}:
</span>
<ng-container
*ngIf=
"checkQuotas; else noneTemplate"
>
<span
class=
"value"
*ngIf=
"!isLoadingQuotas; else valuePlaceholder"
>
{{ 'Quotas set for {n} groups' | translate: { n: groupQuotas } }}
</span>
</
ng-container
>
<a
*ngIf=
"checkQuotas"
[routerLink]=
"['/', 'datasets', dataset.id, 'group-quotas']"
>
{{ 'Manage Group Quotas' | translate }}
</a>
</div>
...
...
@@ -44,6 +87,10 @@
</mat-card-content>
</mat-card>
<ng-template
#loaderSkel
>
<ngx-skeleton-loader></ngx-skeleton-loader>
<ng-template
#valuePlaceholder
>
<ngx-skeleton-loader
class=
"value-placeholder"
></ngx-skeleton-loader>
</ng-template>
<ng-template
#noneTemplate
>
{{ 'None' | translate }}
</ng-template>
This diff is collapsed.
Click to expand it.
src/app/pages/datasets/components/dataset-capacity-management-card/dataset-capacity-management-card.component.scss
View file @
c542ac6a
...
...
@@ -2,22 +2,31 @@
.card
{
@include
details-card
();
}
.legend-placeholder
{
align-items
:
center
;
display
:
flex
;
gap
:
12px
;
}
.chart-extra
{
align-items
:
center
;
display
:
flex
;
justify-content
:
space-around
;
.chart-placeholder
{
align-items
:
center
;
display
:
flex
;
gap
:
12px
;
.details-item
{
margin
:
20px
0
0
;
}
}
ngx-skeleton-loader
{
::ng-deep
.loa
der
{
height
:
64px
;
.details-item
{
.value-placehol
der
{
flex
:
1
;
}
}
}
.details
{
border-top
:
1px
solid
var
(
--
lines
);
box-sizing
:
border-box
;
margin
:
20px
-25px
0
;
// Fragile. Rely on external styles
padding
:
20px
25px
0
!
important
;
// Fragile. Rely on external styles
}
ix-space-management-chart
{
padding
:
0
0
0
8px
;
}
This diff is collapsed.
Click to expand it.
src/app/pages/datasets/components/dataset-capacity-management-card/dataset-capacity-management-card.component.ts
View file @
c542ac6a
...
...
@@ -2,14 +2,14 @@ import {
Component
,
ChangeDetectionStrategy
,
ChangeDetectorRef
,
Input
,
OnChanges
,
OnInit
,
}
from
'
@angular/core
'
;
import
{
UntilDestroy
,
untilDestroyed
}
from
'
@ngneat/until-destroy
'
;
import
{
maxBy
}
from
'
lodash
'
;
import
{
Subscription
,
forkJoin
}
from
'
rxjs
'
;
import
{
map
}
from
'
rxjs/operators
'
;
import
{
DatasetQuotaType
}
from
'
app/enums/dataset.enum
'
;
import
{
map
,
take
}
from
'
rxjs/operators
'
;
import
{
DatasetType
,
DatasetQuotaType
}
from
'
app/enums/dataset.enum
'
;
import
{
Dataset
}
from
'
app/interfaces/dataset.interface
'
;
import
{
DatasetCapacitySettingsComponent
,
}
from
'
app/pages/datasets/components/dataset-capacity-management-card/dataset-capacity-settings/dataset-capacity-settings.component
'
;
import
{
DatasetCapacitySettingsComponent
}
from
'
app/pages/datasets/components/dataset-capacity-management-card/dataset-capacity-settings/dataset-capacity-settings.component
'
;
import
{
DatasetInTree
}
from
'
app/pages/datasets/store/dataset-in-tree.interface
'
;
import
{
DatasetTreeStore
}
from
'
app/pages/datasets/store/dataset-store.service
'
;
import
{
WebSocketService
}
from
'
app/services
'
;
import
{
IxSlideInService
}
from
'
app/services/ix-slide-in.service
'
;
...
...
@@ -23,17 +23,39 @@ import { IxSlideInService } from 'app/services/ix-slide-in.service';
export
class
DatasetCapacityManagementCardComponent
implements
OnInit
,
OnChanges
{
@
Input
()
dataset
:
DatasetInTree
;
inheritedQuotasDataset
:
DatasetInTree
;
extraProperties
:
Dataset
;
extraPropertiesSubscription
:
Subscription
;
isLoadingQuotas
=
false
;
isLoadingProperties
=
false
;
isLoadingQuotas
=
false
;
quotasSubscription
:
Subscription
;
userQuotas
:
number
;
groupQuotas
:
number
;
get
isFilesystem
():
boolean
{
return
this
.
dataset
.
type
===
DatasetType
.
Filesystem
;
}
get
isZvol
():
boolean
{
return
this
.
dataset
.
type
===
DatasetType
.
Volume
;
}
get
checkQuotas
():
boolean
{
return
!
this
.
dataset
.
locked
&&
this
.
isFilesystem
;
}
get
hasQuota
():
boolean
{
return
Boolean
(
this
.
extraProperties
?.
quota
?.
parsed
);
}
get
hasInheritedQuotas
():
boolean
{
return
this
.
inheritedQuotasDataset
?.
quota
?.
parsed
&&
this
.
inheritedQuotasDataset
?.
id
!==
this
.
dataset
?.
id
;
}
constructor
(
private
ws
:
WebSocketService
,
private
cdr
:
ChangeDetectorRef
,
private
datasetStore
:
DatasetTreeStore
,
private
slideInService
:
IxSlideInService
,
)
{}
...
...
@@ -45,7 +67,8 @@ export class DatasetCapacityManagementCardComponent implements OnInit, OnChanges
ngOnChanges
():
void
{
this
.
loadExtraProperties
();
if
(
!
this
.
dataset
.
locked
)
{
this
.
getInheritedQuotas
();
if
(
this
.
checkQuotas
)
{
this
.
getQuotas
();
}
}
...
...
@@ -83,6 +106,20 @@ export class DatasetCapacityManagementCardComponent implements OnInit, OnChanges
});
}
getInheritedQuotas
():
void
{
this
.
datasetStore
.
selectedBranch$
.
pipe
(
map
((
datasets
)
=>
{
const
datasetWithQuotas
=
datasets
.
filter
((
dataset
)
=>
Boolean
(
dataset
?.
quota
?.
parsed
));
return
maxBy
(
datasetWithQuotas
,
(
dataset
)
=>
dataset
.
quota
.
parsed
);
}),
take
(
1
),
untilDestroyed
(
this
),
).
subscribe
((
dataset
)
=>
{
this
.
inheritedQuotasDataset
=
dataset
;
this
.
cdr
.
markForCheck
();
});
}
editDataset
():
void
{
const
editDatasetComponent
=
this
.
slideInService
.
open
(
DatasetCapacitySettingsComponent
,
{
wide
:
true
});
editDatasetComponent
.
setDatasetForEdit
(
this
.
extraProperties
);
...
...
This diff is collapsed.
Click to expand it.
src/app/pages/datasets/components/dataset-details-panel/dataset-details-panel.component.html
View file @
c542ac6a
...
...
@@ -12,6 +12,7 @@
<div
*ngIf=
"!dataset.locked"
class=
"add-buttons"
>
<button
*ngIf=
"!isZvol"
mat-button
(click)=
"onAddZvol()"
>
{{ 'Add Zvol' | translate }}
</button>
...
...
This diff is collapsed.
Click to expand it.
src/app/pages/datasets/components/dataset-details-panel/dataset-details-panel.component.ts
View file @
c542ac6a
...
...
@@ -51,6 +51,10 @@ export class DatasetDetailsPanelComponent implements OnInit {
return
isRootDataset
(
this
.
dataset
);
}
get
isZvol
():
boolean
{
return
this
.
dataset
.
type
===
DatasetType
.
Volume
;
}
onAddDataset
():
void
{
const
addDatasetComponent
=
this
.
modalService
.
openInSlideIn
(
DatasetFormComponent
);
addDatasetComponent
.
setParent
(
this
.
dataset
.
id
);
...
...
This diff is collapsed.
Click to expand it.
src/app/pages/datasets/components/dataset-node/dataset-node.component.html
View file @
c542ac6a
...
...
@@ -6,9 +6,9 @@
<span
class=
"name"
>
{{ label }}
</span>
</div>
<div
class=
"cell"
>
{{ '{value} Used' | translate: { value: dataset.used.parsed | filesize: { standard: 'iec' } } }}
{{ '{value} Used' | translate: { value: dataset.used.parsed | filesize: { standard: 'iec'
, round: 0
} } }}
/
{{ '{value} Left' | translate: { value: dataset.available.parsed | filesize: { standard: 'iec' } } }}
{{ '{value} Left' | translate: { value: dataset.available.parsed | filesize: { standard: 'iec'
, round: 0
} } }}
</div>
<div
class=
"cell cell-encryption"
>
<ix-dataset-encryption-cell
[dataset]=
"dataset"
></ix-dataset-encryption-cell>
...
...
This diff is collapsed.
Click to expand it.
src/app/pages/datasets/components/space-management-chart/space-management-chart.component.html
0 → 100644
View file @
c542ac6a
<div
class=
"chart-wrapper"
*ngIf=
"!isLoading; else chartPlaceholder"
>
<canvas
#canvas
baseChart
chartType=
"doughnut"
[datasets]=
"chartData"
[options]=
"chartOptions"
[width]=
"180"
[height]=
"180"
></canvas>
</div>
<div
class=
"chart-description"
>
<h3
class=
"chart-header"
>
<span
class=
"chart-title"
>
{{ 'Total Allocation' | translate }}:
</span>
<span
*ngIf=
"!isLoading; else valueLoader"
>
{{ extraProperties.used.parsed | filesize: { standard: 'iec', round: 0 } }}
</span>
</h3>
<div
class=
"legend-wrapper"
*ngIf=
"!isLoading; else legendPlaceholder"
>
<div
class=
"legend-list-item"
*ngIf=
"extraProperties.usedbydataset.parsed"
>
<span
class=
"legend-label"
>
<span
class=
"legend-swatch"
></span>
{{ 'Data Written' | translate }}
</span>
<span
class=
"legend-value"
>
{{ extraProperties.usedbydataset.parsed | filesize: { standard: 'iec', round: 0 } }}
<ng-container
*ngIf=
"extraProperties.usedbydataset.parsed"
>
({{ extraProperties.usedbydataset.parsed / extraProperties.used.parsed | percent }})
</ng-container>
</span>
</div>
<div
class=
"legend-list-item"
*ngIf=
"extraProperties.usedbysnapshots.parsed"
>
<span
class=
"legend-label"
>
<span
class=
"legend-swatch"
></span>
<ng-container
*ngIf=
"!isZvol"
>
{{ 'Snapshots' | translate }}
</ng-container>
<ng-container
*ngIf=
"isZvol"
>
{{ 'Used by Snapshots' | translate }}
</ng-container>
</span>
<span
class=
"legend-value"
>
{{ extraProperties.usedbysnapshots.parsed | filesize: { standard: 'iec', round: 0 } }}
<ng-container
*ngIf=
"extraProperties.usedbysnapshots.parsed"
>
({{ extraProperties.usedbysnapshots.parsed / extraProperties.used.parsed | percent }})
</ng-container>
</span>
</div>
<ng-container
*ngIf=
"!isZvol"
>
<div
class=
"legend-list-item"
*ngIf=
"extraProperties.usedbychildren.parsed"
>
<span
class=
"legend-label"
>
<span
class=
"legend-swatch"
></span>
{{ 'Children' | translate }}
</span>
<span
class=
"legend-value"
>
{{ extraProperties.usedbychildren.parsed | filesize: { standard: 'iec', round: 0 } }}
<ng-container
*ngIf=
"extraProperties.usedbychildren.parsed"
>
({{ extraProperties.usedbychildren.parsed / extraProperties.used.parsed | percent }})
</ng-container>
</span>
</div>
</ng-container>
</div>
</div>
<ng-template
#legendPlaceholder
>
<ngx-skeleton-loader
class=
"legend-placeholder"
></ngx-skeleton-loader>
<ngx-skeleton-loader
class=
"legend-placeholder"
></ngx-skeleton-loader>
<ngx-skeleton-loader
class=
"legend-placeholder"
></ngx-skeleton-loader>
</ng-template>
<ng-template
#chartPlaceholder
>
<ngx-skeleton-loader
class=
"chart-placeholder"
></ngx-skeleton-loader>
</ng-template>
<ng-template
#valueLoader
>
<ngx-skeleton-loader
class=
"value-placeholder"
></ngx-skeleton-loader>
</ng-template>
This diff is collapsed.
Click to expand it.
src/app/pages/datasets/components/space-management-chart/space-management-chart.component.scss
0 → 100644
View file @
c542ac6a
$chart-size
:
180px
!
default
;
:host
{
display
:
flex
;
gap
:
24px
;
min-height
:
$chart-size
;
}
.chart-wrapper
{
height
:
$chart-size
;
width
:
$chart-size
;
}
.chart-description
{
flex
:
1
;
}
.chart-header
{
align-items
:
center
;
border-bottom
:
1px
solid
var
(
--
lines
);
box-sizing
:
border-box
;
display
:
flex
;
font-size
:
18px
;
font-weight
:
normal
;
gap
:
8px
;
margin-bottom
:
12px
;
padding
:
16px
8px
12px
;
white-space
:
nowrap
;
}
.chart-placeholder
{
align-items
:
center
;
display
:
flex
;
flex
:
0
0
auto
;
height
:
$chart-size
;
width
:
$chart-size
;
::ng-deep
.loader
{
border-radius
:
50%
;
height
:
$chart-size
;
margin
:
0
;
width
:
$chart-size
;
}
}
.value-placeholder
{
align-items
:
center
;
display
:
inline-flex
;
flex
:
1
;
::ng-deep
.loader
{
margin
:
0
;
}
}
.legend-placeholder
{
align-items
:
center
;
display
:
flex
;
flex
:
1
;
margin-bottom
:
8px
;
::ng-deep
.loader
{
margin
:
0
;
}
}
.legend-list-item
{
align-items
:
center
;
display
:
flex
;
justify-content
:
space-between
;
margin-bottom
:
8px
;
.legend-label
{
align-items
:
center
;
display
:
flex
;
gap
:
8px
;
}
.legend-swatch
{
background-color
:
var
(
--
lines
);
border-radius
:
50%
;
display
:
inline-block
;
height
:
12px
;
width
:
12px
;
}
&
:nth-child
(
1
)
.legend-swatch
{
background-color
:
var
(
--
blue
);
}
&
:nth-child
(
2
)
.legend-swatch
{
background-color
:
var
(
--
magenta
);
}
&
:nth-child
(
3
)
.legend-swatch
{
background-color
:
var
(
--
orange
);
}
&
:nth-child
(
4
)
.legend-swatch
{
background-color
:
var
(
--
orange
);
}
}
This diff is collapsed.
Click to expand it.
src/app/pages/datasets/components/space-management-chart/space-management-chart.component.ts
0 → 100644
View file @
c542ac6a
import
{
ChangeDetectionStrategy
,
ChangeDetectorRef
,
Component
,
Input
,
OnChanges
,
}
from
'
@angular/core
'
;
import
{
UntilDestroy
,
untilDestroyed
}
from
'
@ngneat/until-destroy
'
;
import
{
ChartColor
,
ChartDataSets
,
ChartOptions
}
from
'
chart.js
'
;
import
{
Subscription
}
from
'
rxjs
'
;
import
{
map
}
from
'
rxjs/operators
'
;
import
{
DatasetType
}
from
'
app/enums/dataset.enum
'
;
import
{
Dataset
}
from
'
app/interfaces/dataset.interface
'
;
import
{
DatasetInTree
}
from
'
app/pages/datasets/store/dataset-in-tree.interface
'
;
import
{
WebSocketService
}
from
'
app/services
'
;
import
{
ThemeService
}
from
'
app/services/theme/theme.service
'
;
@
UntilDestroy
()
@
Component
({
selector
:
'
ix-space-management-chart
'
,
templateUrl
:
'
./space-management-chart.component.html
'
,
styleUrls
:
[
'
./space-management-chart.component.scss
'
],
changeDetection
:
ChangeDetectionStrategy
.
OnPush
,
})
export
class
SpaceManagementChartComponent
implements
OnChanges
{
@
Input
()
dataset
:
DatasetInTree
;
isLoading
=
false
;
extraProperties
:
Dataset
;
subscription
:
Subscription
;
chartData
:
ChartDataSets
[]
=
[{
data
:
[]
}];
chartOptions
:
ChartOptions
=
{
tooltips
:
{
enabled
:
false
,
},
responsive
:
false
,
maintainAspectRatio
:
true
,
legend
:
{
display
:
false
,
},
responsiveAnimationDuration
:
0
,
animation
:
{
duration
:
0
,
animateRotate
:
false
,
animateScale
:
false
,
},
hover
:
{
animationDuration
:
0
,
},
};
get
isZvol
():
boolean
{
return
this
.
dataset
.
type
===
DatasetType
.
Volume
;
}
constructor
(
private
cdr
:
ChangeDetectorRef
,
private
ws
:
WebSocketService
,
private
themeService
:
ThemeService
,
)
{}
ngOnChanges
():
void
{
this
.
loadExtraProperties
();
}
loadExtraProperties
():
void
{
this
.
isLoading
=
true
;
this
.
cdr
.
markForCheck
();
this
.
subscription
?.
unsubscribe
();
this
.
subscription
=
this
.
ws
.
call
(
'
pool.dataset.query
'
,
[[[
'
id
'
,
'
=
'
,
this
.
dataset
.
id
]]]).
pipe
(
map
((
datasets
)
=>
datasets
[
0
]),
untilDestroyed
(
this
),
).
subscribe
((
dataset
)
=>
{
this
.
extraProperties
=
dataset
;
this
.
updateChartData
();
this
.
isLoading
=
false
;
this
.
cdr
.
markForCheck
();
});
}
private
updateChartData
():
void
{
const
data
:
number
[]
=
[];
if
(
this
.
isZvol
)
{
data
.
push
(
this
.
extraProperties
.
usedbydataset
.
parsed
,
this
.
extraProperties
.
usedbysnapshots
.
parsed
,
);
}
else
{
data
.
push
(
this
.
extraProperties
.
usedbydataset
.
parsed
,
this
.
extraProperties
.
usedbysnapshots
.
parsed
,
this
.
extraProperties
.
usedbychildren
.
parsed
,
);
}
this
.
chartData
=
this
.
makeDatasets
(
data
);
}
private
makeDatasets
(
data
:
number
[]):
ChartDataSets
[]
{
const
datasets
:
ChartDataSets
[]
=
[];
const
filteredData
=
data
.
filter
(
Boolean
);
const
ds
:
ChartDataSets
=
{
data
:
filteredData
,
backgroundColor
:
[],
borderColor
:
[],
borderWidth
:
1
,
type
:
'
doughnut
'
,
};
filteredData
.
forEach
((
_
,
index
)
=>
{
const
bgRgb
=
this
.
themeService
.
getRgbBackgroundColorByIndex
(
index
);
(
ds
.
backgroundColor
as
ChartColor
[]).
push
(
this
.
themeService
.
getUtils
().
rgbToString
(
bgRgb
,
0.85
));
(
ds
.
borderColor
as
ChartColor
[]).
push
(
this
.
themeService
.
getUtils
().
rgbToString
(
bgRgb
));
});
datasets
.
push
(
ds
);
return
datasets
;
}
}
This diff is collapsed.
Click to expand it.
src/app/pages/datasets/datasets.module.ts
View file @
c542ac6a
...
...
@@ -10,6 +10,7 @@ import { MatSlideToggleModule } from '@angular/material/slide-toggle';
import
{
MatSortModule
}
from
'
@angular/material/sort
'
;
import
{
MatTooltipModule
}
from
'
@angular/material/tooltip
'
;
import
{
TranslateModule
}
from
'
@ngx-translate/core
'
;
import
{
ChartsModule
}
from
'
ng2-charts
'
;
import
{
NgxFilesizeModule
}
from
'
ngx-filesize
'
;
import
{
NgxSkeletonLoaderModule
}
from
'
ngx-skeleton-loader
'
;
import
{
CommonDirectivesModule
}
from
'
app/directives/common/common-directives.module
'
;
...
...
@@ -39,11 +40,13 @@ import { DatasetCapacitySettingsComponent } from './components/dataset-capacity-
import
{
DatasetIconComponent
}
from
'
./components/dataset-icon/dataset-icon.component
'
;
import
{
DatasetEncryptionCellComponent
}
from
'
./components/dataset-node/dataset-encryption-cell/dataset-encryption-cell.component
'
;
import
{
DatasetNodeComponent
}
from
'
./components/dataset-node/dataset-node.component
'
;
import
{
SpaceManagementChartComponent
}
from
'
./components/space-management-chart/space-management-chart.component
'
;
@
NgModule
({
imports
:
[
CommonModule
,
CommonDirectivesModule
,
ChartsModule
,
LayoutModule
,
routing
,
TranslateModule
,
...
...
@@ -86,6 +89,7 @@ import { DatasetNodeComponent } from './components/dataset-node/dataset-node.com
DatasetIconComponent
,
DatasetEncryptionCellComponent
,
ZvolFormComponent
,
SpaceManagementChartComponent
,
DatasetCapacitySettingsComponent
,
],
providers
:
[
...
...
This diff is collapsed.
Click to expand it.
src/app/pages/datasets/store/dataset-in-tree.interface.ts
View file @
c542ac6a
...
...
@@ -18,4 +18,5 @@ export type DatasetInTree = Pick<Dataset,
|
'
pool
'
|
'
type
'
|
'
used
'
|
'
quota
'
>
;
This diff is collapsed.
Click to expand it.
src/app/pages/datasets/store/dataset-store.service.spec.ts
View file @
c542ac6a
...
...
@@ -50,6 +50,7 @@ describe('DatasetTreeStore', () => {
'
encryptionroot
'
,
'
keyformat
'
,
'
keystatus
'
,
'
quota
'
,
],
},
order_by
:
[
'
name
'
],
...
...
This diff is collapsed.
Click to expand it.
src/app/pages/datasets/store/dataset-store.service.ts
View file @
c542ac6a
...
...
@@ -80,6 +80,7 @@ export class DatasetTreeStore extends ComponentStore<DatasetTreeState> {
'
encryptionroot
'
,
'
keyformat
'
,
'
keystatus
'
,
'
quota
'
,
],
},
order_by
:
[
'
name
'
],
...
...
This diff is collapsed.
Click to expand it.
src/app/pages/reports-dashboard/components/report/report.component.ts
View file @
c542ac6a
...
...
@@ -20,7 +20,6 @@ import { ProductType } from 'app/enums/product-type.enum';
import
{
CoreEvent
}
from
'
app/interfaces/events
'
;
import
{
ReportingGraph
}
from
'
app/interfaces/reporting-graph.interface
'
;
import
{
ReportingAggregationKeys
,
ReportingData
}
from
'
app/interfaces/reporting.interface
'
;
import
{
Theme
}
from
'
app/interfaces/theme.interface
'
;
import
{
EmptyConfig
,
EmptyType
}
from
'
app/modules/entity/entity-empty/entity-empty.component
'
;
import
{
WidgetComponent
}
from
'
app/pages/dashboard/components/widget/widget.component
'
;
import
{
LineChartComponent
}
from
'
app/pages/reports-dashboard/components/line-chart/line-chart.component
'
;
...
...
@@ -213,8 +212,8 @@ export class ReportComponent extends WidgetComponent implements AfterViewInit, O
filter
(
Boolean
),
map
(()
=>
this
.
themeService
.
currentTheme
()),
untilDestroyed
(
this
),
).
subscribe
((
theme
:
Theme
)
=>
{
this
.
chartColors
=
this
.
processThemeColors
(
theme
);
).
subscribe
(()
=>
{
this
.
chartColors
=
this
.
themeService
.
getColorPattern
(
);
});
this
.
store$
.
select
(
selectTimezone
).
pipe
(
untilDestroyed
(
this
)).
subscribe
((
timezone
)
=>
{
...
...
@@ -256,10 +255,6 @@ export class ReportComponent extends WidgetComponent implements AfterViewInit, O
this
.
fetchReportData
(
rrdOptions
,
changes
.
report
.
currentValue
,
identifier
);
}
private
processThemeColors
(
theme
:
Theme
):
string
[]
{
return
theme
.
accentColors
.
map
((
color
)
=>
theme
[
color
]);
}
setChartInteractive
(
value
:
boolean
):
void
{
this
.
isActive
=
value
;
}
...
...
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