Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Open sidebar
CSAN
Csan
Commits
d01ff31d
Commit
d01ff31d
authored
Jun 29, 2020
by
AllForNothing
Browse files
Add P2p preheat distribution instance UI
Signed-off-by:
AllForNothing
<
sshijun@vmware.com
>
parent
a78ab897
Changes
24
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
1626 additions
and
8 deletions
+1626
-8
src/portal/scripts/convert-yaml-to-json.js
src/portal/scripts/convert-yaml-to-json.js
+28
-0
src/portal/src/app/app.module.ts
src/portal/src/app/app.module.ts
+3
-1
src/portal/src/app/base/harbor-shell/harbor-shell.component.html
...tal/src/app/base/harbor-shell/harbor-shell.component.html
+4
-0
src/portal/src/app/distribution/base.scss
src/portal/src/app/distribution/base.scss
+20
-0
src/portal/src/app/distribution/distribution-instances/distribution-instances.component.html
...tribution-instances/distribution-instances.component.html
+137
-0
src/portal/src/app/distribution/distribution-instances/distribution-instances.component.scss
...tribution-instances/distribution-instances.component.scss
+32
-0
src/portal/src/app/distribution/distribution-instances/distribution-instances.component.spec.ts
...bution-instances/distribution-instances.component.spec.ts
+142
-0
src/portal/src/app/distribution/distribution-instances/distribution-instances.component.ts
...istribution-instances/distribution-instances.component.ts
+377
-0
src/portal/src/app/distribution/distribution-interface.ts
src/portal/src/app/distribution/distribution-interface.ts
+16
-0
src/portal/src/app/distribution/distribution-setup-modal/distribution-setup-modal.component.html
...ution-setup-modal/distribution-setup-modal.component.html
+238
-0
src/portal/src/app/distribution/distribution-setup-modal/distribution-setup-modal.component.scss
...ution-setup-modal/distribution-setup-modal.component.scss
+3
-0
src/portal/src/app/distribution/distribution-setup-modal/distribution-setup-modal.component.spec.ts
...on-setup-modal/distribution-setup-modal.component.spec.ts
+100
-0
src/portal/src/app/distribution/distribution-setup-modal/distribution-setup-modal.component.ts
...ibution-setup-modal/distribution-setup-modal.component.ts
+219
-0
src/portal/src/app/distribution/distribution.module.ts
src/portal/src/app/distribution/distribution.module.ts
+14
-0
src/portal/src/app/harbor-routing.module.ts
src/portal/src/app/harbor-routing.module.ts
+6
-0
src/portal/src/app/shared/shared.const.ts
src/portal/src/app/shared/shared.const.ts
+3
-2
src/portal/src/i18n/lang/en-us-lang.json
src/portal/src/i18n/lang/en-us-lang.json
+71
-2
src/portal/src/i18n/lang/es-es-lang.json
src/portal/src/i18n/lang/es-es-lang.json
+71
-1
src/portal/src/i18n/lang/fr-fr-lang.json
src/portal/src/i18n/lang/fr-fr-lang.json
+71
-1
src/portal/src/i18n/lang/pt-br-lang.json
src/portal/src/i18n/lang/pt-br-lang.json
+71
-1
No files found.
src/portal/scripts/convert-yaml-to-json.js
View file @
d01ff31d
...
...
@@ -21,4 +21,32 @@ const swaggerObj = yaml.load(fs.readFileSync(inputFile, {encoding: 'utf-8'}));
if
(
swaggerObj
.
host
)
{
delete
swaggerObj
.
host
;
}
// enhancement for property 'additionalProperties'
traverseObject
(
swaggerObj
);
fs
.
writeFileSync
(
outputDir
+
'
/swagger.json
'
,
JSON
.
stringify
(
swaggerObj
,
null
,
2
));
function
traverseObject
(
obj
)
{
if
(
obj
)
{
if
(
Array
.
isArray
(
obj
))
{
for
(
let
i
=
0
;
i
<
obj
.
length
;
i
++
)
{
traverseObject
(
obj
[
i
])
}
}
if
(
typeof
obj
===
'
object
'
)
{
for
(
let
name
in
obj
)
{
if
(
obj
.
hasOwnProperty
(
name
))
{
if
(
name
===
'
additionalProperties
'
&&
obj
[
name
].
type
===
'
object
'
&&
obj
[
name
].
additionalProperties
===
true
)
{
obj
[
name
]
=
true
;
}
else
{
traverseObject
(
obj
[
name
])
}
}
}
}
}
}
src/portal/src/app/app.module.ts
View file @
d01ff31d
...
...
@@ -46,6 +46,7 @@ import { ProjectQuotasComponent } from './project-quotas/project-quotas.componen
import
{
HarborLibraryModule
}
from
"
../lib/harbor-library.module
"
;
import
{
HTTP_INTERCEPTORS
}
from
'
@angular/common/http
'
;
import
{
AllPipesModule
}
from
'
./all-pipes/all-pipes.module
'
;
import
{
DistributionModule
}
from
'
./distribution/distribution.module
'
;
registerLocaleData
(
zh
,
'
zh-cn
'
);
registerLocaleData
(
es
,
'
es-es
'
);
registerLocaleData
(
localeFr
,
'
fr-fr
'
);
...
...
@@ -85,7 +86,8 @@ export function getCurrentLanguage(translateService: TranslateService) {
OidcOnboardModule
,
LicenseModule
,
HarborLibraryModule
,
AllPipesModule
AllPipesModule
,
DistributionModule
,
],
exports
:
[
],
...
...
src/portal/src/app/base/harbor-shell/harbor-shell.component.html
View file @
d01ff31d
...
...
@@ -56,6 +56,10 @@
<clr-icon
shape=
"cloud-traffic"
clrVerticalNavIcon
></clr-icon>
{{'SIDE_NAV.SYSTEM_MGMT.REPLICATION' | translate}}
</a>
<a
clrVerticalNavLink
routerLink=
"/harbor/distribution/instances"
routerLinkActive=
"active"
>
<clr-icon
shape=
"share"
></clr-icon>
{{'SIDE_NAV.DISTRIBUTIONS.NAME' | translate}}
</a>
<a
*ngIf=
"!withAdmiral"
clrVerticalNavLink
routerLink=
"/harbor/labels"
routerLinkActive=
"active"
>
<clr-icon
shape=
"tag"
clrVerticalNavIcon
></clr-icon>
...
...
src/portal/src/app/distribution/base.scss
0 → 100644
View file @
d01ff31d
@mixin
refresh-button
{
cursor
:
pointer
;
margin-top
:
7px
;
}
@mixin
refresh-button-hover
(
$color
)
{
color
:
$color
;
}
@mixin
float-right
(
$right-margin
)
{
display
:
flex
;
justify-content
:
flex-end
;
margin-right
:
$right-margin
;
}
@mixin
square
(
$edge
)
{
width
:
$edge
;
height
:
$edge
;
min-height
:
$edge
;
}
src/portal/src/app/distribution/distribution-instances/distribution-instances.component.html
0 → 100644
View file @
d01ff31d
<div
class=
"row"
>
<div
class=
"col-lg-12 col-md-12 col-sm-12 col-xs-12"
>
<h2
class=
"custom-h2"
>
{{ 'SIDE_NAV.DISTRIBUTIONS.INSTANCES' | translate }}
</h2>
<div>
<clr-datagrid
(clrDgRefresh)=
"loadData()"
[clrDgLoading]=
"inProgress"
[(clrDgSelected)]=
"selectedRow"
>
<clr-dg-action-bar>
<div
class=
"clr-row"
>
<div
class=
"clr-col-7"
>
<button
id=
"new-instance"
type=
"button"
class=
"btn btn-secondary"
(click)=
"addInstance()"
>
<clr-icon
shape=
"plus"
size=
"16"
></clr-icon>
{{
'DISTRIBUTION.ADD_ACTION' | translate
}}
</button>
<button
id=
"set-default"
[disabled]=
"!(selectedRow && selectedRow.length === 1 && !selectedRow[0].default && !selectedRow[0].enabled)"
class=
"btn btn-secondary"
(click)=
"setAsDefault()"
>
{{'SCANNER.SET_AS_DEFAULT' | translate}}
</button>
<clr-dropdown
[clrCloseMenuOnItemClick]=
"false"
class=
"btn btn-link"
clrDropdownTrigger
>
<span
id=
"member-action"
>
{{ 'BUTTON.ACTIONS' | translate}}
<clr-icon
shape=
"caret down"
></clr-icon></span>
<clr-dropdown-menu
*clrIfOpen
>
<clr-dropdown>
<button
type=
"button"
class=
"btn btn-secondary"
(click)=
"editInstance()"
[disabled]=
"!(selectedRow && selectedRow.length === 1)"
>
<clr-icon
shape=
"edit"
size=
"16"
></clr-icon>
{{'DISTRIBUTION.EDIT_ACTION' | translate}}
</button>
<button
type=
"button"
class=
"btn btn-secondary"
(click)=
"operateInstances('enable', selectedRow)"
[disabled]=
"!(selectedRow && selectedRow.length === 1 && !selectedRow[0].enabled)"
>
<clr-icon
shape=
"connect"
size=
"16"
></clr-icon>
{{'DISTRIBUTION.ENABLE_ACTION' | translate}}
</button>
<button
type=
"button"
class=
"btn btn-secondary"
(click)=
"operateInstances('disable', selectedRow)"
[disabled]=
"!(selectedRow && selectedRow.length === 1 && selectedRow[0].enabled)"
>
<clr-icon
shape=
"disconnect"
size=
"16"
></clr-icon>
{{'DISTRIBUTION.DISABLE_ACTION' | translate}}
</button>
<div
class=
"dropdown-divider"
></div>
<button
type=
"button"
class=
"btn btn-secondary"
(click)=
"operateInstances('delete', selectedRow)"
[disabled]=
"selectedRow.length < 1"
>
<clr-icon
shape=
"window-close"
size=
"16"
></clr-icon>
{{'DISTRIBUTION.DELETE_ACTION' | translate}}
</button>
</clr-dropdown>
</clr-dropdown-menu>
</clr-dropdown>
</div>
<div
class=
"clr-col-5"
>
<div
class=
"action-head-pos"
>
<hbr-filter
[withDivider]=
"true"
filterPlaceholder=
"{{'DISTRIBUTION.FILTER_INSTANCE_PLACEHOLDER' | translate}}"
(filterEvt)=
"doFilter($event)"
></hbr-filter>
<span
class=
"refresh-btn"
>
<clr-icon
shape=
"refresh"
[hidden]=
"inProgress"
ng-disabled=
"inProgress"
(click)=
"refresh()"
></clr-icon>
<span
class=
"spinner spinner-inline"
[hidden]=
"inProgress === false"
></span>
</span>
</div>
</div>
</div>
</clr-dg-action-bar>
<clr-dg-column>
{{ 'DISTRIBUTION.NAME' | translate }}
</clr-dg-column>
<clr-dg-column>
{{ 'DISTRIBUTION.ENDPOINT' | translate }}
</clr-dg-column>
<clr-dg-column>
{{ 'DISTRIBUTION.PROVIDER' | translate }}
</clr-dg-column>
<clr-dg-column>
{{ 'DISTRIBUTION.STATUS' | translate }}
</clr-dg-column>
<clr-dg-column>
{{ 'DISTRIBUTION.ENABLED' | translate }}
</clr-dg-column>
<clr-dg-column>
{{'SCANNER.AUTH' | translate}}
</clr-dg-column>
<clr-dg-column>
{{'DISTRIBUTION.SETUP_TIMESTAMP' | translate}}
</clr-dg-column>
<clr-dg-column>
{{'DISTRIBUTION.DESCRIPTION' | translate}}
</clr-dg-column>
<clr-dg-placeholder>
{{
'DISTRIBUTION.NOT_FOUND' | translate
}}
</clr-dg-placeholder>
<clr-dg-row
*ngFor=
"let instance of instances"
[clrDgItem]=
"instance"
>
<clr-dg-cell>
<span>
{{ instance.name }}
</span>
<span
*ngIf=
"instance.default"
class=
"label label-info ml-1"
>
{{'SCANNER.DEFAULT' | translate}}
</span>
</clr-dg-cell>
<clr-dg-cell>
{{ instance.endpoint }}
</clr-dg-cell>
<clr-dg-cell>
<span>
{{ instance.vendor }}
</span>
<clr-signpost
*ngIf=
"providerMap[instance.vendor]"
>
<clr-signpost-content
*clrIfOpen
>
<div>
<span>
<img
(error)=
"showDefaultIcon($event, instance.vendor)"
class=
"height-24"
[src]=
"providerMap[instance.vendor].icon"
>
</span>
</div>
<div
class=
"margin-top-5px"
>
<span>
{{'DISTRIBUTION.NAME' | translate}}:
</span>
<span
class=
"ml-1"
>
{{providerMap[instance.vendor].name}}
</span>
</div>
<div
class=
"margin-top-5px"
>
<span
class=
"no-wrapper"
>
<span>
{{'DISTRIBUTION.MAINTAINER' | translate}}:
</span>
<span
class=
"ml-1"
>
{{providerMap[instance.vendor].maintainers?.join(',')}}
</span>
</span>
</div>
<div
class=
"margin-top-5px"
>
<span>
{{'DISTRIBUTION.SOURCE' | translate}}:
</span>
<a
target=
"_blank"
href=
"{{providerMap[instance.vendor].source}}"
class=
"ml-1"
>
{{providerMap[instance.vendor].source}}
</a>
</div>
<div
class=
"margin-top-5px"
>
<span>
{{'DISTRIBUTION.VERSION' | translate}}:
</span>
<span
class=
"ml-1"
>
{{providerMap[instance.vendor].version}}
</span>
</div>
</clr-signpost-content>
</clr-signpost>
</clr-dg-cell>
<clr-dg-cell
[ngSwitch]=
"instance.status === 'Healthy'"
>
<span
*ngSwitchCase=
"true"
class=
"label label-success"
>
{{ instance.status }}
</span>
<span
*ngSwitchDefault
class=
"label label-danger"
>
{{ instance.status }}
</span>
</clr-dg-cell>
<clr-dg-cell>
{{ instance.enabled || false }}
</clr-dg-cell>
<clr-dg-cell>
{{ instance.auth_mode }}
</clr-dg-cell>
<clr-dg-cell>
{{fmtTime(instance.setup_timestamp) | date: 'short'}}
</clr-dg-cell>
<clr-dg-cell>
{{ instance.description }}
</clr-dg-cell>
</clr-dg-row>
<clr-dg-footer>
<clr-dg-pagination
#pagination
[clrDgPageSize]=
"pageSize"
[clrDgTotalItems]=
"totalCount"
[(clrDgPage)]=
"currentPage"
>
<span
*ngIf=
"pagination.totalItems"
>
{{ pagination.firstItem + 1 }} - {{ pagination.lastItem + 1 }}{{ 'HELM_CHART.OF' | translate }}
</span>
<span>
{{ pagination.totalItems }} {{ 'HELM_CHART.ITEMS' | translate }}
</span>
</clr-dg-pagination>
</clr-dg-footer>
</clr-datagrid>
</div>
</div>
</div>
<div>
<dist-setup-modal
(refresh)=
"refresh()"
[providers]=
"providers"
#setupModal
></dist-setup-modal>
</div>
src/portal/src/app/distribution/distribution-instances/distribution-instances.component.scss
0 → 100644
View file @
d01ff31d
@import
"../base.scss"
;
$refrsh-btn-color
:
#007CBB
;
.refresh-btn
{
@include
refresh-button
}
.refresh-btn
:hover
{
@include
refresh-button-hover
(
$refrsh-btn-color
);
}
.filter-pos
{
float
:
right
;
margin-right
:
24px
;
position
:
relative
;
top
:
10px
;
}
.action-head-pos
{
padding-right
:
18px
;
height
:
24px
;
display
:
flex
;
justify-content
:
flex-end
;
}
.no-wrapper
{
white-space
:
nowrap
;
}
.margin-top-5px
{
margin-top
:
5px
;
}
.height-24
{
height
:
24px
;
}
src/portal/src/app/distribution/distribution-instances/distribution-instances.component.spec.ts
0 → 100644
View file @
d01ff31d
import
{
async
,
ComponentFixture
,
TestBed
}
from
'
@angular/core/testing
'
;
import
{
TranslateModule
,
TranslateService
}
from
'
@ngx-translate/core
'
;
import
{
ClarityModule
}
from
'
@clr/angular
'
;
import
{
SharedModule
}
from
'
../../shared/shared.module
'
;
import
{
CUSTOM_ELEMENTS_SCHEMA
}
from
'
@angular/core
'
;
import
{
HttpClientTestingModule
}
from
'
@angular/common/http/testing
'
;
import
{
DistributionInstancesComponent
}
from
'
./distribution-instances.component
'
;
import
{
PreheatService
}
from
"
../../../../ng-swagger-gen/services/preheat.service
"
;
import
{
Instance
}
from
'
../../../../ng-swagger-gen/models/instance
'
;
import
{
HttpHeaders
,
HttpResponse
}
from
'
@angular/common/http
'
;
import
{
of
}
from
'
rxjs
'
;
import
{
delay
}
from
'
rxjs/operators
'
;
import
{
Metadata
}
from
'
../../../../ng-swagger-gen/models/metadata
'
;
import
{
DistributionSetupModalComponent
}
from
'
../distribution-setup-modal/distribution-setup-modal.component
'
;
describe
(
'
DistributionInstanceComponent
'
,
()
=>
{
let
component
:
DistributionInstancesComponent
;
let
fixture
:
ComponentFixture
<
DistributionInstancesComponent
>
;
const
instance1
:
Instance
=
{
name
:
'
Test1
'
,
default
:
true
,
enabled
:
true
,
description
:
'
Test1
'
,
endpoint
:
'
http://test.com
'
,
id
:
1
,
setup_timestamp
:
new
Date
().
getTime
(),
auth_mode
:
'
NONE
'
,
vendor
:
'
kraken
'
,
status
:
'
Healthy
'
};
const
instance2
:
Instance
=
{
name
:
'
Test2
'
,
default
:
false
,
enabled
:
false
,
description
:
'
Test2
'
,
endpoint
:
'
http://test2.com
'
,
id
:
2
,
setup_timestamp
:
new
Date
().
getTime
()
+
3600000
,
auth_mode
:
'
BASIC
'
,
auth_info
:
{
password
:
'
123
'
,
username
:
'
abc
'
},
vendor
:
'
kraken
'
,
status
:
'
Healthy
'
};
const
instance3
:
Instance
=
{
name
:
'
Test3
'
,
default
:
false
,
enabled
:
true
,
description
:
'
Test3
'
,
endpoint
:
'
http://test3.com
'
,
id
:
3
,
setup_timestamp
:
new
Date
().
getTime
()
+
7200000
,
auth_mode
:
'
OAUTH
'
,
auth_info
:
{
token
:
'
xxxxxxxxxxxxxxxxxxxx
'
},
vendor
:
'
kraken
'
,
status
:
'
Unhealthy
'
};
const
mockedProviders
:
Metadata
[]
=
[{
'
icon
'
:
'
https://raw.githubusercontent.com/alibaba/Dragonfly/master/docs/images/logo.png
'
,
'
id
'
:
'
dragonfly
'
,
'
maintainers
'
:
[
'
Jin Zhang/taiyun.zj@alibaba-inc.com
'
],
'
name
'
:
'
Dragonfly
'
,
'
source
'
:
'
https://github.com/alibaba/Dragonfly
'
,
'
version
'
:
'
0.10.1
'
},
{
'
icon
'
:
'
https://github.com/uber/kraken/blob/master/assets/kraken-logo-color.svg
'
,
'
id
'
:
'
kraken
'
,
'
maintainers
'
:
[
'
mmpei/peimingming@corp.netease.com
'
],
'
name
'
:
'
Kraken
'
,
'
source
'
:
'
https://github.com/uber/kraken
'
,
'
version
'
:
'
0.1.3
'
}];
const
fakedPreheatService
=
{
ListInstancesResponse
()
{
const
res
:
HttpResponse
<
Array
<
Instance
>>
=
new
HttpResponse
<
Array
<
Instance
>>
({
headers
:
new
HttpHeaders
({
'
x-total-count
'
:
'
3
'
}),
body
:
[
instance1
,
instance2
,
instance3
]
});
return
of
(
res
).
pipe
(
delay
(
10
));
},
ListProviders
()
{
return
of
(
mockedProviders
).
pipe
(
delay
(
10
));
}
};
beforeEach
(
async
(()
=>
{
TestBed
.
configureTestingModule
({
imports
:
[
ClarityModule
,
TranslateModule
,
SharedModule
,
HttpClientTestingModule
],
schemas
:
[
CUSTOM_ELEMENTS_SCHEMA
],
providers
:
[
{
provide
:
PreheatService
,
useValue
:
fakedPreheatService
}
],
declarations
:
[
DistributionInstancesComponent
,
DistributionSetupModalComponent
]
}).
compileComponents
();
}));
beforeEach
(()
=>
{
fixture
=
TestBed
.
createComponent
(
DistributionInstancesComponent
);
component
=
fixture
.
componentInstance
;
fixture
.
detectChanges
();
});
it
(
'
should create
'
,
()
=>
{
expect
(
component
).
toBeTruthy
();
});
it
(
'
should render list and get providers
'
,
async
()
=>
{
fixture
.
autoDetectChanges
(
true
);
await
fixture
.
whenStable
();
expect
(
component
.
providers
.
length
).
toEqual
(
2
);
const
rows
=
fixture
.
nativeElement
.
getElementsByTagName
(
'
clr-dg-row
'
);
expect
(
rows
.
length
).
toEqual
(
3
);
});
it
(
'
should open modal
'
,
async
()
=>
{
fixture
.
autoDetectChanges
(
true
);
await
fixture
.
whenStable
();
const
addButton
:
HTMLButtonElement
=
fixture
.
nativeElement
.
querySelector
(
"
#new-instance
"
);
addButton
.
click
();
await
fixture
.
whenStable
();
const
modal
:
HTMLElement
=
fixture
.
nativeElement
.
querySelector
(
"
clr-modal
"
);
expect
(
modal
).
toBeTruthy
();
});
});
src/portal/src/app/distribution/distribution-instances/distribution-instances.component.ts
0 → 100644
View file @
d01ff31d
import
{
MessageHandlerService
}
from
'
../../shared/message-handler/message-handler.service
'
;
import
{
Component
,
OnInit
,
ViewChild
,
OnDestroy
}
from
'
@angular/core
'
;
import
{
Subscription
,
Observable
,
forkJoin
,
throwError
as
observableThrowError
}
from
'
rxjs
'
;
import
{
DistributionSetupModalComponent
}
from
'
../distribution-setup-modal/distribution-setup-modal.component
'
;
import
{
OperationService
}
from
'
../../../lib/components/operation/operation.service
'
;
import
{
ConfirmationState
,
ConfirmationTargets
,
ConfirmationButtons
}
from
'
../../shared/shared.const
'
;
import
{
ConfirmationDialogService
}
from
'
../../shared/confirmation-dialog/confirmation-dialog.service
'
;
import
{
ConfirmationMessage
}
from
'
../../shared/confirmation-dialog/confirmation-message
'
;
import
{
operateChanges
,
OperateInfo
,
OperationState
}
from
'
../../../lib/components/operation/operate
'
;
import
{
TranslateService
}
from
'
@ngx-translate/core
'
;
import
{
map
,
catchError
,
finalize
}
from
'
rxjs/operators
'
;
import
{
errorHandler
}
from
'
../../../lib/utils/shared/shared.utils
'
;
import
{
clone
,
DEFAULT_PAGE_SIZE
}
from
'
../../../lib/utils/utils
'
;
import
{
Instance
}
from
"
../../../../ng-swagger-gen/models/instance
"
;
import
{
PreheatService
}
from
"
../../../../ng-swagger-gen/services/preheat.service
"
;
import
{
Metadata
}
from
'
../../../../ng-swagger-gen/models/metadata
'
;
interface
MultiOperateData
{
operation
:
string
;
instances
:
Instance
[];
}
const
DEFAULT_ICON
:
string
=
'
images/harbor-logo.svg
'
;
const
KRAKEN_ICON
:
string
=
'
images/kraken-logo-color.svg
'
;
const
ONE_THOUSAND
:
number
=
1000
;
const
KRAKEN
:
string
=
'
kraken
'
;
@
Component
({
selector
:
'
dist-instances
'
,
templateUrl
:
'
./distribution-instances.component.html
'
,
styleUrls
:
[
'
./distribution-instances.component.scss
'
]
})
export
class
DistributionInstancesComponent
implements
OnInit
,
OnDestroy
{
instances
:
Instance
[]
=
[];
selectedRow
:
Instance
[]
=
[];
pageSize
:
number
=
DEFAULT_PAGE_SIZE
;
currentPage
:
number
=
1
;
totalCount
:
number
=
0
;
queryString
:
string
;
chanSub
:
Subscription
;
private
loading
:
boolean
=
true
;
private
operationSubscription
:
Subscription
;
@
ViewChild
(
'
setupModal
'
,
{
static
:
false
})
setupModal
:
DistributionSetupModalComponent
;
providerMap
:
{[
key
:
string
]:
Metadata
}
=
{};
providers
:
Metadata
[]
=
[];
constructor
(
private
disService
:
PreheatService
,
private
msgHandler
:
MessageHandlerService
,
private
translate
:
TranslateService
,
private
operationDialogService
:
ConfirmationDialogService
,
private
operationService
:
OperationService
)
{
// subscribe operation
this
.
operationSubscription
=
operationDialogService
.
confirmationConfirm$
.
subscribe
(
confirmed
=>
{
if
(
confirmed
&&
confirmed
.
source
===
ConfirmationTargets
.
INSTANCE
&&
confirmed
.
state
===
ConfirmationState
.
CONFIRMED
)
{
this
.
operateInstance
(
confirmed
.
data
);
}
}
);
}
public
get
inProgress
():
boolean
{
return
this
.
loading
;
}
ngOnInit
()
{
this
.
loadData
();
this
.
getProviders
();
}
ngOnDestroy
()
{
if
(
this
.
operationSubscription
)
{
this
.
operationSubscription
.
unsubscribe
();
}
if
(
this
.
chanSub
)
{
this
.
chanSub
.
unsubscribe
();
}
}
getProviders
()
{
this
.
disService
.
ListProviders
().
subscribe
(
providers
=>
{
if
(
providers
&&
providers
.
length
)
{
this
.
providers
=
providers
;
providers
.
forEach
(
item
=>
{
this
.
providerMap
[
item
.
id
]
=
item
;
});
}
},
err
=>
this
.
msgHandler
.
error
(
err
)
);
}
loadData
()
{
this
.
selectedRow
=
[];
const
queryParam
:
PreheatService
.
ListInstancesParams
=
{
page
:
this
.
currentPage
,
pageSize
:
this
.
pageSize
};
if
(
this
.
queryString
)
{
queryParam
.
q
=
encodeURIComponent
(
`name=~
${
this
.
queryString
}
`
);
}
this
.
loading
=
true
;
this
.
disService
.
ListInstancesResponse
(
queryParam
)
.
pipe
(
finalize
(()
=>
this
.
loading
=
false
))
.
subscribe
(
response
=>
{
this
.
totalCount
=
Number
.
parseInt
(
response
.
headers
.
get
(
'
x-total-count
'
)
);
this
.
instances
=
response
.
body
as
Instance
[];
},
err
=>
this
.
msgHandler
.
error
(
err
)
);
}
refresh
()
{
this
.
queryString
=
null
;
this
.
currentPage
=
1
;
this
.
loadData
();
}
doFilter
(
$evt
:
any
)
{
this
.
currentPage
=
1
;
this
.
queryString
=
$evt
;
this
.
loadData
();
}
addInstance
()
{
this
.
setupModal
.
openSetupModal
(
false
);
}
editInstance
()
{
if
(
this
.
selectedRow
&&
this
.
selectedRow
.
length
===
1
)
{
this
.
setupModal
.
openSetupModal
(
true
,
clone
(
this
.
selectedRow
[
0
]));
}
}