Merge pull request #14011 from deaflynx/update-vc-syntax-appearance

Version control: fixed multiple identical requests, update template style
This commit is contained in:
Igor Kulikov 2025-09-25 16:48:37 +03:00 committed by GitHub
commit f66ea51218
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 338 additions and 326 deletions

View File

@ -15,76 +15,79 @@
limitations under the License. limitations under the License.
--> -->
<section *ngIf="!versionCreateResult$" class="flex flex-col" style="height: 100%;"> @if (!versionCreateResult$) {
<mat-toolbar> <section class="flex flex-col" style="height: 100%;">
<h2>{{ 'version-control.create-entities-version' | translate }}</h2> <mat-toolbar>
<span class="flex-1"></span> <h2>{{ 'version-control.create-entities-version' | translate }}</h2>
</mat-toolbar> <span class="flex-1"></span>
<mat-progress-bar color="warn" style="z-index: 10; width: 100%; margin-bottom: -4px;" mode="indeterminate" </mat-toolbar>
*ngIf="isLoading$ | async"> <mat-progress-bar color="warn" style="z-index: 10; width: 100%; margin-bottom: -4px;" mode="indeterminate"
</mat-progress-bar> [class.hidden]="(isLoading$ | async) === false">
<form [formGroup]="createVersionFormGroup" class="flex flex-col" style="flex: 1; padding-top: 16px; overflow: auto;"> </mat-progress-bar>
<div class="flex flex-col gt-sm:flex-row gt-sm:gap-2"> <form [formGroup]="createVersionFormGroup" class="flex flex-col" style="flex: 1; padding-top: 16px; overflow: auto;">
<tb-branch-autocomplete <div class="flex flex-col gt-sm:flex-row gt-sm:gap-2">
class="flex-1" <tb-branch-autocomplete
required class="flex-1"
formControlName="branch"> appearance="outline"
</tb-branch-autocomplete> required
<mat-form-field class="mat-block flex-1"> formControlName="branch">
<mat-label translate>version-control.version-name</mat-label> </tb-branch-autocomplete>
<input required matInput formControlName="versionName"> <mat-form-field class="mat-block flex-1" appearance="outline">
<mat-error *ngIf="createVersionFormGroup.get('versionName').hasError('required') || <mat-label translate>version-control.version-name</mat-label>
createVersionFormGroup.get('versionName').hasError('pattern')"> <input required matInput formControlName="versionName">
{{ 'version-control.version-name-required' | translate }} <mat-error [class.hidden]="!(createVersionFormGroup.get('versionName').hasError('required') ||
</mat-error> createVersionFormGroup.get('versionName').hasError('pattern'))">
{{ 'version-control.version-name-required' | translate }}
</mat-error>
</mat-form-field>
</div>
<mat-form-field class="mat-block" style="margin-bottom: 24px;" appearance="outline">
<mat-label translate>version-control.default-sync-strategy</mat-label>
<mat-select required formControlName="syncStrategy">
@for (strategy of syncStrategies; track strategy) {
<mat-option [value]="strategy">
{{syncStrategyTranslations.get(strategy) | translate}}
</mat-option>
}
</mat-select>
<mat-hint [innerHTML]="(syncStrategyHints.get(createVersionFormGroup.get('syncStrategy').value) | translate) | safe:'html'"></mat-hint>
</mat-form-field> </mat-form-field>
<tb-entity-types-version-create
formControlName="entityTypes">
</tb-entity-types-version-create>
</form>
<div class="flex items-center justify-end gap-2" style="padding-top: 16px;">
<button mat-button color="primary"
type="button"
[disabled]="(isLoading$ | async)"
(click)="cancel()" cdkFocusInitial>
{{ 'action.cancel' | translate }}
</button>
<button mat-raised-button color="primary"
type="button"
(click)="export()"
[disabled]="(isLoading$ | async) || createVersionFormGroup.invalid || !createVersionFormGroup.dirty">
{{ 'action.create' | translate }}
</button>
</div> </div>
<mat-form-field class="mat-block" style="margin-bottom: 24px;">
<mat-label translate>version-control.default-sync-strategy</mat-label>
<mat-select required formControlName="syncStrategy">
<mat-option *ngFor="let strategy of syncStrategies" [value]="strategy">
{{syncStrategyTranslations.get(strategy) | translate}}
</mat-option>
</mat-select>
<mat-hint [innerHTML]="(syncStrategyHints.get(createVersionFormGroup.get('syncStrategy').value) | translate) | safe:'html'"></mat-hint>
</mat-form-field>
<tb-entity-types-version-create
formControlName="entityTypes">
</tb-entity-types-version-create>
</form>
<div class="flex items-center justify-end gap-2" style="padding-top: 16px;">
<button mat-button color="primary"
type="button"
[disabled]="(isLoading$ | async)"
(click)="cancel()" cdkFocusInitial>
{{ 'action.cancel' | translate }}
</button>
<button mat-raised-button color="primary"
type="button"
(click)="export()"
[disabled]="(isLoading$ | async) || createVersionFormGroup.invalid || !createVersionFormGroup.dirty">
{{ 'action.create' | translate }}
</button>
</div>
</section>
<section *ngIf="versionCreateResult$">
<section *ngIf="resultMessage">
<div class="mat-headline-6 vc-result-message" [innerHtml]="resultMessage"></div>
</section> </section>
<div *ngIf="(versionCreateResult$ | async)?.done || hasError; else progress" class="flex items-center justify-end gap-2"> } @else {
<button mat-button color="primary" <div class="mat-headline-6 vc-result-message" [class.hidden]="!resultMessage" [innerHtml]="resultMessage"></div>
type="button" @if ((versionCreateResult$ | async)?.done || hasError) {
[disabled]="(isLoading$ | async)" <div class="flex items-center justify-end gap-2">
(click)="cancel()" cdkFocusInitial> <button mat-button color="primary"
{{ 'action.close' | translate }} type="button"
</button> [disabled]="(isLoading$ | async)"
</div> (click)="cancel()" cdkFocusInitial>
<ng-template #progress> {{ 'action.close' | translate }}
</button>
</div>
} @else {
<section class="flex flex-col items-center justify-center"> <section class="flex flex-col items-center justify-center">
<div class="mat-headline-6 vc-result-message progress"> <div class="mat-headline-6 vc-result-message progress">
<span translate>version-control.creating-version</span> <span translate>version-control.creating-version</span>
<mat-progress-bar mode="indeterminate"></mat-progress-bar> <mat-progress-bar mode="indeterminate"></mat-progress-bar>
</div> </div>
</section> </section>
</ng-template> }
</section> }

