ecosystem/application-properties/application-properties.component.ts
| selector | c8y-application-properties |
| imports |
TooltipDirective
C8yTranslatePipe
HumanizeAppNamePipe
|
| templateUrl | ./application-properties.component.html |
TitleComponent
BreadcrumbComponent
BreadcrumbItemComponent
NgClass
FormsModule
ReactiveFormsModule
AppIconComponent
IconDirective
InputGroupEditableComponent
C8yTranslateDirective
TooltipDirective
PropertiesListComponent
FormGroupComponent
RequiredInputPlaceholderDirective
MessagesComponent
MessageDirective
IconSelectorWrapperComponent
UploadArchiveComponent
LoadingComponent
ActivityLogComponent
C8yTranslatePipe
AsyncPipe
HumanizeAppNamePipe
DatePipe
OnInit
<c8y-title>{{ application | humanizeAppName | async }}</c8y-title>
@if (!isMicroservice) {
<c8y-breadcrumb>
<c8y-breadcrumb-item
[icon]="'c8y-atom'"
[label]="'Ecosystem' | translate"
></c8y-breadcrumb-item>
<c8y-breadcrumb-item
[icon]="'c8y-modules'"
[label]="'Applications' | translate"
[path]="'ecosystem/application/applications'"
></c8y-breadcrumb-item>
@if (isFeature) {
<c8y-breadcrumb-item
[icon]="breadcrumbConfig?.icon"
[label]="breadcrumbConfig?.label"
[path]="breadcrumbConfig?.path"
></c8y-breadcrumb-item>
}
<c8y-breadcrumb-item [label]="application | humanizeAppName | async"></c8y-breadcrumb-item>
<c8y-breadcrumb-item [label]="'Properties' | translate"></c8y-breadcrumb-item>
</c8y-breadcrumb>
}
@if (isMicroservice) {
<c8y-breadcrumb>
<c8y-breadcrumb-item
[icon]="'c8y-atom'"
[label]="'Ecosystem' | translate"
></c8y-breadcrumb-item>
<c8y-breadcrumb-item
[icon]="breadcrumbConfig?.icon"
[label]="breadcrumbConfig?.label"
[path]="breadcrumbConfig?.path"
></c8y-breadcrumb-item>
<c8y-breadcrumb-item [label]="application | humanizeAppName | async"></c8y-breadcrumb-item>
<c8y-breadcrumb-item [label]="'Properties' | translate"></c8y-breadcrumb-item>
</c8y-breadcrumb>
}
<div class="row">
<div [ngClass]="{ 'col-md-8': !isActivityLogSupported, 'col-md-12': isActivityLogSupported }">
@if (application) {
<div
class="card content-fullpage"
[ngClass]="{ 'd-grid grid__col--7-5--md': isActivityLogSupported }"
>
<form
class="d-flex d-col content-fullpage"
(ngSubmit)="formGroup.valid && save(formGroup.value)"
[formGroup]="formGroup"
novalidate
>
@if (!isLoading) {
<div class="d-contents">
<div class="card-block separator-bottom large-padding flex-no-shrink">
<div class="d-flex-md a-i-start text-center text-left-md">
@if (!isPackage && !isFeature && !isMicroservice && !isExternal) {
<c8y-app-icon
class="icon-48"
[app]="application"
[contextPath]="application.contextPath"
[name]="application.name"
></c8y-app-icon>
}
@if (isPackage) {
<i
class="icon-48"
c8yIcon="big-parcel"
></i>
}
@if (isFeature) {
<i
class="icon-48"
c8yIcon="tab"
></i>
}
@if (isMicroservice) {
<i
class="icon-48"
c8yIcon="microchip"
></i>
}
@if (isExternal) {
<i
class="icon-48"
c8yIcon="globe1"
></i>
}
<div class="p-t-md-16 p-l-md-16 p-r-md-32 flex-grow">
<p class="h4 text-medium m-b-8">{{ application | humanizeAppName | async }}</p>
@if (!isOwner) {
<p>
<em class="text-muted">
{{
formGroup?.controls?.description?.value ||
(noDescriptionLabel | translate)
}}
</em>
</p>
}
@if (isOwner) {
<div class="d-flex gap-8">
<c8y-input-group-editable
title="{{ 'Description' | translate }}"
[multiline]="true"
maxHeight="120px"
[noSaveButton]="true"
[ariaLabel]="'Description' | translate"
[placeholder]="noDescriptionLabel | translate"
formControlName="description"
></c8y-input-group-editable>
@if (
!formGroup.controls.description.value &&
application?.manifest?.description
) {
<button
class="btn btn-default"
[attr.aria-label]="'Restore description from manifest' | translate"
[tooltip]="'Restore description from manifest' | translate"
placement="top"
type="button"
[delay]="300"
(click)="restoreManifestDescription()"
>
<i [c8yIcon]="'restore'"></i>
</button>
}
</div>
}
</div>
<div class="text-right-md m-t-4 flex-no-shrink">
<span
class="label"
[ngClass]="appState?.class"
>
{{ appState?.label | translate }}
</span>
@if (application.manifest?.version) {
<div
class="fit-w m-t-2"
data-cy="application-detail--version"
>
<label
class="text-label-small"
translate
>
Version:
</label>
<small class="p-l-4 text-bold">{{ application.manifest?.version }}</small>
</div>
}
@if (!isUnpacked) {
<div class="fit-w m-t-2">
<label
class="text-label-small"
translate
>
Creation time:
</label>
<small class="p-l-4 text-bold">
{{ (binaryMo?.creationTime | c8yDate) || '---' }}
</small>
</div>
}
<div class="m-t-8">
@if (isUpdateAvailable) {
<button
class="btn btn-default btn-sm"
[attr.aria-label]="
'There\'s a newer version available, click to update' | translate
"
tooltip="{{
'There\'s a newer version available, click to update' | translate
}}"
placement="top"
type="button"
(click)="updateToLatestVersion()"
[delay]="300"
>
<i [c8yIcon]="'installing-updates'"></i>
{{ 'Update available' | translate }}
</button>
}
@if (canOpenInBrowser) {
<button
class="btn btn-default btn-sm"
title="{{ 'Open' | translate }}"
type="button"
(click)="openApp(application)"
[disabled]="disableOpenInBrowser"
>
<i [c8yIcon]="'external-link'"></i>
{{ 'Open' | translate }}
</button>
}
@if (canOpenInBrowser && disableOpenInBrowser) {
<div>
<small
class="text-muted"
translate
>
The application is overwritten by a custom application sharing the same
path
</small>
</div>
}
@if (isCustomMicroservice) {
<span>
@if (!isSubscribed) {
<button
class="btn btn-default btn-sm"
title="{{ 'Subscribe' | translate }}"
type="button"
(click)="subscribe()"
>
<i [c8yIcon]="'check-circle-o'"></i>
{{ 'Subscribe' | translate }}
</button>
}
@if (isSubscribed) {
<button
class="btn btn-default btn-sm"
title="{{ 'Unsubscribe' | translate }}"
type="button"
(click)="unsubscribe()"
>
<i [c8yIcon]="'minus-circle'"></i>
{{ 'Unsubscribe' | translate }}
</button>
}
</span>
}
</div>
</div>
</div>
</div>
<div class="inner-scroll bg-level-0 flex-grow">
<div class="card-block large-padding">
@if (isPackage) {
<div class="row p-16">
<c8y-properties-list
icon="info"
[title]="'Package details' | translate"
[data]="application.manifest"
[properties]="packageProperties"
[emptyLabel]="'---'"
></c8y-properties-list>
</div>
}
@if (sourcePackage) {
<div class="row p-16">
<c8y-properties-list
icon="info"
[title]="'Source package information' | translate"
[data]="sourcePackage.manifest"
[properties]="packageProperties"
[emptyLabel]="'---'"
></c8y-properties-list>
</div>
}
<div class="row">
<div class="col-sm-5">
<c8y-form-group>
<label for="appId">ID</label>
<input
class="form-control"
id="appId"
name="id"
type="text"
autocomplete="off"
[readonly]="true"
formControlName="id"
/>
</c8y-form-group>
</div>
<div class="col-sm-7">
<c8y-form-group>
<label>{{ 'Name' | translate }}</label>
<input
class="form-control"
placeholder="{{ 'e.g. My application' | translate }}"
name="name"
type="text"
required
[readonly]="!isOwner"
formControlName="name"
/>
</c8y-form-group>
</div>
</div>
<div class="row">
<div class="col-sm-5">
<c8y-form-group>
<label>{{ 'Application key' | translate }}</label>
<input
class="form-control"
placeholder="{{ 'e.g. my-application-key' | translate }}"
name="key"
type="text"
required
[readonly]="application.id || !isOwner"
formControlName="key"
/>
</c8y-form-group>
</div>
<div
class="col-sm-7"
data-cy="application-detail--type"
>
<c8y-form-group>
<label>{{ 'Type' | translate }}</label>
<div>
@if (application.id) {
<p class="form-control-static">
<i [c8yIcon]="iconMap[application.type]"></i>
<span>
{{ application.type | translate }}
</span>
</p>
}
</div>
</c8y-form-group>
</div>
</div>
@switch (application.type) {
@case ('HOSTED') {
<c8y-form-group>
<label>{{ 'Path' | translate }}</label>
<div class="input-group">
<span class="input-group-addon text-nowrap">/apps/</span>
<input
class="form-control"
placeholder="{{ 'e.g. my-application`used in URL`' | translate }}"
name="contextPath"
type="text"
required
[readOnly]="application.id || !isOwner"
formControlName="contextPath"
/>
</div>
</c8y-form-group>
}
@case ('MICROSERVICE') {
<c8y-form-group>
<label>{{ 'Path' | translate }}</label>
<div class="input-group">
<span class="input-group-addon">/service/</span>
<input
class="form-control"
placeholder="{{ 'e.g. my-microservice`used in URL`' | translate }}"
name="contextPath"
type="text"
required
[readOnly]="application.id || !isOwner"
formControlName="contextPath"
/>
</div>
</c8y-form-group>
<div class="row">
@if (application.manifest.version) {
<div
class="col-sm-4 m-b-16 flex-auto"
data-cy="application-detail--version"
>
<label>{{ 'Version' | translate }}</label>
<p class="form-control-static">
{{ application.manifest.version }}
</p>
</div>
}
@if (application.manifest.isolation) {
<div
class="col-sm-4 m-b-16 flex-auto"
data-cy="application-detail--isolation"
>
<label>{{ 'Isolation' | translate }}</label>
<p class="form-control-static">
@if (singleTenant) {
<span>
<i
class="c8y-icon-duocolor h4"
[c8yIcon]="'c8y-enterprise'"
></i>
{{ 'Single tenant' | translate }}
</span>
}
@if (!singleTenant) {
<span>
<i
class="c8y-icon-duocolor icon-32"
[c8yIcon]="'c8y-sub-tenants'"
></i>
{{ 'Multi tenant' | translate }}
</span>
}
</p>
</div>
}
@if (application.manifest.isolation) {
<div
class="col-sm-4 m-b-16 flex-auto"
data-cy="application-detail--billing-mode"
>
<label>{{ 'Billing mode' | translate }}</label>
<p class="form-control-static">
@if (subscription) {
<span [tooltip]="'Resources usage assigned to: Owner' | translate">
{{ 'Subscription' | translate }}
</span>
}
@if (!subscription && singleTenant) {
<span
[tooltip]="'Resources usage assigned to: Subscriber | translate'"
>
{{ 'Resources' | translate }}
</span>
}
@if (!subscription && !singleTenant) {
<span [tooltip]="'Resources usage assigned to: Owner' | translate">
{{ 'Resources' | translate }}
</span>
}
</p>
</div>
}
</div>
@if (application.manifest.provider) {
<div class="legend form-block m-t-40">
{{ 'Provider' | translate }}
</div>
}
@if (application.manifest.provider) {
<div
class="list-inline"
data-cy="application-detail--provider"
>
@if (application.manifest.provider.name) {
<div>
<div class="col-sm-4 m-b-16">
<label>{{ 'Name' | translate }}</label>
<p class="form-control-static">
{{ application.manifest.provider.name }}
</p>
</div>
</div>
}
@if (application.manifest.provider.domain) {
<div>
<div class="col-sm-4 m-b-16">
<label>{{ 'Domain' | translate }}</label>
<p class="form-control-static">
{{ application.manifest.provider.domain }}
</p>
</div>
</div>
}
@if (application.manifest.provider.support) {
<div>
<div class="col-sm-4 m-b-16">
<label>{{ 'Support' | translate }}</label>
<p class="form-control-static">
{{ application.manifest.provider.support }}
</p>
</div>
</div>
}
</div>
}
}
@case ('EXTERNAL') {
<c8y-form-group>
<label>{{ 'External URL' | translate }}</label>
<input
class="form-control"
placeholder="{{ 'e.g.' | translate }} http://www.example.com/"
name="externalUrl"
type="url"
required
[pattern]="'^(?!javascript:).+'"
[readOnly]="!isOwner"
formControlName="externalUrl"
/>
<c8y-messages>
<c8y-message
[name]="'pattern'"
[text]="'Valid URL required.' | translate"
></c8y-message>
</c8y-messages>
</c8y-form-group>
}
}
@if (isOwner && !isCustomMicroservice) {
<div class="d-col">
<label>{{ 'Select icon' | translate }}</label>
<c8y-icon-selector-wrapper
class="d-inline-flex"
name="icon"
formControlName="icon"
></c8y-icon-selector-wrapper>
</div>
}
</div>
</div>
</div>
}
@if (isCustomMicroservice && !isLoading) {
<div class="d-contents">
<c8y-upload-archive
[(application)]="application"
(refresh)="onNewArchive()"
></c8y-upload-archive>
</div>
}
@if (application && !!isOwner && hasAdminPermissions) {
<div class="card-footer separator">
<button
class="btn btn-default"
title="{{ 'Cancel' | translate }}"
type="button"
(click)="cancel()"
>
{{ 'Cancel' | translate }}
</button>
@if (canDelete) {
<button
class="btn btn-danger"
title="{{ 'Delete' | translate }}"
type="button"
(click)="delete()"
>
{{ 'Delete' | translate }}
</button>
}
<button
class="btn btn-primary btn-form"
title="{{ 'Save' | translate }}"
type="submit"
[disabled]="!application.type || formGroup.invalid || formGroup.pristine"
>
{{ 'Save' | translate }}
</button>
</div>
}
</form>
@if (isActivityLogSupported) {
<div class="content-fullpage d-flex d-col bg-level-1">
<div class="card-header separator">
<div
class="card-title"
translate
>
Activity log
</div>
<div class="m-l-auto">
<button
class="btn btn-link btn-sm"
title="{{ 'Reload' | translate }}"
type="button"
(click)="load()"
>
<i
c8yIcon="refresh"
[ngClass]="{ 'icon-spin': isLoading }"
></i>
{{ 'Reload' | translate }}
</button>
</div>
</div>
@if (isLoading) {
<div class="p-16 text-center">
<c8y-loading></c8y-loading>
</div>
}
@if (!isLoading) {
<c8y-activity-log
class="d-contents"
[hasAdminPermissions]="hasAdminPermissions"
[application]="application"
></c8y-activity-log>
}
</div>
}
</div>
}
</div>
</div>