Commit cf4e1a4bd93995fd4cae49c81fb86b9e1cbd1381
1 parent
a73e6be5
UI: Inline tenant profile create/edit.
Showing
10 changed files
with
277 additions
and
19 deletions
@@ -86,6 +86,7 @@ import { FilterUserInfoDialogComponent } from './filter/filter-user-info-dialog. | @@ -86,6 +86,7 @@ import { FilterUserInfoDialogComponent } from './filter/filter-user-info-dialog. | ||
86 | import { FilterPredicateValueComponent } from './filter/filter-predicate-value.component'; | 86 | import { FilterPredicateValueComponent } from './filter/filter-predicate-value.component'; |
87 | import { TenantProfileAutocompleteComponent } from './profile/tenant-profile-autocomplete.component'; | 87 | import { TenantProfileAutocompleteComponent } from './profile/tenant-profile-autocomplete.component'; |
88 | import { TenantProfileComponent } from './profile/tenant-profile.component'; | 88 | import { TenantProfileComponent } from './profile/tenant-profile.component'; |
89 | +import { TenantProfileDialogComponent } from './profile/tenant-profile-dialog.component'; | ||
89 | 90 | ||
90 | @NgModule({ | 91 | @NgModule({ |
91 | declarations: | 92 | declarations: |
@@ -154,7 +155,8 @@ import { TenantProfileComponent } from './profile/tenant-profile.component'; | @@ -154,7 +155,8 @@ import { TenantProfileComponent } from './profile/tenant-profile.component'; | ||
154 | FilterUserInfoDialogComponent, | 155 | FilterUserInfoDialogComponent, |
155 | FilterPredicateValueComponent, | 156 | FilterPredicateValueComponent, |
156 | TenantProfileAutocompleteComponent, | 157 | TenantProfileAutocompleteComponent, |
157 | - TenantProfileComponent | 158 | + TenantProfileComponent, |
159 | + TenantProfileDialogComponent | ||
158 | ], | 160 | ], |
159 | imports: [ | 161 | imports: [ |
160 | CommonModule, | 162 | CommonModule, |
@@ -212,7 +214,8 @@ import { TenantProfileComponent } from './profile/tenant-profile.component'; | @@ -212,7 +214,8 @@ import { TenantProfileComponent } from './profile/tenant-profile.component'; | ||
212 | FiltersEditComponent, | 214 | FiltersEditComponent, |
213 | UserFilterDialogComponent, | 215 | UserFilterDialogComponent, |
214 | TenantProfileAutocompleteComponent, | 216 | TenantProfileAutocompleteComponent, |
215 | - TenantProfileComponent | 217 | + TenantProfileComponent, |
218 | + TenantProfileDialogComponent | ||
216 | ], | 219 | ], |
217 | providers: [ | 220 | providers: [ |
218 | WidgetComponentService, | 221 | WidgetComponentService, |
@@ -20,6 +20,8 @@ | @@ -20,6 +20,8 @@ | ||
20 | #tenantProfileInput | 20 | #tenantProfileInput |
21 | formControlName="tenantProfile" | 21 | formControlName="tenantProfile" |
22 | [required]="required" | 22 | [required]="required" |
23 | + (keydown)="tenantProfileEnter($event)" | ||
24 | + (keypress)="tenantProfileEnter($event)" | ||
23 | [matAutocomplete]="tenantProfileAutocomplete"> | 25 | [matAutocomplete]="tenantProfileAutocomplete"> |
24 | <button *ngIf="selectTenantProfileFormGroup.get('tenantProfile').value && !disabled" | 26 | <button *ngIf="selectTenantProfileFormGroup.get('tenantProfile').value && !disabled" |
25 | type="button" | 27 | type="button" |
@@ -27,6 +29,14 @@ | @@ -27,6 +29,14 @@ | ||
27 | (click)="clear()"> | 29 | (click)="clear()"> |
28 | <mat-icon class="material-icons">close</mat-icon> | 30 | <mat-icon class="material-icons">close</mat-icon> |
29 | </button> | 31 | </button> |
32 | + <button *ngIf="selectTenantProfileFormGroup.get('tenantProfile').value && !disabled" | ||
33 | + type="button" | ||
34 | + matSuffix mat-button mat-icon-button aria-label="Edit" | ||
35 | + matTooltip="{{ 'tenant-profile.edit' | translate }}" | ||
36 | + matTooltipPosition="above" | ||
37 | + (click)="editTenantProfile($event)"> | ||
38 | + <mat-icon class="material-icons">edit</mat-icon> | ||
39 | + </button> | ||
30 | <mat-autocomplete | 40 | <mat-autocomplete |
31 | class="tb-autocomplete" | 41 | class="tb-autocomplete" |
32 | #tenantProfileAutocomplete="matAutocomplete" | 42 | #tenantProfileAutocomplete="matAutocomplete" |
@@ -34,10 +44,21 @@ | @@ -34,10 +44,21 @@ | ||
34 | <mat-option *ngFor="let tenantProfile of filteredTenantProfiles | async" [value]="tenantProfile"> | 44 | <mat-option *ngFor="let tenantProfile of filteredTenantProfiles | async" [value]="tenantProfile"> |
35 | <span [innerHTML]="tenantProfile.name | highlight:searchText"></span> | 45 | <span [innerHTML]="tenantProfile.name | highlight:searchText"></span> |
36 | </mat-option> | 46 | </mat-option> |
37 | - <mat-option *ngIf="!(filteredTenantProfiles | async)?.length" [value]="null"> | ||
38 | - <span> | ||
39 | - {{ translate.get('tenant-profile.no-tenant-profiles-matching', {entity: searchText}) | async }} | ||
40 | - </span> | 47 | + <mat-option *ngIf="!(filteredTenantProfiles | async)?.length" [value]="null" class="tb-not-found"> |
48 | + <div class="tb-not-found-content" (click)="$event.stopPropagation()"> | ||
49 | + <div *ngIf="!textIsNotEmpty(searchText); else searchNotEmpty"> | ||
50 | + <span translate>tenant-profile.no-tenant-profiles-found</span> | ||
51 | + </div> | ||
52 | + <ng-template #searchNotEmpty> | ||
53 | + <span> | ||
54 | + {{ translate.get('tenant-profile.no-tenant-profiles-matching', | ||
55 | + {entity: truncate.transform(searchText, true, 6, '...')}) | async }} | ||
56 | + </span> | ||
57 | + </ng-template> | ||
58 | + <span> | ||
59 | + <a translate (click)="createTenantProfile($event, searchText)">tenant-profile.create-new-tenant-profile</a> | ||
60 | + </span> | ||
61 | + </div> | ||
41 | </mat-option> | 62 | </mat-option> |
42 | </mat-autocomplete> | 63 | </mat-autocomplete> |
43 | <mat-error *ngIf="selectTenantProfileFormGroup.get('tenantProfile').hasError('required')"> | 64 | <mat-error *ngIf="selectTenantProfileFormGroup.get('tenantProfile').hasError('required')"> |
@@ -14,7 +14,7 @@ | @@ -14,7 +14,7 @@ | ||
14 | /// limitations under the License. | 14 | /// limitations under the License. |
15 | /// | 15 | /// |
16 | 16 | ||
17 | -import { Component, ElementRef, forwardRef, Input, OnInit, ViewChild } from '@angular/core'; | 17 | +import { Component, ElementRef, EventEmitter, forwardRef, Input, OnInit, Output, ViewChild } from '@angular/core'; |
18 | import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR } from '@angular/forms'; | 18 | import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR } from '@angular/forms'; |
19 | import { Observable } from 'rxjs'; | 19 | import { Observable } from 'rxjs'; |
20 | import { PageLink } from '@shared/models/page/page-link'; | 20 | import { PageLink } from '@shared/models/page/page-link'; |
@@ -27,7 +27,12 @@ import { coerceBooleanProperty } from '@angular/cdk/coercion'; | @@ -27,7 +27,12 @@ import { coerceBooleanProperty } from '@angular/cdk/coercion'; | ||
27 | import { TenantProfileId } from '@shared/models/id/tenant-profile-id'; | 27 | import { TenantProfileId } from '@shared/models/id/tenant-profile-id'; |
28 | import { EntityInfoData } from '@shared/models/entity.models'; | 28 | import { EntityInfoData } from '@shared/models/entity.models'; |
29 | import { TenantProfileService } from '@core/http/tenant-profile.service'; | 29 | import { TenantProfileService } from '@core/http/tenant-profile.service'; |
30 | -import { entityIdEquals } from '../../../../shared/models/id/entity-id'; | 30 | +import { entityIdEquals } from '@shared/models/id/entity-id'; |
31 | +import { TruncatePipe } from '@shared//pipe/truncate.pipe'; | ||
32 | +import { ENTER } from '@angular/cdk/keycodes'; | ||
33 | +import { TenantProfile } from '@shared/models/tenant.model'; | ||
34 | +import { MatDialog } from '@angular/material/dialog'; | ||
35 | +import { TenantProfileDialogComponent, TenantProfileDialogData } from './tenant-profile-dialog.component'; | ||
31 | 36 | ||
32 | @Component({ | 37 | @Component({ |
33 | selector: 'tb-tenant-profile-autocomplete', | 38 | selector: 'tb-tenant-profile-autocomplete', |
@@ -60,6 +65,9 @@ export class TenantProfileAutocompleteComponent implements ControlValueAccessor, | @@ -60,6 +65,9 @@ export class TenantProfileAutocompleteComponent implements ControlValueAccessor, | ||
60 | @Input() | 65 | @Input() |
61 | disabled: boolean; | 66 | disabled: boolean; |
62 | 67 | ||
68 | + @Output() | ||
69 | + tenantProfileUpdated = new EventEmitter<TenantProfileId>(); | ||
70 | + | ||
63 | @ViewChild('tenantProfileInput', {static: true}) tenantProfileInput: ElementRef; | 71 | @ViewChild('tenantProfileInput', {static: true}) tenantProfileInput: ElementRef; |
64 | 72 | ||
65 | filteredTenantProfiles: Observable<Array<EntityInfoData>>; | 73 | filteredTenantProfiles: Observable<Array<EntityInfoData>>; |
@@ -70,8 +78,10 @@ export class TenantProfileAutocompleteComponent implements ControlValueAccessor, | @@ -70,8 +78,10 @@ export class TenantProfileAutocompleteComponent implements ControlValueAccessor, | ||
70 | 78 | ||
71 | constructor(private store: Store<AppState>, | 79 | constructor(private store: Store<AppState>, |
72 | public translate: TranslateService, | 80 | public translate: TranslateService, |
81 | + public truncate: TruncatePipe, | ||
73 | private tenantProfileService: TenantProfileService, | 82 | private tenantProfileService: TenantProfileService, |
74 | - private fb: FormBuilder) { | 83 | + private fb: FormBuilder, |
84 | + private dialog: MatDialog) { | ||
75 | this.selectTenantProfileFormGroup = this.fb.group({ | 85 | this.selectTenantProfileFormGroup = this.fb.group({ |
76 | tenantProfile: [null] | 86 | tenantProfile: [null] |
77 | }); | 87 | }); |
@@ -168,4 +178,67 @@ export class TenantProfileAutocompleteComponent implements ControlValueAccessor, | @@ -168,4 +178,67 @@ export class TenantProfileAutocompleteComponent implements ControlValueAccessor, | ||
168 | }, 0); | 178 | }, 0); |
169 | } | 179 | } |
170 | 180 | ||
181 | + textIsNotEmpty(text: string): boolean { | ||
182 | + return (text && text.length > 0); | ||
183 | + } | ||
184 | + | ||
185 | + tenantProfileEnter($event: KeyboardEvent) { | ||
186 | + if ($event.keyCode === ENTER) { | ||
187 | + $event.preventDefault(); | ||
188 | + if (!this.modelValue) { | ||
189 | + this.createTenantProfile($event, this.searchText); | ||
190 | + } | ||
191 | + } | ||
192 | + } | ||
193 | + | ||
194 | + createTenantProfile($event: Event, profileName: string) { | ||
195 | + $event.preventDefault(); | ||
196 | + const tenantProfile: TenantProfile = { | ||
197 | + id: null, | ||
198 | + name: profileName | ||
199 | + }; | ||
200 | + this.openTenantProfileDialog(tenantProfile, true); | ||
201 | + } | ||
202 | + | ||
203 | + editTenantProfile($event: Event) { | ||
204 | + $event.preventDefault(); | ||
205 | + this.tenantProfileService.getTenantProfile(this.modelValue.id).subscribe( | ||
206 | + (tenantProfile) => { | ||
207 | + this.openTenantProfileDialog(tenantProfile, false); | ||
208 | + } | ||
209 | + ); | ||
210 | + } | ||
211 | + | ||
212 | + openTenantProfileDialog(tenantProfile: TenantProfile, isAdd: boolean) { | ||
213 | + this.dialog.open<TenantProfileDialogComponent, TenantProfileDialogData, | ||
214 | + TenantProfile>(TenantProfileDialogComponent, { | ||
215 | + disableClose: true, | ||
216 | + panelClass: ['tb-dialog', 'tb-fullscreen-dialog'], | ||
217 | + data: { | ||
218 | + isAdd, | ||
219 | + tenantProfile | ||
220 | + } | ||
221 | + }).afterClosed().subscribe( | ||
222 | + (savedTenantProfile) => { | ||
223 | + if (!savedTenantProfile) { | ||
224 | + setTimeout(() => { | ||
225 | + this.tenantProfileInput.nativeElement.blur(); | ||
226 | + this.tenantProfileInput.nativeElement.focus(); | ||
227 | + }, 0); | ||
228 | + } else { | ||
229 | + this.tenantProfileService.getTenantProfileInfo(savedTenantProfile.id.id).subscribe( | ||
230 | + (profile) => { | ||
231 | + this.modelValue = new TenantProfileId(profile.id.id); | ||
232 | + this.selectTenantProfileFormGroup.get('tenantProfile').patchValue(profile, {emitEvent: true}); | ||
233 | + if (isAdd) { | ||
234 | + this.propagateChange(this.modelValue); | ||
235 | + } else { | ||
236 | + this.tenantProfileUpdated.next(savedTenantProfile.id); | ||
237 | + } | ||
238 | + } | ||
239 | + ); | ||
240 | + } | ||
241 | + } | ||
242 | + ); | ||
243 | + } | ||
171 | } | 244 | } |
1 | +<!-- | ||
2 | + | ||
3 | + Copyright © 2016-2020 The Thingsboard Authors | ||
4 | + | ||
5 | + Licensed under the Apache License, Version 2.0 (the "License"); | ||
6 | + you may not use this file except in compliance with the License. | ||
7 | + You may obtain a copy of the License at | ||
8 | + | ||
9 | + http://www.apache.org/licenses/LICENSE-2.0 | ||
10 | + | ||
11 | + Unless required by applicable law or agreed to in writing, software | ||
12 | + distributed under the License is distributed on an "AS IS" BASIS, | ||
13 | + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
14 | + See the License for the specific language governing permissions and | ||
15 | + limitations under the License. | ||
16 | + | ||
17 | +--> | ||
18 | +<form (ngSubmit)="save()" style="min-width: 600px;"> | ||
19 | + <mat-toolbar color="primary"> | ||
20 | + <h2>{{ (isAdd ? 'tenant-profile.add' : 'tenant-profile.edit' ) | translate }}</h2> | ||
21 | + <span fxFlex></span> | ||
22 | + <button mat-icon-button | ||
23 | + (click)="cancel()" | ||
24 | + type="button"> | ||
25 | + <mat-icon class="material-icons">close</mat-icon> | ||
26 | + </button> | ||
27 | + </mat-toolbar> | ||
28 | + <mat-progress-bar color="warn" mode="indeterminate" *ngIf="isLoading$ | async"> | ||
29 | + </mat-progress-bar> | ||
30 | + <div style="height: 4px;" *ngIf="!(isLoading$ | async)"></div> | ||
31 | + <div mat-dialog-content> | ||
32 | + <tb-tenant-profile | ||
33 | + #tenantProfileComponent | ||
34 | + [standalone]="true" | ||
35 | + [entity]="tenantProfile" | ||
36 | + [isEdit]="true"> | ||
37 | + </tb-tenant-profile> | ||
38 | + </div> | ||
39 | + <div mat-dialog-actions fxLayoutAlign="end center"> | ||
40 | + <button mat-raised-button color="primary" | ||
41 | + type="submit" | ||
42 | + [disabled]="(isLoading$ | async) || tenantProfileComponent.entityForm?.invalid || !tenantProfileComponent.entityForm?.dirty"> | ||
43 | + {{ (isAdd ? 'action.add' : 'action.save') | translate }} | ||
44 | + </button> | ||
45 | + <button mat-button color="primary" | ||
46 | + type="button" | ||
47 | + cdkFocusInitial | ||
48 | + [disabled]="(isLoading$ | async)" | ||
49 | + (click)="cancel()"> | ||
50 | + {{ 'action.cancel' | translate }} | ||
51 | + </button> | ||
52 | + </div> | ||
53 | +</form> |
1 | +/// | ||
2 | +/// Copyright © 2016-2020 The Thingsboard Authors | ||
3 | +/// | ||
4 | +/// Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | +/// you may not use this file except in compliance with the License. | ||
6 | +/// You may obtain a copy of the License at | ||
7 | +/// | ||
8 | +/// http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | +/// | ||
10 | +/// Unless required by applicable law or agreed to in writing, software | ||
11 | +/// distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | +/// See the License for the specific language governing permissions and | ||
14 | +/// limitations under the License. | ||
15 | +/// | ||
16 | + | ||
17 | +import { | ||
18 | + AfterViewInit, | ||
19 | + Component, | ||
20 | + ComponentFactoryResolver, | ||
21 | + Inject, | ||
22 | + Injector, | ||
23 | + SkipSelf, | ||
24 | + ViewChild | ||
25 | +} from '@angular/core'; | ||
26 | +import { ErrorStateMatcher } from '@angular/material/core'; | ||
27 | +import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; | ||
28 | +import { Store } from '@ngrx/store'; | ||
29 | +import { AppState } from '@core/core.state'; | ||
30 | +import { FormControl, FormGroupDirective, NgForm } from '@angular/forms'; | ||
31 | +import { DialogComponent } from '@shared/components/dialog.component'; | ||
32 | +import { Router } from '@angular/router'; | ||
33 | +import { TenantProfile } from '@shared/models/tenant.model'; | ||
34 | +import { TenantProfileComponent } from './tenant-profile.component'; | ||
35 | +import { TenantProfileService } from '@core/http/tenant-profile.service'; | ||
36 | + | ||
37 | +export interface TenantProfileDialogData { | ||
38 | + tenantProfile: TenantProfile; | ||
39 | + isAdd: boolean; | ||
40 | +} | ||
41 | + | ||
42 | +@Component({ | ||
43 | + selector: 'tb-tenant-profile-dialog', | ||
44 | + templateUrl: './tenant-profile-dialog.component.html', | ||
45 | + providers: [{provide: ErrorStateMatcher, useExisting: TenantProfileDialogComponent}], | ||
46 | + styleUrls: [] | ||
47 | +}) | ||
48 | +export class TenantProfileDialogComponent extends | ||
49 | + DialogComponent<TenantProfileDialogComponent, TenantProfile> implements ErrorStateMatcher, AfterViewInit { | ||
50 | + | ||
51 | + isAdd: boolean; | ||
52 | + tenantProfile: TenantProfile; | ||
53 | + | ||
54 | + submitted = false; | ||
55 | + | ||
56 | + @ViewChild('tenantProfileComponent', {static: true}) tenantProfileComponent: TenantProfileComponent; | ||
57 | + | ||
58 | + constructor(protected store: Store<AppState>, | ||
59 | + protected router: Router, | ||
60 | + @Inject(MAT_DIALOG_DATA) public data: TenantProfileDialogData, | ||
61 | + public dialogRef: MatDialogRef<TenantProfileDialogComponent, TenantProfile>, | ||
62 | + private componentFactoryResolver: ComponentFactoryResolver, | ||
63 | + private injector: Injector, | ||
64 | + @SkipSelf() private errorStateMatcher: ErrorStateMatcher, | ||
65 | + private tenantProfileService: TenantProfileService) { | ||
66 | + super(store, router, dialogRef); | ||
67 | + this.isAdd = this.data.isAdd; | ||
68 | + this.tenantProfile = this.data.tenantProfile; | ||
69 | + } | ||
70 | + | ||
71 | + ngAfterViewInit(): void { | ||
72 | + if (this.isAdd) { | ||
73 | + setTimeout(() => { | ||
74 | + this.tenantProfileComponent.entityForm.markAsDirty(); | ||
75 | + }, 0); | ||
76 | + } | ||
77 | + } | ||
78 | + | ||
79 | + isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean { | ||
80 | + const originalErrorState = this.errorStateMatcher.isErrorState(control, form); | ||
81 | + const customErrorState = !!(control && control.invalid && this.submitted); | ||
82 | + return originalErrorState || customErrorState; | ||
83 | + } | ||
84 | + | ||
85 | + cancel(): void { | ||
86 | + this.dialogRef.close(null); | ||
87 | + } | ||
88 | + | ||
89 | + save(): void { | ||
90 | + this.submitted = true; | ||
91 | + if (this.tenantProfileComponent.entityForm.valid) { | ||
92 | + this.tenantProfile = {...this.tenantProfile, ...this.tenantProfileComponent.entityFormValue()}; | ||
93 | + this.tenantProfileService.saveTenantProfile(this.tenantProfile).subscribe( | ||
94 | + (tenantProfile) => { | ||
95 | + this.dialogRef.close(tenantProfile); | ||
96 | + } | ||
97 | + ); | ||
98 | + } | ||
99 | + } | ||
100 | + | ||
101 | +} |
@@ -14,7 +14,7 @@ | @@ -14,7 +14,7 @@ | ||
14 | /// limitations under the License. | 14 | /// limitations under the License. |
15 | /// | 15 | /// |
16 | 16 | ||
17 | -import { Component, Inject, Input } from '@angular/core'; | 17 | +import { Component, Inject, Input, Optional } from '@angular/core'; |
18 | import { Store } from '@ngrx/store'; | 18 | import { Store } from '@ngrx/store'; |
19 | import { AppState } from '@core/core.state'; | 19 | import { AppState } from '@core/core.state'; |
20 | import { FormBuilder, FormGroup, Validators } from '@angular/forms'; | 20 | import { FormBuilder, FormGroup, Validators } from '@angular/forms'; |
@@ -36,8 +36,8 @@ export class TenantProfileComponent extends EntityComponent<TenantProfile> { | @@ -36,8 +36,8 @@ export class TenantProfileComponent extends EntityComponent<TenantProfile> { | ||
36 | 36 | ||
37 | constructor(protected store: Store<AppState>, | 37 | constructor(protected store: Store<AppState>, |
38 | protected translate: TranslateService, | 38 | protected translate: TranslateService, |
39 | - @Inject('entity') protected entityValue: TenantProfile, | ||
40 | - @Inject('entitiesTableConfig') protected entitiesTableConfigValue: EntityTableConfig<TenantProfile>, | 39 | + @Optional() @Inject('entity') protected entityValue: TenantProfile, |
40 | + @Optional() @Inject('entitiesTableConfig') protected entitiesTableConfigValue: EntityTableConfig<TenantProfile>, | ||
41 | protected fb: FormBuilder) { | 41 | protected fb: FormBuilder) { |
42 | super(store, fb, entityValue, entitiesTableConfigValue); | 42 | super(store, fb, entityValue, entitiesTableConfigValue); |
43 | } | 43 | } |
@@ -52,7 +52,8 @@ | @@ -52,7 +52,8 @@ | ||
52 | <tb-tenant-profile-autocomplete | 52 | <tb-tenant-profile-autocomplete |
53 | [selectDefaultProfile]="isAdd" | 53 | [selectDefaultProfile]="isAdd" |
54 | required | 54 | required |
55 | - formControlName="tenantProfileId"> | 55 | + formControlName="tenantProfileId" |
56 | + (tenantProfileUpdated)="onTenantProfileUpdated()"> | ||
56 | </tb-tenant-profile-autocomplete> | 57 | </tb-tenant-profile-autocomplete> |
57 | <div formGroupName="additionalInfo" fxLayout="column"> | 58 | <div formGroupName="additionalInfo" fxLayout="column"> |
58 | <mat-form-field class="mat-block"> | 59 | <mat-form-field class="mat-block"> |
@@ -88,4 +88,7 @@ export class TenantComponent extends ContactBasedComponent<TenantInfo> { | @@ -88,4 +88,7 @@ export class TenantComponent extends ContactBasedComponent<TenantInfo> { | ||
88 | })); | 88 | })); |
89 | } | 89 | } |
90 | 90 | ||
91 | + onTenantProfileUpdated() { | ||
92 | + this.entitiesTableConfig.table.updateData(false); | ||
93 | + } | ||
91 | } | 94 | } |
@@ -25,11 +25,11 @@ export interface TenantProfileData { | @@ -25,11 +25,11 @@ export interface TenantProfileData { | ||
25 | 25 | ||
26 | export interface TenantProfile extends BaseData<TenantProfileId> { | 26 | export interface TenantProfile extends BaseData<TenantProfileId> { |
27 | name: string; | 27 | name: string; |
28 | - description: string; | ||
29 | - default: boolean; | ||
30 | - isolatedTbCore: boolean; | ||
31 | - isolatedTbRuleEngine: boolean; | ||
32 | - profileData: TenantProfileData; | 28 | + description?: string; |
29 | + default?: boolean; | ||
30 | + isolatedTbCore?: boolean; | ||
31 | + isolatedTbRuleEngine?: boolean; | ||
32 | + profileData?: TenantProfileData; | ||
33 | } | 33 | } |
34 | 34 | ||
35 | export interface Tenant extends ContactBased<TenantId> { | 35 | export interface Tenant extends ContactBased<TenantId> { |
@@ -1680,6 +1680,7 @@ | @@ -1680,6 +1680,7 @@ | ||
1680 | "tenant-profile": "Tenant profile", | 1680 | "tenant-profile": "Tenant profile", |
1681 | "tenant-profiles": "Tenant profiles", | 1681 | "tenant-profiles": "Tenant profiles", |
1682 | "add": "Add tenant profile", | 1682 | "add": "Add tenant profile", |
1683 | + "edit": "Edit tenant profile", | ||
1683 | "tenant-profile-details": "Tenant profile details", | 1684 | "tenant-profile-details": "Tenant profile details", |
1684 | "no-tenant-profiles-text": "No tenant profiles found", | 1685 | "no-tenant-profiles-text": "No tenant profiles found", |
1685 | "search": "Search tenant profiles", | 1686 | "search": "Search tenant profiles", |
@@ -1699,7 +1700,9 @@ | @@ -1699,7 +1700,9 @@ | ||
1699 | "delete-tenant-profiles-title": "Are you sure you want to delete { count, plural, 1 {1 tenant profile} other {# tenant profiles} }?", | 1700 | "delete-tenant-profiles-title": "Are you sure you want to delete { count, plural, 1 {1 tenant profile} other {# tenant profiles} }?", |
1700 | "delete-tenant-profiles-text": "Be careful, after the confirmation all selected tenant profiles will be removed and all related data will become unrecoverable.", | 1701 | "delete-tenant-profiles-text": "Be careful, after the confirmation all selected tenant profiles will be removed and all related data will become unrecoverable.", |
1701 | "set-default-tenant-profile-title": "Are you sure you want to make the tenant profile '{{tenantProfileName}}' root?", | 1702 | "set-default-tenant-profile-title": "Are you sure you want to make the tenant profile '{{tenantProfileName}}' root?", |
1702 | - "set-default-tenant-profile-text": "After the confirmation the tenant profile will be marked as default and will be used for new tenants with no profile specified." | 1703 | + "set-default-tenant-profile-text": "After the confirmation the tenant profile will be marked as default and will be used for new tenants with no profile specified.", |
1704 | + "no-tenant-profiles-found": "No tenant profiles found.", | ||
1705 | + "create-new-tenant-profile": "Create a new one!" | ||
1703 | }, | 1706 | }, |
1704 | "timeinterval": { | 1707 | "timeinterval": { |
1705 | "seconds-interval": "{ seconds, plural, 1 {1 second} other {# seconds} }", | 1708 | "seconds-interval": "{ seconds, plural, 1 {1 second} other {# seconds} }", |