View File

@ -15,59 +15,63 @@
limitations under the License. limitations under the License.
--> -->
<section *ngIf="!versionLoadResult$" class="flex flex-col" style="height: 100%;"> @if (!versionLoadResult$) {
<mat-toolbar> <section class="flex flex-col" style="height: 100%;">
<h2>{{ 'version-control.restore-entities-from-version' | translate: {versionName} }}</h2> <mat-toolbar>
<span class="flex-1"></span> <h2>{{ 'version-control.restore-entities-from-version' | translate: {versionName} }}</h2>
</mat-toolbar> <span class="flex-1"></span>
<mat-progress-bar color="warn" style="z-index: 10; width: 100%; margin-bottom: -4px;" mode="indeterminate" </mat-toolbar>
*ngIf="isLoading$ | async"> <mat-progress-bar color="warn" style="z-index: 10; width: 100%; margin-bottom: -4px;" mode="indeterminate"
</mat-progress-bar> [class.hidden]="(isLoading$ | async) === false">
<form [formGroup]="loadVersionFormGroup" class="flex flex-col" style="flex: 1; padding: 16px 0; overflow-y: auto; overflow-x: hidden"> </mat-progress-bar>
<tb-entity-types-version-load <form [formGroup]="loadVersionFormGroup" class="flex flex-col" style="flex: 1; padding: 16px 0; overflow-y: auto; overflow-x: hidden">
formControlName="entityTypes"> <tb-entity-types-version-load
</tb-entity-types-version-load> formControlName="entityTypes">
</form> </tb-entity-types-version-load>
<div tb-hint-tooltip-icon="{{ 'version-control.rollback-on-error-hint' | translate }}" [formGroup]="loadVersionFormGroup"> </form>
<mat-slide-toggle formControlName="rollbackOnError"> <div tb-hint-tooltip-icon="{{ 'version-control.rollback-on-error-hint' | translate }}" [formGroup]="loadVersionFormGroup">
{{ 'version-control.rollback-on-error' | translate }} <mat-slide-toggle formControlName="rollbackOnError">
</mat-slide-toggle> {{ 'version-control.rollback-on-error' | translate }}
</div> </mat-slide-toggle>
<div class="flex items-center justify-end gap-2" style="padding-top: 16px;"> </div>
<button mat-button color="primary" <div class="flex items-center justify-end gap-2" style="padding-top: 16px;">
type="button" <button mat-button color="primary"
[disabled]="(isLoading$ | async)" type="button"
(click)="cancel()" cdkFocusInitial> [disabled]="(isLoading$ | async)"
{{ 'action.cancel' | translate }} (click)="cancel()" cdkFocusInitial>
</button> {{ 'action.cancel' | translate }}
<button mat-raised-button color="primary" </button>
type="button" <button mat-raised-button color="primary"
(click)="restore()" type="button"
[disabled]="(isLoading$ | async) || loadVersionFormGroup.invalid"> (click)="restore()"
{{ 'action.restore' | translate }} [disabled]="(isLoading$ | async) || loadVersionFormGroup.invalid">
</button> {{ 'action.restore' | translate }}
</div> </button>
</section> </div>
<section *ngIf="versionLoadResult$"> </section>
<div *ngIf="(versionLoadResult$ | async)?.done && !entityTypeLoadResults?.length && !errorMessage" class="mat-headline-6 vc-result-message"> } @else {
<div [class.hidden]="!((versionLoadResult$ | async)?.done && !entityTypeLoadResults?.length && !errorMessage)" class="mat-headline-6 vc-result-message">
{{ 'version-control.no-entities-restored' | translate }} {{ 'version-control.no-entities-restored' | translate }}
</div> </div>
<div *ngIf="errorMessage" class="mat-headline-6 vc-result-message error" [innerHTML]="errorMessage"></div> <div [class.hidden]="!errorMessage" class="mat-headline-6 vc-result-message error" [innerHTML]="errorMessage"></div>
<div *ngFor="let entityTypeLoadResult of entityTypeLoadResults" class="mat-headline-6 vc-result-message">{{ entityTypeLoadResultMessage(entityTypeLoadResult) }}</div> @for (entityTypeLoadResult of entityTypeLoadResults; track entityTypeLoadResult.entityType) {
<div *ngIf="(versionLoadResult$ | async)?.done || hasError; else progress" class="flex items-center justify-end gap-2"> <div class="mat-headline-6 vc-result-message">{{ entityTypeLoadResultMessage(entityTypeLoadResult) }}</div>
<button mat-button color="primary" }
type="button" @if ((versionLoadResult$ | async)?.done || hasError) {
[disabled]="(isLoading$ | async)" <div class="flex items-center justify-end gap-2">
(click)="cancel()" cdkFocusInitial> <button mat-button color="primary"
{{ 'action.close' | translate }} type="button"
</button> [disabled]="(isLoading$ | async)"
</div> (click)="cancel()" cdkFocusInitial>
<ng-template #progress> {{ 'action.close' | translate }}
</button>
</div>
} @else {
<section class="flex flex-col items-center justify-center"> <section class="flex flex-col items-center justify-center">
<div class="mat-headline-6 vc-result-message progress"> <div class="mat-headline-6 vc-result-message progress">
<span translate>version-control.restoring-entities-from-version</span> <span translate>version-control.restoring-entities-from-version</span>
<mat-progress-bar mode="indeterminate"></mat-progress-bar> <mat-progress-bar mode="indeterminate"></mat-progress-bar>
</div> </div>
</section> </section>
</ng-template> }
</section> }

