diff --git a/src/app/appmarket/appinstance/appinstance/appinstance.component.css b/src/app/appmarket/appinstance/appinstance/appinstance.component.css index 8311dad14e566309867d9d2b11684a825a986f67..cb373c1ec56d1cb87377a31046f8a30e976b1da2 100644 --- a/src/app/appmarket/appinstance/appinstance/appinstance.component.css +++ b/src/app/appmarket/appinstance/appinstance/appinstance.component.css @@ -75,3 +75,7 @@ align-items: center; } +:host ::ng-deep .p-dropdown { + width: 200px; +} + diff --git a/src/app/appmarket/appinstance/appinstance/appinstance.component.html b/src/app/appmarket/appinstance/appinstance/appinstance.component.html index cf48f16ff1ca9395d589b490d3e503ed70eaab5b..fb4a7c6bbb737f776b57f9c780446cbeac8fa16a 100644 --- a/src/app/appmarket/appinstance/appinstance/appinstance.component.html +++ b/src/app/appmarket/appinstance/appinstance/appinstance.component.html @@ -21,27 +21,31 @@ {{app?.application.version ? 'v.' + app?.application.version : 'None'}} | <span pTooltip="{{'APPLICATIONS.TOOLTIP_MESSAGE_NOT_AVAILABLE' | translate}}" - tooltipPosition="bottom" [showDelay]="50" [tooltipDisabled]="!!app?.applicationBase.licenseUrl"> + tooltipPosition="bottom" [showDelay]="50" + [tooltipDisabled]="!!app?.applicationBase.licenseUrl"> <a class="{{app?.applicationBase.licenseUrl ? '' : 'disabled-url'}}" [href]="app?.applicationBase.licenseUrl" target="_blank">{{app?.applicationBase.license || 'License'}}</a> </span> | <span pTooltip="{{'APPLICATIONS.TOOLTIP_MESSAGE_NOT_AVAILABLE' | translate}}" - tooltipPosition="bottom" [showDelay]="50" [tooltipDisabled]="!!app?.applicationBase.wwwUrl"> + tooltipPosition="bottom" [showDelay]="50" + [tooltipDisabled]="!!app?.applicationBase.wwwUrl"> <a class="{{app?.applicationBase.wwwUrl ? '' : 'disabled-url'}}" [href]="app?.applicationBase.wwwUrl">WWW</a> </span> | <span pTooltip="{{'APPLICATIONS.TOOLTIP_MESSAGE_NOT_AVAILABLE' | translate}}" - tooltipPosition="bottom" [showDelay]="50" [tooltipDisabled]="!!app?.applicationBase.sourceUrl"> + tooltipPosition="bottom" [showDelay]="50" + [tooltipDisabled]="!!app?.applicationBase.sourceUrl"> <a class="{{app?.applicationBase.sourceUrl ? '' : 'disabled-url'}}" [href]="app?.applicationBase.sourceUrl" target="_blank">{{'APP_INSTANCE.SOURCE' | translate}}</a> </span> | <span pTooltip="{{'APPLICATIONS.TOOLTIP_MESSAGE_NOT_AVAILABLE' | translate}}" - tooltipPosition="bottom" [showDelay]="50" [tooltipDisabled]="!!app?.applicationBase.issuesUrl"> + tooltipPosition="bottom" [showDelay]="50" + [tooltipDisabled]="!!app?.applicationBase.issuesUrl"> <a class="{{app?.applicationBase.issuesUrl ? '' : 'disabled-url'}}" [href]="app?.applicationBase.issuesUrl" target="_blank">{{'APP_INSTANCE.ISSUES' | translate}}</a> @@ -135,6 +139,11 @@ {{'APP_INSTANCE.UPGRADE_BUTTON' | translate}} </a> </li> + <li *ngIf="appInstance.upgradePossible"> + <a role="button" (click)="this.openVersionUpdateModal()"> + {{'APP_INSTANCE.MANUAL_UPDATE.HEADER' | translate}} + </a> + </li> <li *ngIf="appInstance.autoUpgradesEnabled"> <a role="button" (click)="this.disableAutoUpgradesModal.show()"> {{'APP_INSTANCE.DISABLE_AUTO_UPGRADES_BUTTON' | translate}} @@ -151,6 +160,9 @@ <!-- if application deployment failed --> <div class="btn-group pull-right" *ngIf="getStateAsEnum(appInstanceStatus?.state) === AppInstanceState.FAILURE"> + <button class="btn btn-primary" + *roles="['ROLE_DOMAIN_ADMIN', 'ROLE_SYSTEM_ADMIN']" + (click)="openVersionUpdateModal()">{{'APP_INSTANCE.REDEPLOY_BUTTON' | translate}}</button> <button class="btn btn-primary" *roles="['ROLE_DOMAIN_ADMIN', 'ROLE_SYSTEM_ADMIN']" (click)="redeployConfirm.show()">{{'APP_INSTANCE.REDEPLOY_BUTTON' | translate}}</button> @@ -184,6 +196,28 @@ </div> </nmaas-modal> + <!-- Manual update version modal--> + <nmaas-modal styleModal="info" #manualUpdateModal> + <div class="nmaas-modal-header"> + <h4 style="text-align: center">{{'APP_INSTANCES.MANUAL_UPDATE.HEADER' | translate}}</h4> + </div> + <div class="nmaas-modal-body"> + <div class="form-group" style="height: 150px"> + <p>{{'APP_INSTANCES.MANUAL_UPDATE.BODY' | translate}}</p> + <div> + <p-dropdown [options]="appVersions" optionLabel="version" optionValue="version" placeholder="Select version" emptyMessage="No version available" + [disabled]="appVersions.length == 0" [(ngModel)]="selectedVersion"></p-dropdown> + </div> + </div> + </div> + <div class="nmaas-modal-footer"> + <button type="button" class="btn btn-primary " [disabled]="appVersions.length == 0" + (click)="this.manualUpdateVersion()">{{'APP_INSTANCES.MANUAL_UPDATE.YES_BUTTON' | translate}}</button> + <button type="button" class="btn btn-danger" + (click)="this.manualUpdateModal.hide()">{{'UNDEPLOY_MODAL.CANCEL_BUTTON' | translate}}</button> + </div> + </nmaas-modal> + <!-- Update config modal --> <nmaas-modal styleModal="info" #updateConfig> <div class="nmaas-modal-header"> diff --git a/src/app/appmarket/appinstance/appinstance/appinstance.component.ts b/src/app/appmarket/appinstance/appinstance/appinstance.component.ts index e9d78a7da5edd5e38e3296d6d6be768d88ca7e07..b8c9d081db3f35906b28bfc91bf3c3438f3aa86f 100644 --- a/src/app/appmarket/appinstance/appinstance/appinstance.component.ts +++ b/src/app/appmarket/appinstance/appinstance/appinstance.component.ts @@ -26,6 +26,8 @@ import {ApplicationDTO} from '../../../model/application-dto'; import {AddMembersModalComponent} from '../modals/add-members-modal/add-members-modal.component'; import {AuthService} from '../../../auth/auth.service'; import {SelectPodModalComponent} from '../modals/select-pod-modal/select-pod-modal.component'; +import {ApplicationVersion} from '../../../model/application-version'; +import * as semver from 'semver'; @Component({ selector: 'nmaas-appinstance', @@ -90,6 +92,9 @@ export class AppInstanceComponent implements OnInit, OnDestroy { @ViewChild('applyConfig') public applyConfig: ModalComponent; + @ViewChild('manualUpdateModal') + public manualUpdateModal: ModalComponent; + app: ApplicationDTO; @@ -121,6 +126,9 @@ export class AppInstanceComponent implements OnInit, OnDestroy { public podNames: PodInfo[] = []; + public appVersions: ApplicationVersion[] = []; + public selectedVersion = ''; + constructor(private appsService: AppsService, public appImagesService: AppImagesService, private appInstanceService: AppInstanceService, @@ -575,4 +583,30 @@ export class AppInstanceComponent implements OnInit, OnDestroy { return outputString; } + public appVersionCompare(a: ApplicationVersion, b: ApplicationVersion): number { + // defaults version that cannot be parsed to `0.0.0` + return semver.compare(semver.coerce(a.version) || '0.0.0', semver.coerce(b.version) || '0.0.0') + } + + public openVersionUpdateModal() { + this.appsService.getApplicationVersions(this.appInstance.application.applicationBase.id).subscribe( versions => { + this.appVersions = versions; + this.appVersions.sort(this.appVersionCompare) + const appVer = new ApplicationVersion() + appVer.version = this.appInstance.applicationVersion + this.appVersions = this.appVersions.filter(val => { + return this.appVersionCompare(val, appVer) === 1; + }) + }) + this.manualUpdateModal.show(); + } + + public manualUpdateVersion() { + this.appInstanceService.manualUpdateVersion(this.appInstanceId, this.selectedVersion).subscribe( next => { + console.debug("manualy updated version"); + }) + this.manualUpdateModal.hide(); + } + + } diff --git a/src/app/service/appinstance.service.ts b/src/app/service/appinstance.service.ts index fe51536b3d6fe0c4d29f250ed6fd0f2d4651e014..87370e63efd6054143b7bc25cd1ed8ef9cd3cd7c 100644 --- a/src/app/service/appinstance.service.ts +++ b/src/app/service/appinstance.service.ts @@ -143,6 +143,10 @@ export class AppInstanceService extends GenericDataService { return this.http.get(this.getUrl() + 'statistics') } + public manualUpdateVersion(appInstanceId: number, version: string): Observable<void> { + return this.http.post<void>(this.getUrl() + `${appInstanceId}/version/${version}`, appInstanceId) + } + } export class CustomerSearchCriteria { diff --git a/src/app/service/apps.service.ts b/src/app/service/apps.service.ts index 09b522431539de68fa5b1764d87039ddad57151d..32e0d701731e391f574456a6cb25ba3113f1a5c3 100644 --- a/src/app/service/apps.service.ts +++ b/src/app/service/apps.service.ts @@ -10,6 +10,7 @@ import {AppStateChange} from '../model/appstatechange'; import {ApplicationBase} from '../model/application-base'; import {Application} from '../model/application'; import {ApplicationDTO} from '../model/application-dto'; +import {ApplicationVersion} from '../model/application-version'; @Injectable({ providedIn: 'root', @@ -38,6 +39,12 @@ export class AppsService extends GenericDataService { return this.patch(this.appConfig.getApiUrl() + '/apps/base', app); } + // application version + + public getApplicationVersions(id: number): Observable<ApplicationVersion[]> { + return this.get<ApplicationVersion[]>(this.appConfig.getApiUrl() + `/apps/versions/${id}`) + } + // application dto public getApplicationDTO(id: number): Observable<ApplicationDTO> {