View File

@ -18,86 +18,90 @@
<fieldset [formGroup]="entityTypesVersionCreateFormGroup" class="fields-group flex flex-col"> <fieldset [formGroup]="entityTypesVersionCreateFormGroup" class="fields-group flex flex-col">
<legend class="group-title" translate>version-control.entities-to-export</legend> <legend class="group-title" translate>version-control.entities-to-export</legend>
<div class="flex flex-col" style="flex: 1; overflow: auto;"> <div class="flex flex-col" style="flex: 1; overflow: auto;">
<div *ngFor="let entityTypeFormGroup of entityTypesFormGroupArray(); trackBy: trackByEntityType; @for (entityTypeFormGroup of entityTypesFormGroupArray(); track entityTypeFormGroup; let index = $index, isLast = $last) {
let $index = index; last as isLast;" <div class="flex flex-row items-center justify-start" [class.pb-2]="!isLast">
class="flex flex-row items-center justify-start" [class.pb-2]="!isLast"> <mat-expansion-panel class="entity-type-config flex-1" [class.load]="loading" [formGroup]="entityTypeFormGroup"
<mat-expansion-panel class="entity-type-config flex-1" [class.load]="loading" [formGroup]="entityTypeFormGroup" [expanded]="entityTypesFormGroupExpanded(entityTypeFormGroup)" (opened)="loading = false">
[expanded]="entityTypesFormGroupExpanded(entityTypeFormGroup)" (opened)="loading = false"> <mat-expansion-panel-header>
<mat-expansion-panel-header> <div class="flex flex-1 flex-row items-center justify-start">
<div class="flex flex-1 flex-row items-center justify-start"> <mat-panel-title>
<mat-panel-title> <div class="flex flex-1 flex-row items-center justify-start">
<div class="flex flex-1 flex-row items-center justify-start"> <div>{{ entityTypeText(entityTypeFormGroup) }}</div>
<div>{{ entityTypeText(entityTypeFormGroup) }}</div> </div>
</div> </mat-panel-title>
</mat-panel-title> <span class="flex-1"></span>
<span class="flex-1"></span> <button [class.hidden]="disabled" mat-icon-button style="min-width: 40px;"
<button *ngIf="!disabled" mat-icon-button style="min-width: 40px;" type="button"
type="button" (click)="removeEntityType(index)"
(click)="removeEntityType($index)" matTooltip="{{ 'action.remove' | translate }}"
matTooltip="{{ 'action.remove' | translate }}" matTooltipPosition="above">
matTooltipPosition="above"> <mat-icon>delete</mat-icon>
<mat-icon>delete</mat-icon> </button>
</button> </div>
</div> </mat-expansion-panel-header>
</mat-expansion-panel-header> <div class="entity-type-config-content flex flex-col gap-2">
<div class="entity-type-config-content flex flex-col gap-2"> <mat-divider></mat-divider>
<mat-divider></mat-divider> <div class="flex flex-row xs:flex-col gt-xs:gap-4">
<div class="flex flex-row xs:flex-col gt-xs:gap-4"> <tb-entity-type-select
<tb-entity-type-select showLabel
showLabel formControlName="entityType"
formControlName="entityType" appearance="outline"
required required
[filterAllowedEntityTypes]="false" [filterAllowedEntityTypes]="false"
[allowedEntityTypes]="allowedEntityTypes(entityTypeFormGroup)"> [allowedEntityTypes]="allowedEntityTypes(entityTypeFormGroup)">
</tb-entity-type-select> </tb-entity-type-select>
<div class="flex flex-1 flex-row xs:flex-col gt-xs:gap-4" formGroupName="config"> <div class="flex flex-1 flex-row xs:flex-col gt-xs:gap-4" formGroupName="config">
<mat-form-field class="mat-block flex-1"> <mat-form-field class="mat-block flex-1" appearance="outline">
<mat-label translate>version-control.sync-strategy</mat-label> <mat-label translate>version-control.sync-strategy</mat-label>
<mat-select formControlName="syncStrategy"> <mat-select formControlName="syncStrategy">
<mat-option [value]="'default'"> <mat-option [value]="'default'">
{{ 'version-control.default' | translate }} {{ 'version-control.default' | translate }}
</mat-option> </mat-option>
<mat-option *ngFor="let strategy of syncStrategies" [value]="strategy"> @for (strategy of syncStrategies; track strategy) {
{{syncStrategyTranslations.get(strategy) | translate}} <mat-option [value]="strategy">
</mat-option> {{syncStrategyTranslations.get(strategy) | translate}}
</mat-select> </mat-option>
</mat-form-field> }
<div class="flex flex-1 flex-col"> </mat-select>
<mat-checkbox *ngIf="entityTypeFormGroup.get('entityType').value === entityTypes.DEVICE" formControlName="saveCredentials"> </mat-form-field>
{{ 'version-control.export-credentials' | translate }} <div class="flex flex-1 flex-col">
</mat-checkbox> <mat-checkbox [class.hidden]="entityTypeFormGroup.get('entityType').value !== entityTypes.DEVICE" formControlName="saveCredentials">
<mat-checkbox *ngIf="!entityTypesWithoutRelatedData.has(entityTypeFormGroup.get('entityType').value)" formControlName="saveAttributes"> {{ 'version-control.export-credentials' | translate }}
{{ 'version-control.export-attributes' | translate }} </mat-checkbox>
</mat-checkbox> <mat-checkbox [class.hidden]="entityTypesWithoutRelatedData.has(entityTypeFormGroup.get('entityType').value)" formControlName="saveAttributes">
<mat-checkbox *ngIf="!entityTypesWithoutRelatedData.has(entityTypeFormGroup.get('entityType').value)" formControlName="saveRelations"> {{ 'version-control.export-attributes' | translate }}
{{ 'version-control.export-relations' | translate }} </mat-checkbox>
</mat-checkbox> <mat-checkbox [class.hidden]="entityTypesWithoutRelatedData.has(entityTypeFormGroup.get('entityType').value)" formControlName="saveRelations">
<mat-checkbox *ngIf="typesWithCalculatedFields.has(entityTypeFormGroup.get('entityType').value)" formControlName="saveCalculatedFields"> {{ 'version-control.export-relations' | translate }}
{{ 'version-control.export-calculated-fields' | translate }} </mat-checkbox>
</mat-checkbox> <mat-checkbox [class.hidden]="!typesWithCalculatedFields.has(entityTypeFormGroup.get('entityType').value)" formControlName="saveCalculatedFields">
{{ 'version-control.export-calculated-fields' | translate }}
</mat-checkbox>
</div>
</div> </div>
</div> </div>
<div class="flex flex-row xs:flex-col gt-xs:min-h-19 gt-xs:items-center gt-xs:justify-start gt-xs:gap-4"
formGroupName="config">
<mat-slide-toggle formControlName="allEntities">
{{ 'version-control.all-entities' | translate }}
</mat-slide-toggle>
@if (!entityTypeFormGroup.get('config').get('allEntities').value) {
<tb-entity-list
class="flex-1"
appearance="outline"
subscriptSizing="dynamic"
[entityType]="entityTypeFormGroup.get('entityType').value"
required
formControlName="entityIds">
</tb-entity-list>
}
</div>
</div> </div>
<div class="flex flex-row xs:flex-col gt-xs:min-h-19 gt-xs:items-center gt-xs:justify-start gt-xs:gap-4" </mat-expansion-panel>
formGroupName="config"> </div>
<mat-slide-toggle formControlName="allEntities"> } @empty {
{{ 'version-control.all-entities' | translate }} <span translate class="tb-prompt flex items-center justify-center">version-control.no-entities-to-export-prompt</span>
</mat-slide-toggle> }
<tb-entity-list
class="flex-1"
[class.!hidden]="entityTypeFormGroup.get('config').get('allEntities').value"
[entityType]="entityTypeFormGroup.get('entityType').value"
required
formControlName="entityIds">
</tb-entity-list>
</div>
</div>
</mat-expansion-panel>
</div>
<div *ngIf="!entityTypesFormGroupArray().length">
<span translate
class="tb-prompt flex items-center justify-center">version-control.no-entities-to-export-prompt</span>
</div>
</div> </div>
<div style="padding-top: 16px;" class="flex flex-row"> <div style="padding-top: 16px;" class="flex flex-row">
<button mat-raised-button color="primary" <button mat-raised-button color="primary"

View File

@ -186,10 +186,6 @@ export class EntityTypesVersionCreateComponent extends PageComponent implements
return !!(entityTypeControl as any).expanded; return !!(entityTypeControl as any).expanded;
} }
public trackByEntityType(index: number, entityTypeControl: AbstractControl): any {
return entityTypeControl;
}
public removeEntityType(index: number) { public removeEntityType(index: number) {
(this.entityTypesVersionCreateFormGroup.get('entityTypes') as UntypedFormArray).removeAt(index); (this.entityTypesVersionCreateFormGroup.get('entityTypes') as UntypedFormArray).removeAt(index);
} }

View File

@ -18,73 +18,72 @@
<fieldset class="fields-group flex flex-col" [formGroup]="entityTypesVersionLoadFormGroup"> <fieldset class="fields-group flex flex-col" [formGroup]="entityTypesVersionLoadFormGroup">
<legend class="group-title" translate>version-control.entities-to-restore</legend> <legend class="group-title" translate>version-control.entities-to-restore</legend>
<div class="flex flex-col" style="flex: 1; overflow: auto;"> <div class="flex flex-col" style="flex: 1; overflow: auto;">
<div *ngFor="let entityTypeFormGroup of entityTypesFormGroupArray(); trackBy: trackByEntityType; @for (entityTypeFormGroup of entityTypesFormGroupArray(); track entityTypeFormGroup; let index = $index, isLast = $last) {
let $index = index; last as isLast;" <div class="flex flex-row items-center justify-start" [class.pb-2]="!isLast">
class="flex flex-row items-center justify-start" [class.pb-2]="!isLast"> <mat-expansion-panel class="entity-type-config flex-1" [class.load]="loading" [formGroup]="entityTypeFormGroup"
<mat-expansion-panel class="entity-type-config flex-1" [class.load]="loading" [formGroup]="entityTypeFormGroup" [expanded]="entityTypesFormGroupExpanded(entityTypeFormGroup)" (opened)="loading = false">
[expanded]="entityTypesFormGroupExpanded(entityTypeFormGroup)" (opened)="loading = false"> <mat-expansion-panel-header>
<mat-expansion-panel-header> <div class="flex flex-1 flex-row items-center justify-start">
<div class="flex flex-1 flex-row items-center justify-start"> <mat-panel-title>
<mat-panel-title> <div class="flex flex-1 flex-row items-center justify-start">
<div class="flex flex-1 flex-row items-center justify-start"> <div>{{ entityTypeText(entityTypeFormGroup) }}</div>
<div>{{ entityTypeText(entityTypeFormGroup) }}</div> </div>
</div> </mat-panel-title>
</mat-panel-title> <span class="flex-1"></span>
<span class="flex-1"></span> <button [class.hidden]="disabled" mat-icon-button style="min-width: 40px;"
<button *ngIf="!disabled" mat-icon-button style="min-width: 40px;" type="button"
type="button" (click)="removeEntityType(index)"
(click)="removeEntityType($index)" matTooltip="{{ 'action.remove' | translate }}"
matTooltip="{{ 'action.remove' | translate }}" matTooltipPosition="above">
matTooltipPosition="above"> <mat-icon>delete</mat-icon>
<mat-icon>delete</mat-icon> </button>
</button> </div>
</div> </mat-expansion-panel-header>
</mat-expansion-panel-header> <div class="entity-type-config-content flex flex-col gap-2">
<div class="entity-type-config-content flex flex-col gap-2"> <mat-divider></mat-divider>
<mat-divider></mat-divider> <div class="flex flex-row xs:flex-col gt-xs:gap-8">
<div class="flex flex-row xs:flex-col gt-xs:gap-8"> <tb-entity-type-select
<tb-entity-type-select class="flex-1"
class="flex-1" showLabel
showLabel formControlName="entityType"
formControlName="entityType" required
required appearance="outline"
[filterAllowedEntityTypes]="false" [filterAllowedEntityTypes]="false"
[allowedEntityTypes]="allowedEntityTypes(entityTypeFormGroup)"> [allowedEntityTypes]="allowedEntityTypes(entityTypeFormGroup)">
</tb-entity-type-select> </tb-entity-type-select>
<div class="flex flex-1 flex-row xs:flex-col xs:gap-2 gt-xs:gap-4" formGroupName="config"> <div class="flex flex-1 flex-row xs:flex-col xs:gap-2 gt-xs:gap-4" formGroupName="config">
<div class="flex flex-1 flex-col"> <div class="flex flex-1 flex-col">
<mat-checkbox #removeOtherEntitiesCheckbox <mat-checkbox #removeOtherEntitiesCheckbox
formControlName="removeOtherEntities" formControlName="removeOtherEntities"
(change)="onRemoveOtherEntities(removeOtherEntitiesCheckbox, entityTypeFormGroup)"> (change)="onRemoveOtherEntities(removeOtherEntitiesCheckbox, entityTypeFormGroup)">
{{ 'version-control.remove-other-entities' | translate }} {{ 'version-control.remove-other-entities' | translate }}
</mat-checkbox> </mat-checkbox>
<mat-checkbox formControlName="findExistingEntityByName"> <mat-checkbox formControlName="findExistingEntityByName">
{{ 'version-control.find-existing-entity-by-name' | translate }} {{ 'version-control.find-existing-entity-by-name' | translate }}
</mat-checkbox> </mat-checkbox>
</div> </div>
<div class="flex flex-1 flex-col"> <div class="flex flex-1 flex-col">
<mat-checkbox *ngIf="entityTypeFormGroup.get('entityType').value === entityTypes.DEVICE" formControlName="loadCredentials"> <mat-checkbox [class.hidden]="entityTypeFormGroup.get('entityType').value !== entityTypes.DEVICE" formControlName="loadCredentials">
{{ 'version-control.load-credentials' | translate }} {{ 'version-control.load-credentials' | translate }}
</mat-checkbox> </mat-checkbox>
<mat-checkbox *ngIf="!entityTypesWithoutRelatedData.has(entityTypeFormGroup.get('entityType').value)" formControlName="loadAttributes"> <mat-checkbox [class.hidden]="entityTypesWithoutRelatedData.has(entityTypeFormGroup.get('entityType').value)" formControlName="loadAttributes">
{{ 'version-control.load-attributes' | translate }} {{ 'version-control.load-attributes' | translate }}
</mat-checkbox> </mat-checkbox>
<mat-checkbox *ngIf="!entityTypesWithoutRelatedData.has(entityTypeFormGroup.get('entityType').value)" formControlName="loadRelations"> <mat-checkbox [class.hidden]="entityTypesWithoutRelatedData.has(entityTypeFormGroup.get('entityType').value)" formControlName="loadRelations">
{{ 'version-control.load-relations' | translate }} {{ 'version-control.load-relations' | translate }}
</mat-checkbox> </mat-checkbox>
<mat-checkbox *ngIf="typesWithCalculatedFields.has(entityTypeFormGroup.get('entityType').value)" formControlName="loadCalculatedFields"> <mat-checkbox [class.hidden]="!typesWithCalculatedFields.has(entityTypeFormGroup.get('entityType').value)" formControlName="loadCalculatedFields">
{{ 'version-control.load-calculated-fields' | translate }} {{ 'version-control.load-calculated-fields' | translate }}
</mat-checkbox> </mat-checkbox>
</div>
</div> </div>
</div> </div>
</div> </div>
</div> </mat-expansion-panel>
</mat-expansion-panel> </div>
</div> } @empty {
<div *ngIf="!entityTypesFormGroupArray().length"> <span translate class="tb-prompt flex items-center justify-center">version-control.no-entities-to-restore-prompt</span>
<span translate }
class="tb-prompt flex items-center justify-center">version-control.no-entities-to-restore-prompt</span>
</div>
</div> </div>
<div style="padding-top: 16px;" class="flex flex-row"> <div style="padding-top: 16px;" class="flex flex-row">
<button mat-raised-button color="primary" <button mat-raised-button color="primary"

View File

@ -15,39 +15,40 @@
limitations under the License. limitations under the License.
--> -->
<section *ngIf="!versionCreateResult$"> @if (!versionCreateResult$) {
<mat-toolbar> <mat-toolbar>
<h2>{{ 'version-control.create-entity-version' | translate }}</h2> <h2>{{ 'version-control.create-entity-version' | translate }}</h2>
<span class="flex-1"></span> <span class="flex-1"></span>
</mat-toolbar> </mat-toolbar>
<mat-progress-bar color="warn" style="z-index: 10; width: 100%; margin-bottom: -4px;" mode="indeterminate" <mat-progress-bar color="warn" style="z-index: 10; width: 100%; margin-bottom: -4px;" mode="indeterminate"
*ngIf="isLoading$ | async"> [class.hidden]="(isLoading$ | async) === false">
</mat-progress-bar> </mat-progress-bar>
<form [formGroup]="createVersionFormGroup" style="padding-top: 16px;"> <form [formGroup]="createVersionFormGroup" style="padding-top: 16px;">
<fieldset [disabled]="isLoading$ | async"> <fieldset [disabled]="isLoading$ | async">
<div class="flex flex-1 flex-col"> <div class="flex flex-1 flex-col">
<tb-branch-autocomplete <tb-branch-autocomplete
required required
appearance="outline"
formControlName="branch"> formControlName="branch">
</tb-branch-autocomplete> </tb-branch-autocomplete>
<mat-form-field class="mat-block flex-1"> <mat-form-field class="mat-block flex-1" appearance="outline">
<mat-label translate>version-control.version-name</mat-label> <mat-label translate>version-control.version-name</mat-label>
<input required matInput formControlName="versionName"> <input required matInput formControlName="versionName">
<mat-error *ngIf="createVersionFormGroup.get('versionName').hasError('required') || <mat-error [class.hidden]="!(createVersionFormGroup.get('versionName').hasError('required') ||
createVersionFormGroup.get('versionName').hasError('pattern')"> createVersionFormGroup.get('versionName').hasError('pattern'))">
{{ 'version-control.version-name-required' | translate }} {{ 'version-control.version-name-required' | translate }}
</mat-error> </mat-error>
</mat-form-field> </mat-form-field>
<mat-checkbox *ngIf="entityId.entityType === entityTypes.DEVICE" formControlName="saveCredentials" style="margin-bottom: 16px;"> <mat-checkbox [class.hidden]="entityId.entityType !== entityTypes.DEVICE" formControlName="saveCredentials" style="margin-bottom: 16px;">
{{ 'version-control.export-credentials' | translate }} {{ 'version-control.export-credentials' | translate }}
</mat-checkbox> </mat-checkbox>
<mat-checkbox *ngIf="!entityTypesWithoutRelatedData.has(entityId.entityType)" formControlName="saveAttributes" style="margin-bottom: 16px;"> <mat-checkbox [class.hidden]="entityTypesWithoutRelatedData.has(entityId.entityType)" formControlName="saveAttributes" style="margin-bottom: 16px;">
{{ 'version-control.export-attributes' | translate }} {{ 'version-control.export-attributes' | translate }}
</mat-checkbox> </mat-checkbox>
<mat-checkbox *ngIf="!entityTypesWithoutRelatedData.has(entityId.entityType)" formControlName="saveRelations" style="margin-bottom: 16px;"> <mat-checkbox [class.hidden]="entityTypesWithoutRelatedData.has(entityId.entityType)" formControlName="saveRelations" style="margin-bottom: 16px;">
{{ 'version-control.export-relations' | translate }} {{ 'version-control.export-relations' | translate }}
</mat-checkbox> </mat-checkbox>
<mat-checkbox *ngIf="typesWithCalculatedFields.has(entityId.entityType)" formControlName="saveCalculatedFields" class="mb-4"> <mat-checkbox [class.hidden]="!typesWithCalculatedFields.has(entityId.entityType)" formControlName="saveCalculatedFields" class="mb-4">
{{ 'version-control.export-calculated-fields' | translate }} {{ 'version-control.export-calculated-fields' | translate }}
</mat-checkbox> </mat-checkbox>
</div> </div>
@ -67,10 +68,9 @@
{{ 'action.create' | translate }} {{ 'action.create' | translate }}
</button> </button>
</div> </div>
</section> } @else {
<section *ngIf="versionCreateResult$"> @if ((versionCreateResult$ | async)?.done || resultMessage) {
<section *ngIf="(versionCreateResult$ | async)?.done || resultMessage; else progress"> <section [class.hidden]="!resultMessage">
<section *ngIf="resultMessage">
<div class="mat-headline-6 vc-result-message">{{ resultMessage }}</div> <div class="mat-headline-6 vc-result-message">{{ resultMessage }}</div>
<div class="flex items-center justify-end gap-2"> <div class="flex items-center justify-end gap-2">
<button mat-button color="primary" <button mat-button color="primary"
@ -81,13 +81,12 @@
</button> </button>
</div> </div>
</section> </section>
</section> } @else {
<ng-template #progress>
<section class="flex flex-col items-center justify-center"> <section class="flex flex-col items-center justify-center">
<div class="mat-headline-6 vc-result-message progress"> <div class="mat-headline-6 vc-result-message progress">
<span translate>version-control.creating-version</span> <span translate>version-control.creating-version</span>
<mat-progress-bar mode="indeterminate"></mat-progress-bar> <mat-progress-bar mode="indeterminate"></mat-progress-bar>
</div> </div>
</section> </section>
</ng-template> }
</section> }

View File

@ -15,51 +15,53 @@
limitations under the License. limitations under the License.
--> -->
<section *ngIf="!versionLoadResult$"> @if (!versionLoadResult$) {
<mat-toolbar *ngIf="entityDataInfo"> @if (entityDataInfo) {
<h2>{{ 'version-control.restore-entity-from-version' | translate: {versionName} }}</h2> <mat-toolbar>
<span class="flex-1"></span> <h2>{{ 'version-control.restore-entity-from-version' | translate: {versionName} }}</h2>
</mat-toolbar> <span class="flex-1"></span>
<mat-progress-bar color="warn" style="z-index: 10; width: 100%; margin-bottom: -4px;" mode="indeterminate" </mat-toolbar>
*ngIf="entityDataInfo && (isLoading$ | async)"> <mat-progress-bar color="warn" style="z-index: 10; width: 100%; margin-bottom: -4px;" mode="indeterminate"
</mat-progress-bar> [class.hidden]="(isLoading$ | async) === false">
<mat-spinner *ngIf="!entityDataInfo" mode="indeterminate" diameter="80"></mat-spinner> </mat-progress-bar>
<form *ngIf="entityDataInfo" [formGroup]="restoreFormGroup" style="padding-top: 16px;"> <form [formGroup]="restoreFormGroup" style="padding-top: 16px;">
<fieldset [disabled]="isLoading$ | async"> <fieldset [disabled]="isLoading$ | async">
<div class="flex flex-1 flex-col"> <div class="flex flex-1 flex-col">
<mat-checkbox *ngIf="entityDataInfo.hasCredentials" formControlName="loadCredentials" style="margin-bottom: 16px;"> <mat-checkbox [class.hidden]="!entityDataInfo?.hasCredentials" formControlName="loadCredentials" style="margin-bottom: 16px;">
{{ 'version-control.load-credentials' | translate }} {{ 'version-control.load-credentials' | translate }}
</mat-checkbox> </mat-checkbox>
<mat-checkbox *ngIf="entityDataInfo.hasAttributes" formControlName="loadAttributes" style="margin-bottom: 16px;"> <mat-checkbox [class.hidden]="!entityDataInfo?.hasAttributes" formControlName="loadAttributes" style="margin-bottom: 16px;">
{{ 'version-control.load-attributes' | translate }} {{ 'version-control.load-attributes' | translate }}
</mat-checkbox> </mat-checkbox>
<mat-checkbox *ngIf="entityDataInfo.hasRelations" formControlName="loadRelations" style="margin-bottom: 16px;"> <mat-checkbox [class.hidden]="!entityDataInfo?.hasRelations" formControlName="loadRelations" style="margin-bottom: 16px;">
{{ 'version-control.load-relations' | translate }} {{ 'version-control.load-relations' | translate }}
</mat-checkbox> </mat-checkbox>
<mat-checkbox *ngIf="entityDataInfo.hasCalculatedFields" formControlName="loadCalculatedFields" class="mb-4"> <mat-checkbox [class.hidden]="!entityDataInfo?.hasCalculatedFields" formControlName="loadCalculatedFields" class="mb-4">
{{ 'version-control.load-calculated-fields' | translate }} {{ 'version-control.load-calculated-fields' | translate }}
</mat-checkbox> </mat-checkbox>
</div> </div>
</fieldset> </fieldset>
</form> </form>
<div *ngIf="entityDataInfo" class="flex items-center justify-end gap-2"> <div class="flex items-center justify-end gap-2">
<button mat-button color="primary" <button mat-button color="primary"
type="button" type="button"
[disabled]="(isLoading$ | async)" [disabled]="(isLoading$ | async)"
(click)="cancel()" cdkFocusInitial> (click)="cancel()" cdkFocusInitial>
{{ 'action.cancel' | translate }} {{ 'action.cancel' | translate }}
</button> </button>
<button mat-raised-button color="primary" <button mat-raised-button color="primary"
type="button" type="button"
(click)="restore()" (click)="restore()"
[disabled]="(isLoading$ | async) || restoreFormGroup.invalid"> [disabled]="(isLoading$ | async) || restoreFormGroup.invalid">
{{ 'action.restore' | translate }} {{ 'action.restore' | translate }}
</button> </button>
</div> </div>
</section> } @else {
<section *ngIf="versionLoadResult$"> <mat-spinner mode="indeterminate" diameter="80"></mat-spinner>
<section *ngIf="(versionLoadResult$ | async)?.done || errorMessage; else progress"> }
<section *ngIf="errorMessage"> } @else {
@if ((versionLoadResult$ | async)?.done || errorMessage) {
<section [class.hidden]="!errorMessage">
<div class="mat-headline-6 vc-result-message error" [innerHTML]="errorMessage"></div> <div class="mat-headline-6 vc-result-message error" [innerHTML]="errorMessage"></div>
<div class="flex items-center justify-end gap-2"> <div class="flex items-center justify-end gap-2">
<button mat-button color="primary" <button mat-button color="primary"
@ -70,13 +72,12 @@
</button> </button>
</div> </div>
</section> </section>
</section> } @else {
<ng-template #progress>
<section class="flex flex-col items-center justify-center"> <section class="flex flex-col items-center justify-center">
<div class="mat-headline-6 vc-result-message progress"> <div class="mat-headline-6 vc-result-message progress">
<span translate>version-control.restoring-entity-version</span> <span translate>version-control.restoring-entity-version</span>
<mat-progress-bar mode="indeterminate"></mat-progress-bar> <mat-progress-bar mode="indeterminate"></mat-progress-bar>
</div> </div>
</section> </section>
</ng-template> }
</section> }

View File

@ -19,7 +19,7 @@
<form [formGroup]="confirmFormGroup" style="padding-top: 16px;"> <form [formGroup]="confirmFormGroup" style="padding-top: 16px;">
<fieldset [disabled]="(isLoading$ | async)"> <fieldset [disabled]="(isLoading$ | async)">
<div style="user-select: none;" [innerHTML]="removeOtherEntitiesConfirmText"></div> <div style="user-select: none;" [innerHTML]="removeOtherEntitiesConfirmText"></div>
<mat-form-field class="mat-block"> <mat-form-field class="mat-block" appearance="outline">
<input matInput formControlName="verification"/> <input matInput formControlName="verification"/>
</mat-form-field> </mat-form-field>
</fieldset> </fieldset>

View File

@ -15,7 +15,10 @@
limitations under the License. limitations under the License.
--> -->
<mat-form-field [formGroup]="branchFormGroup" class="mat-block" [floatLabel]="(selectionMode || emptyPlaceholder) ? 'always' : 'auto'" subscriptSizing="{{ subscriptSizing }}"> <mat-form-field [formGroup]="branchFormGroup" class="mat-block"
[floatLabel]="(selectionMode || emptyPlaceholder) ? 'always' : 'auto'"
[appearance]="appearance"
[subscriptSizing]="subscriptSizing">
<mat-label>{{ 'version-control.branch' | translate }}</mat-label> <mat-label>{{ 'version-control.branch' | translate }}</mat-label>
<input matInput type="text" placeholder="{{emptyPlaceholder || ((loading ? 'common.loading' : 'version-control.select-branch') | translate)}}" <input matInput type="text" placeholder="{{emptyPlaceholder || ((loading ? 'common.loading' : 'version-control.select-branch') | translate)}}"
#branchInput #branchInput

View File

@ -35,7 +35,7 @@ import { BranchInfo } from '@shared/models/vc.models';
import { EntitiesVersionControlService } from '@core/http/entities-version-control.service'; import { EntitiesVersionControlService } from '@core/http/entities-version-control.service';
import { isNotEmptyStr } from '@core/utils'; import { isNotEmptyStr } from '@core/utils';
import { MatAutocomplete, MatAutocompleteTrigger } from '@angular/material/autocomplete'; import { MatAutocomplete, MatAutocompleteTrigger } from '@angular/material/autocomplete';
import { SubscriptSizing } from '@angular/material/form-field'; import { SubscriptSizing, MatFormFieldAppearance } from '@angular/material/form-field';
@Component({ @Component({
selector: 'tb-branch-autocomplete', selector: 'tb-branch-autocomplete',
@ -57,6 +57,9 @@ export class BranchAutocompleteComponent implements ControlValueAccessor, OnInit
@Input() @Input()
subscriptSizing: SubscriptSizing = 'fixed'; subscriptSizing: SubscriptSizing = 'fixed';
@Input()
appearance: MatFormFieldAppearance = 'fill';
private requiredValue: boolean; private requiredValue: boolean;
get required(): boolean { get required(): boolean {