Updated logic for file upload, changed to dialog window upload
This commit is contained in:
		
							parent
							
								
									5b14dc67fc
								
							
						
					
					
						commit
						e4588616f3
					
				@ -28,6 +28,12 @@
 | 
				
			|||||||
          [class.!hidden]="isEdit || dashboardScope !== 'tenant'">
 | 
					          [class.!hidden]="isEdit || dashboardScope !== 'tenant'">
 | 
				
			||||||
    {{'dashboard.export' | translate }}
 | 
					    {{'dashboard.export' | translate }}
 | 
				
			||||||
  </button>
 | 
					  </button>
 | 
				
			||||||
 | 
					  <button mat-raised-button color="primary"
 | 
				
			||||||
 | 
					          [disabled]="(isLoading$ | async)"
 | 
				
			||||||
 | 
					          (click)="onEntityAction($event, 'import')"
 | 
				
			||||||
 | 
					          [class.!hidden]="isEdit || dashboardScope !== 'tenant'">
 | 
				
			||||||
 | 
					    {{'dashboard.import' | translate }}
 | 
				
			||||||
 | 
					  </button>
 | 
				
			||||||
  <button mat-raised-button color="primary"
 | 
					  <button mat-raised-button color="primary"
 | 
				
			||||||
          [disabled]="(isLoading$ | async)"
 | 
					          [disabled]="(isLoading$ | async)"
 | 
				
			||||||
          (click)="onEntityAction($event, 'makePublic')"
 | 
					          (click)="onEntityAction($event, 'makePublic')"
 | 
				
			||||||
@ -144,19 +150,6 @@
 | 
				
			|||||||
                                formControlName="image">
 | 
					                                formControlName="image">
 | 
				
			||||||
        </tb-gallery-image-input>
 | 
					        </tb-gallery-image-input>
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
 | 
					 | 
				
			||||||
      <div class="tb-form-panel stroked gap-2" [class.!hidden]="!isEdit">
 | 
					 | 
				
			||||||
        <div class="tb-form-panel-title" translate>dashboard.update-dashboard</div>
 | 
					 | 
				
			||||||
        <tb-file-input [contentConvertFunction]="loadDataFromJsonContent"
 | 
					 | 
				
			||||||
                       [existingFileName]="currentFileName"
 | 
					 | 
				
			||||||
                       (fileNameChanged)="currentFileName = $event"
 | 
					 | 
				
			||||||
                       formControlName="fileContent"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                       dropLabel="{{ 'import.drop-json-file-or' | translate }}"
 | 
					 | 
				
			||||||
                       accept=".json,application/json"
 | 
					 | 
				
			||||||
                       allowedExtensions="json">
 | 
					 | 
				
			||||||
        </tb-file-input>
 | 
					 | 
				
			||||||
      </div>
 | 
					 | 
				
			||||||
    </fieldset>
 | 
					    </fieldset>
 | 
				
			||||||
  </form>
 | 
					  </form>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
 | 
				
			|||||||
@ -22,7 +22,7 @@ import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms
 | 
				
			|||||||
import { ActionNotificationShow } from '@core/notification/notification.actions';
 | 
					import { ActionNotificationShow } from '@core/notification/notification.actions';
 | 
				
			||||||
import { TranslateService } from '@ngx-translate/core';
 | 
					import { TranslateService } from '@ngx-translate/core';
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  Dashboard,
 | 
					  Dashboard, DashboardInfo,
 | 
				
			||||||
  getDashboardAssignedCustomersText,
 | 
					  getDashboardAssignedCustomersText,
 | 
				
			||||||
  isCurrentPublicDashboardCustomer,
 | 
					  isCurrentPublicDashboardCustomer,
 | 
				
			||||||
  isPublicDashboard
 | 
					  isPublicDashboard
 | 
				
			||||||
@ -31,13 +31,14 @@ import { DashboardService } from '@core/http/dashboard.service';
 | 
				
			|||||||
import { EntityTableConfig } from '@home/models/entity/entities-table-config.models';
 | 
					import { EntityTableConfig } from '@home/models/entity/entities-table-config.models';
 | 
				
			||||||
import { isEqual } from '@core/utils';
 | 
					import { isEqual } from '@core/utils';
 | 
				
			||||||
import { EntityType } from '@shared/models/entity-type.models';
 | 
					import { EntityType } from '@shared/models/entity-type.models';
 | 
				
			||||||
 | 
					import {PageLink} from "@shared/models/page/page-link";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@Component({
 | 
					@Component({
 | 
				
			||||||
  selector: 'tb-dashboard-form',
 | 
					  selector: 'tb-dashboard-form',
 | 
				
			||||||
  templateUrl: './dashboard-form.component.html',
 | 
					  templateUrl: './dashboard-form.component.html',
 | 
				
			||||||
  styleUrls: ['./dashboard-form.component.scss']
 | 
					  styleUrls: ['./dashboard-form.component.scss']
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
export class DashboardFormComponent extends EntityComponent<Dashboard> {
 | 
					export class DashboardFormComponent extends EntityComponent<Dashboard, PageLink, DashboardInfo> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  dashboardScope: 'tenant' | 'customer' | 'customer_user' | 'edge';
 | 
					  dashboardScope: 'tenant' | 'customer' | 'customer_user' | 'edge';
 | 
				
			||||||
  customerId: string;
 | 
					  customerId: string;
 | 
				
			||||||
@ -45,7 +46,6 @@ export class DashboardFormComponent extends EntityComponent<Dashboard> {
 | 
				
			|||||||
  publicLink: string;
 | 
					  publicLink: string;
 | 
				
			||||||
  assignedCustomersText: string;
 | 
					  assignedCustomersText: string;
 | 
				
			||||||
  entityType = EntityType;
 | 
					  entityType = EntityType;
 | 
				
			||||||
  currentFileName: string = '';
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  constructor(protected store: Store<AppState>,
 | 
					  constructor(protected store: Store<AppState>,
 | 
				
			||||||
              protected translate: TranslateService,
 | 
					              protected translate: TranslateService,
 | 
				
			||||||
@ -85,7 +85,6 @@ export class DashboardFormComponent extends EntityComponent<Dashboard> {
 | 
				
			|||||||
      {
 | 
					      {
 | 
				
			||||||
        title: [entity ? entity.title : '', [Validators.required, Validators.maxLength(255)]],
 | 
					        title: [entity ? entity.title : '', [Validators.required, Validators.maxLength(255)]],
 | 
				
			||||||
        image: [entity ? entity.image : null],
 | 
					        image: [entity ? entity.image : null],
 | 
				
			||||||
        fileContent: [null],
 | 
					 | 
				
			||||||
        mobileHide: [entity ? entity.mobileHide : false],
 | 
					        mobileHide: [entity ? entity.mobileHide : false],
 | 
				
			||||||
        mobileOrder: [entity ? entity.mobileOrder : null, [Validators.pattern(/^-?[0-9]+$/)]],
 | 
					        mobileOrder: [entity ? entity.mobileOrder : null, [Validators.pattern(/^-?[0-9]+$/)]],
 | 
				
			||||||
        configuration: this.fb.group(
 | 
					        configuration: this.fb.group(
 | 
				
			||||||
@ -103,11 +102,9 @@ export class DashboardFormComponent extends EntityComponent<Dashboard> {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  updateForm(entity: Dashboard) {
 | 
					  updateForm(entity: Dashboard) {
 | 
				
			||||||
    this.currentFileName = '';
 | 
					 | 
				
			||||||
    this.updateFields(entity);
 | 
					    this.updateFields(entity);
 | 
				
			||||||
    this.entityForm.patchValue({title: entity.title});
 | 
					    this.entityForm.patchValue({title: entity.title});
 | 
				
			||||||
    this.entityForm.patchValue({image: entity.image});
 | 
					    this.entityForm.patchValue({image: entity.image});
 | 
				
			||||||
    this.entityForm.patchValue({fileContent: entity.fileContent || null});
 | 
					 | 
				
			||||||
    this.entityForm.patchValue({mobileHide: entity.mobileHide});
 | 
					    this.entityForm.patchValue({mobileHide: entity.mobileHide});
 | 
				
			||||||
    this.entityForm.patchValue({mobileOrder: entity.mobileOrder});
 | 
					    this.entityForm.patchValue({mobileOrder: entity.mobileOrder});
 | 
				
			||||||
    this.entityForm.patchValue({configuration: {description: entity.configuration ? entity.configuration.description : ''}});
 | 
					    this.entityForm.patchValue({configuration: {description: entity.configuration ? entity.configuration.description : ''}});
 | 
				
			||||||
@ -147,14 +144,4 @@ export class DashboardFormComponent extends EntityComponent<Dashboard> {
 | 
				
			|||||||
      this.publicLink = this.dashboardService.getPublicDashboardLink(entity);
 | 
					      this.publicLink = this.dashboardService.getPublicDashboardLink(entity);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					 | 
				
			||||||
  loadDataFromJsonContent(content: string): any {
 | 
					 | 
				
			||||||
    try {
 | 
					 | 
				
			||||||
      const importData = JSON.parse(content);
 | 
					 | 
				
			||||||
      return importData ? importData['configuration'] : importData;
 | 
					 | 
				
			||||||
    } catch (err) {
 | 
					 | 
				
			||||||
      this.store.dispatch(new ActionNotificationShow({message: err.message, type: 'error'}));
 | 
					 | 
				
			||||||
      return null;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -24,13 +24,15 @@ import { DashboardRoutingModule } from './dashboard-routing.module';
 | 
				
			|||||||
import { MakeDashboardPublicDialogComponent } from '@modules/home/pages/dashboard/make-dashboard-public-dialog.component';
 | 
					import { MakeDashboardPublicDialogComponent } from '@modules/home/pages/dashboard/make-dashboard-public-dialog.component';
 | 
				
			||||||
import { HomeComponentsModule } from '@modules/home/components/home-components.module';
 | 
					import { HomeComponentsModule } from '@modules/home/components/home-components.module';
 | 
				
			||||||
import { DashboardTabsComponent } from '@home/pages/dashboard/dashboard-tabs.component';
 | 
					import { DashboardTabsComponent } from '@home/pages/dashboard/dashboard-tabs.component';
 | 
				
			||||||
 | 
					import {ImportDashboardFileDialogComponent} from "@home/pages/dashboard/import-dashboard-file-dialog.component";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@NgModule({
 | 
					@NgModule({
 | 
				
			||||||
  declarations: [
 | 
					  declarations: [
 | 
				
			||||||
    DashboardFormComponent,
 | 
					    DashboardFormComponent,
 | 
				
			||||||
    DashboardTabsComponent,
 | 
					    DashboardTabsComponent,
 | 
				
			||||||
    ManageDashboardCustomersDialogComponent,
 | 
					    ManageDashboardCustomersDialogComponent,
 | 
				
			||||||
    MakeDashboardPublicDialogComponent
 | 
					    MakeDashboardPublicDialogComponent,
 | 
				
			||||||
 | 
					    ImportDashboardFileDialogComponent
 | 
				
			||||||
  ],
 | 
					  ],
 | 
				
			||||||
  imports: [
 | 
					  imports: [
 | 
				
			||||||
    CommonModule,
 | 
					    CommonModule,
 | 
				
			||||||
 | 
				
			|||||||
@ -14,9 +14,9 @@
 | 
				
			|||||||
/// limitations under the License.
 | 
					/// limitations under the License.
 | 
				
			||||||
///
 | 
					///
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { Injectable } from '@angular/core';
 | 
					import {Injectable} from '@angular/core';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { ActivatedRouteSnapshot, Router } from '@angular/router';
 | 
					import {ActivatedRouteSnapshot, Router} from '@angular/router';
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  CellActionDescriptor,
 | 
					  CellActionDescriptor,
 | 
				
			||||||
  checkBoxCell,
 | 
					  checkBoxCell,
 | 
				
			||||||
@ -26,20 +26,20 @@ import {
 | 
				
			|||||||
  GroupActionDescriptor,
 | 
					  GroupActionDescriptor,
 | 
				
			||||||
  HeaderActionDescriptor
 | 
					  HeaderActionDescriptor
 | 
				
			||||||
} from '@home/models/entity/entities-table-config.models';
 | 
					} from '@home/models/entity/entities-table-config.models';
 | 
				
			||||||
import { TranslateService } from '@ngx-translate/core';
 | 
					import {TranslateService} from '@ngx-translate/core';
 | 
				
			||||||
import { DatePipe } from '@angular/common';
 | 
					import {DatePipe} from '@angular/common';
 | 
				
			||||||
import { EntityType, entityTypeResources, entityTypeTranslations } from '@shared/models/entity-type.models';
 | 
					import {EntityType, entityTypeResources, entityTypeTranslations} from '@shared/models/entity-type.models';
 | 
				
			||||||
import { EntityAction } from '@home/models/entity/entity-component.models';
 | 
					import {EntityAction} from '@home/models/entity/entity-component.models';
 | 
				
			||||||
import { forkJoin, Observable, of } from 'rxjs';
 | 
					import {forkJoin, Observable, of} from 'rxjs';
 | 
				
			||||||
import { select, Store } from '@ngrx/store';
 | 
					import {select, Store} from '@ngrx/store';
 | 
				
			||||||
import { selectAuthUser } from '@core/auth/auth.selectors';
 | 
					import {selectAuthUser} from '@core/auth/auth.selectors';
 | 
				
			||||||
import { map, mergeMap, take, tap } from 'rxjs/operators';
 | 
					import {map, mergeMap, take, tap} from 'rxjs/operators';
 | 
				
			||||||
import { AppState } from '@core/core.state';
 | 
					import {AppState} from '@core/core.state';
 | 
				
			||||||
import { Authority } from '@app/shared/models/authority.enum';
 | 
					import {Authority} from '@app/shared/models/authority.enum';
 | 
				
			||||||
import { CustomerService } from '@core/http/customer.service';
 | 
					import {CustomerService} from '@core/http/customer.service';
 | 
				
			||||||
import { Customer } from '@app/shared/models/customer.model';
 | 
					import {Customer} from '@app/shared/models/customer.model';
 | 
				
			||||||
import { MatDialog } from '@angular/material/dialog';
 | 
					import {MatDialog} from '@angular/material/dialog';
 | 
				
			||||||
import { DialogService } from '@core/services/dialog.service';
 | 
					import {DialogService} from '@core/services/dialog.service';
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  AddEntitiesToCustomerDialogComponent,
 | 
					  AddEntitiesToCustomerDialogComponent,
 | 
				
			||||||
  AddEntitiesToCustomerDialogData
 | 
					  AddEntitiesToCustomerDialogData
 | 
				
			||||||
@ -52,8 +52,8 @@ import {
 | 
				
			|||||||
  isCurrentPublicDashboardCustomer,
 | 
					  isCurrentPublicDashboardCustomer,
 | 
				
			||||||
  isPublicDashboard
 | 
					  isPublicDashboard
 | 
				
			||||||
} from '@app/shared/models/dashboard.models';
 | 
					} from '@app/shared/models/dashboard.models';
 | 
				
			||||||
import { DashboardService } from '@app/core/http/dashboard.service';
 | 
					import {DashboardService} from '@app/core/http/dashboard.service';
 | 
				
			||||||
import { DashboardFormComponent } from '@modules/home/pages/dashboard/dashboard-form.component';
 | 
					import {DashboardFormComponent} from '@modules/home/pages/dashboard/dashboard-form.component';
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  ManageDashboardCustomersActionType,
 | 
					  ManageDashboardCustomersActionType,
 | 
				
			||||||
  ManageDashboardCustomersDialogComponent,
 | 
					  ManageDashboardCustomersDialogComponent,
 | 
				
			||||||
@ -63,25 +63,30 @@ import {
 | 
				
			|||||||
  MakeDashboardPublicDialogComponent,
 | 
					  MakeDashboardPublicDialogComponent,
 | 
				
			||||||
  MakeDashboardPublicDialogData
 | 
					  MakeDashboardPublicDialogData
 | 
				
			||||||
} from '@modules/home/pages/dashboard/make-dashboard-public-dialog.component';
 | 
					} from '@modules/home/pages/dashboard/make-dashboard-public-dialog.component';
 | 
				
			||||||
import { DashboardTabsComponent } from '@home/pages/dashboard/dashboard-tabs.component';
 | 
					import {DashboardTabsComponent} from '@home/pages/dashboard/dashboard-tabs.component';
 | 
				
			||||||
import { ImportExportService } from '@shared/import-export/import-export.service';
 | 
					import {ImportExportService} from '@shared/import-export/import-export.service';
 | 
				
			||||||
import { EdgeService } from '@core/http/edge.service';
 | 
					import {EdgeService} from '@core/http/edge.service';
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  AddEntitiesToEdgeDialogComponent,
 | 
					  AddEntitiesToEdgeDialogComponent,
 | 
				
			||||||
  AddEntitiesToEdgeDialogData
 | 
					  AddEntitiesToEdgeDialogData
 | 
				
			||||||
} from '@home/dialogs/add-entities-to-edge-dialog.component';
 | 
					} from '@home/dialogs/add-entities-to-edge-dialog.component';
 | 
				
			||||||
import { HomeDialogsService } from '@home/dialogs/home-dialogs.service';
 | 
					import {HomeDialogsService} from '@home/dialogs/home-dialogs.service';
 | 
				
			||||||
import { Widget } from '@shared/models/widget.models';
 | 
					import {Widget} from '@shared/models/widget.models';
 | 
				
			||||||
import { EntityAliases } from '@shared/models/alias.models';
 | 
					import {EntityAliases} from '@shared/models/alias.models';
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  EntityAliasesDialogComponent,
 | 
					  EntityAliasesDialogComponent,
 | 
				
			||||||
  EntityAliasesDialogData
 | 
					  EntityAliasesDialogData
 | 
				
			||||||
} from '@home/components/alias/entity-aliases-dialog.component';
 | 
					} from '@home/components/alias/entity-aliases-dialog.component';
 | 
				
			||||||
 | 
					import {
 | 
				
			||||||
 | 
					  DashboardInfoDialogData,
 | 
				
			||||||
 | 
					  ImportDashboardFileDialogComponent
 | 
				
			||||||
 | 
					} from "@home/pages/dashboard/import-dashboard-file-dialog.component";
 | 
				
			||||||
 | 
					import {PageLink} from "@shared/models/page/page-link";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@Injectable()
 | 
					@Injectable()
 | 
				
			||||||
export class DashboardsTableConfigResolver  {
 | 
					export class DashboardsTableConfigResolver {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private readonly config: EntityTableConfig<DashboardInfo | Dashboard> = new EntityTableConfig<DashboardInfo | Dashboard>();
 | 
					  private readonly config: EntityTableConfig<Dashboard, PageLink, DashboardInfo> = new EntityTableConfig<Dashboard, PageLink, DashboardInfo>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  constructor(private store: Store<AppState>,
 | 
					  constructor(private store: Store<AppState>,
 | 
				
			||||||
              private dashboardService: DashboardService,
 | 
					              private dashboardService: DashboardService,
 | 
				
			||||||
@ -110,7 +115,7 @@ export class DashboardsTableConfigResolver  {
 | 
				
			|||||||
    this.config.deleteEntitiesContent = () => this.translate.instant('dashboard.delete-dashboards-text');
 | 
					    this.config.deleteEntitiesContent = () => this.translate.instant('dashboard.delete-dashboards-text');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    this.config.loadEntity = id => this.dashboardService.getDashboard(id.id);
 | 
					    this.config.loadEntity = id => this.dashboardService.getDashboard(id.id);
 | 
				
			||||||
    this.config.saveEntity = dashboard => this.saveAndAssignDashboard(this.dashboardContentModification(dashboard) as DashboardSetup);
 | 
					    this.config.saveEntity = dashboard => this.saveAndAssignDashboard(dashboard as DashboardSetup);
 | 
				
			||||||
    this.config.onEntityAction = action => this.onDashboardAction(action);
 | 
					    this.config.onEntityAction = action => this.onDashboardAction(action);
 | 
				
			||||||
    this.config.detailsReadonly = () => (this.config.componentsData.dashboardScope === 'customer_user' ||
 | 
					    this.config.detailsReadonly = () => (this.config.componentsData.dashboardScope === 'customer_user' ||
 | 
				
			||||||
      this.config.componentsData.dashboardScope === 'edge_customer_user');
 | 
					      this.config.componentsData.dashboardScope === 'edge_customer_user');
 | 
				
			||||||
@ -179,20 +184,6 @@ export class DashboardsTableConfigResolver  {
 | 
				
			|||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private dashboardContentModification(dashboard: Dashboard): Dashboard{
 | 
					 | 
				
			||||||
    if(dashboard.fileContent != undefined){
 | 
					 | 
				
			||||||
      const { description, ...dashboardContent } = dashboard.fileContent;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      dashboard.configuration = {
 | 
					 | 
				
			||||||
        ...dashboard.configuration,
 | 
					 | 
				
			||||||
        ...dashboardContent
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    delete dashboard.fileContent;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return dashboard;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  configureColumns(dashboardScope: string): Array<EntityTableColumn<DashboardInfo>> {
 | 
					  configureColumns(dashboardScope: string): Array<EntityTableColumn<DashboardInfo>> {
 | 
				
			||||||
    const columns: Array<EntityTableColumn<DashboardInfo>> = [
 | 
					    const columns: Array<EntityTableColumn<DashboardInfo>> = [
 | 
				
			||||||
      new DateEntityTableColumn<DashboardInfo>('createdTime', 'common.created-time', this.datePipe, '150px'),
 | 
					      new DateEntityTableColumn<DashboardInfo>('createdTime', 'common.created-time', this.datePipe, '150px'),
 | 
				
			||||||
@ -389,7 +380,7 @@ export class DashboardsTableConfigResolver  {
 | 
				
			|||||||
    return actions;
 | 
					    return actions;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  openDashboard($event: Event, dashboard: DashboardInfo) {
 | 
					  openDashboard($event: Event, dashboard: Dashboard) {
 | 
				
			||||||
    if ($event) {
 | 
					    if ($event) {
 | 
				
			||||||
      $event.stopPropagation();
 | 
					      $event.stopPropagation();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -436,13 +427,27 @@ export class DashboardsTableConfigResolver  {
 | 
				
			|||||||
      ));
 | 
					      ));
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  exportDashboard($event: Event, dashboard: DashboardInfo) {
 | 
					  exportDashboard($event: Event, dashboard: Dashboard) {
 | 
				
			||||||
    if ($event) {
 | 
					    if ($event) {
 | 
				
			||||||
      $event.stopPropagation();
 | 
					      $event.stopPropagation();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    this.importExport.exportDashboard(dashboard.id.id);
 | 
					    this.importExport.exportDashboard(dashboard.id.id);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  importDashboardFile($event: Event, dashboard: Dashboard) {
 | 
				
			||||||
 | 
					    if ($event) {
 | 
				
			||||||
 | 
					      $event.stopPropagation();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return this.dialog.open<ImportDashboardFileDialogComponent, DashboardInfoDialogData,
 | 
				
			||||||
 | 
					      boolean>(ImportDashboardFileDialogComponent, {
 | 
				
			||||||
 | 
					      disableClose: true,
 | 
				
			||||||
 | 
					      panelClass: ['tb-dialog', 'tb-fullscreen-dialog'],
 | 
				
			||||||
 | 
					      data: {
 | 
				
			||||||
 | 
					        dashboard
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }).afterClosed();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  addDashboardsToCustomer($event: Event) {
 | 
					  addDashboardsToCustomer($event: Event) {
 | 
				
			||||||
    if ($event) {
 | 
					    if ($event) {
 | 
				
			||||||
      $event.stopPropagation();
 | 
					      $event.stopPropagation();
 | 
				
			||||||
@ -463,7 +468,7 @@ export class DashboardsTableConfigResolver  {
 | 
				
			|||||||
      });
 | 
					      });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  makePublic($event: Event, dashboard: DashboardInfo) {
 | 
					  makePublic($event: Event, dashboard: Dashboard) {
 | 
				
			||||||
    if ($event) {
 | 
					    if ($event) {
 | 
				
			||||||
      $event.stopPropagation();
 | 
					      $event.stopPropagation();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -484,7 +489,7 @@ export class DashboardsTableConfigResolver  {
 | 
				
			|||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  makePrivate($event: Event, dashboard: DashboardInfo) {
 | 
					  makePrivate($event: Event, dashboard: Dashboard) {
 | 
				
			||||||
    if ($event) {
 | 
					    if ($event) {
 | 
				
			||||||
      $event.stopPropagation();
 | 
					      $event.stopPropagation();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -506,7 +511,7 @@ export class DashboardsTableConfigResolver  {
 | 
				
			|||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  manageAssignedCustomers($event: Event, dashboard: DashboardInfo) {
 | 
					  manageAssignedCustomers($event: Event, dashboard: Dashboard) {
 | 
				
			||||||
    const assignedCustomersIds = dashboard.assignedCustomers ?
 | 
					    const assignedCustomersIds = dashboard.assignedCustomers ?
 | 
				
			||||||
      dashboard.assignedCustomers.map(customerInfo => customerInfo.customerId.id) : [];
 | 
					      dashboard.assignedCustomers.map(customerInfo => customerInfo.customerId.id) : [];
 | 
				
			||||||
    this.showManageAssignedCustomersDialog($event, [dashboard.id.id], 'manage', assignedCustomersIds);
 | 
					    this.showManageAssignedCustomersDialog($event, [dashboard.id.id], 'manage', assignedCustomersIds);
 | 
				
			||||||
@ -543,7 +548,7 @@ export class DashboardsTableConfigResolver  {
 | 
				
			|||||||
      });
 | 
					      });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  unassignFromCustomer($event: Event, dashboard: DashboardInfo, customerId: string) {
 | 
					  unassignFromCustomer($event: Event, dashboard: Dashboard, customerId: string) {
 | 
				
			||||||
    if ($event) {
 | 
					    if ($event) {
 | 
				
			||||||
      $event.stopPropagation();
 | 
					      $event.stopPropagation();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -593,7 +598,7 @@ export class DashboardsTableConfigResolver  {
 | 
				
			|||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  onDashboardAction(action: EntityAction<DashboardInfo>): boolean {
 | 
					  onDashboardAction(action: EntityAction<Dashboard>): boolean {
 | 
				
			||||||
    switch (action.action) {
 | 
					    switch (action.action) {
 | 
				
			||||||
      case 'open':
 | 
					      case 'open':
 | 
				
			||||||
        this.openDashboard(action.event, action.entity);
 | 
					        this.openDashboard(action.event, action.entity);
 | 
				
			||||||
@ -601,6 +606,9 @@ export class DashboardsTableConfigResolver  {
 | 
				
			|||||||
      case 'export':
 | 
					      case 'export':
 | 
				
			||||||
        this.exportDashboard(action.event, action.entity);
 | 
					        this.exportDashboard(action.event, action.entity);
 | 
				
			||||||
        return true;
 | 
					        return true;
 | 
				
			||||||
 | 
					      case 'import':
 | 
				
			||||||
 | 
					        this.importDashboardFile(action.event, action.entity);
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
      case 'makePublic':
 | 
					      case 'makePublic':
 | 
				
			||||||
        this.makePublic(action.event, action.entity);
 | 
					        this.makePublic(action.event, action.entity);
 | 
				
			||||||
        return true;
 | 
					        return true;
 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,73 @@
 | 
				
			|||||||
 | 
					<!--
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ThingsBoard, Inc. ("COMPANY") CONFIDENTIAL
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Copyright © 2016-2025 ThingsBoard, Inc. All Rights Reserved.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    NOTICE: All information contained herein is, and remains
 | 
				
			||||||
 | 
					    the property of ThingsBoard, Inc. and its suppliers,
 | 
				
			||||||
 | 
					    if any.  The intellectual and technical concepts contained
 | 
				
			||||||
 | 
					    herein are proprietary to ThingsBoard, Inc.
 | 
				
			||||||
 | 
					    and its suppliers and may be covered by U.S. and Foreign Patents,
 | 
				
			||||||
 | 
					    patents in process, and are protected by trade secret or copyright law.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Dissemination of this information or reproduction of this material is strictly forbidden
 | 
				
			||||||
 | 
					    unless prior written permission is obtained from COMPANY.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Access to the source code contained herein is hereby forbidden to anyone except current COMPANY employees,
 | 
				
			||||||
 | 
					    managers or contractors who have executed Confidentiality and Non-disclosure agreements
 | 
				
			||||||
 | 
					    explicitly covering such access.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    The copyright notice above does not evidence any actual or intended publication
 | 
				
			||||||
 | 
					    or disclosure  of  this source code, which includes
 | 
				
			||||||
 | 
					    information that is confidential and/or proprietary, and is a trade secret, of  COMPANY.
 | 
				
			||||||
 | 
					    ANY REPRODUCTION, MODIFICATION, DISTRIBUTION, PUBLIC  PERFORMANCE,
 | 
				
			||||||
 | 
					    OR PUBLIC DISPLAY OF OR THROUGH USE  OF THIS  SOURCE CODE  WITHOUT
 | 
				
			||||||
 | 
					    THE EXPRESS WRITTEN CONSENT OF COMPANY IS STRICTLY PROHIBITED,
 | 
				
			||||||
 | 
					    AND IN VIOLATION OF APPLICABLE LAWS AND INTERNATIONAL TREATIES.
 | 
				
			||||||
 | 
					    THE RECEIPT OR POSSESSION OF THIS SOURCE CODE AND/OR RELATED INFORMATION
 | 
				
			||||||
 | 
					    DOES NOT CONVEY OR IMPLY ANY RIGHTS TO REPRODUCE, DISCLOSE OR DISTRIBUTE ITS CONTENTS,
 | 
				
			||||||
 | 
					    OR TO MANUFACTURE, USE, OR SELL ANYTHING THAT IT  MAY DESCRIBE, IN WHOLE OR IN PART.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<form [formGroup]="uploadFileFormGroup" (ngSubmit)="save()" style="width: 800px;">
 | 
				
			||||||
 | 
					  <mat-toolbar color="primary">
 | 
				
			||||||
 | 
					    <h2>{{ 'dashboard.update-dashboard' | translate }}</h2>
 | 
				
			||||||
 | 
					    <span class="flex-1"></span>
 | 
				
			||||||
 | 
					    <button mat-icon-button
 | 
				
			||||||
 | 
					            (click)="cancel()"
 | 
				
			||||||
 | 
					            type="button">
 | 
				
			||||||
 | 
					      <mat-icon class="material-icons">close</mat-icon>
 | 
				
			||||||
 | 
					    </button>
 | 
				
			||||||
 | 
					  </mat-toolbar>
 | 
				
			||||||
 | 
					  <mat-progress-bar color="warn" mode="indeterminate" *ngIf="isLoading$ | async">
 | 
				
			||||||
 | 
					  </mat-progress-bar>
 | 
				
			||||||
 | 
					  <div style="height: 4px;" *ngIf="!(isLoading$ | async)"></div>
 | 
				
			||||||
 | 
					  <div mat-dialog-content>
 | 
				
			||||||
 | 
					      <tb-file-input [contentConvertFunction]="loadDataFromJsonContent"
 | 
				
			||||||
 | 
					                     [existingFileName]="currentFileName"
 | 
				
			||||||
 | 
					                     (fileNameChanged)="currentFileName = $event"
 | 
				
			||||||
 | 
					                     label="{{'dashboard.upload-file-to-update' | translate}}"
 | 
				
			||||||
 | 
					                     formControlName="file"
 | 
				
			||||||
 | 
					                     dropLabel="{{ 'import.drop-json-file-or' | translate }}"
 | 
				
			||||||
 | 
					                     accept=".json,application/json"
 | 
				
			||||||
 | 
					                     allowedExtensions="json">
 | 
				
			||||||
 | 
					      </tb-file-input>
 | 
				
			||||||
 | 
					  </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  <div mat-dialog-actions class="flex flex-row items-center justify-end">
 | 
				
			||||||
 | 
					    <button mat-button color="primary"
 | 
				
			||||||
 | 
					            type="button"
 | 
				
			||||||
 | 
					            [disabled]="(isLoading$ | async)"
 | 
				
			||||||
 | 
					            (click)="cancel()" cdkFocusInitial>
 | 
				
			||||||
 | 
					      {{ 'action.cancel' | translate }}
 | 
				
			||||||
 | 
					    </button>
 | 
				
			||||||
 | 
					    <button mat-raised-button color="primary"
 | 
				
			||||||
 | 
					            type="submit"
 | 
				
			||||||
 | 
					            [disabled]="(isLoading$ | async) || uploadFileFormGroup.invalid
 | 
				
			||||||
 | 
					            || !uploadFileFormGroup.dirty">
 | 
				
			||||||
 | 
					      {{ 'action.save' | translate }}
 | 
				
			||||||
 | 
					    </button>
 | 
				
			||||||
 | 
					  </div>
 | 
				
			||||||
 | 
					</form>
 | 
				
			||||||
@ -0,0 +1,106 @@
 | 
				
			|||||||
 | 
					///
 | 
				
			||||||
 | 
					/// ThingsBoard, Inc. ("COMPANY") CONFIDENTIAL
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// Copyright © 2016-2025 ThingsBoard, Inc. All Rights Reserved.
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// NOTICE: All information contained herein is, and remains
 | 
				
			||||||
 | 
					/// the property of ThingsBoard, Inc. and its suppliers,
 | 
				
			||||||
 | 
					/// if any.  The intellectual and technical concepts contained
 | 
				
			||||||
 | 
					/// herein are proprietary to ThingsBoard, Inc.
 | 
				
			||||||
 | 
					/// and its suppliers and may be covered by U.S. and Foreign Patents,
 | 
				
			||||||
 | 
					/// patents in process, and are protected by trade secret or copyright law.
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// Dissemination of this information or reproduction of this material is strictly forbidden
 | 
				
			||||||
 | 
					/// unless prior written permission is obtained from COMPANY.
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// Access to the source code contained herein is hereby forbidden to anyone except current COMPANY employees,
 | 
				
			||||||
 | 
					/// managers or contractors who have executed Confidentiality and Non-disclosure agreements
 | 
				
			||||||
 | 
					/// explicitly covering such access.
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// The copyright notice above does not evidence any actual or intended publication
 | 
				
			||||||
 | 
					/// or disclosure  of  this source code, which includes
 | 
				
			||||||
 | 
					/// information that is confidential and/or proprietary, and is a trade secret, of  COMPANY.
 | 
				
			||||||
 | 
					/// ANY REPRODUCTION, MODIFICATION, DISTRIBUTION, PUBLIC  PERFORMANCE,
 | 
				
			||||||
 | 
					/// OR PUBLIC DISPLAY OF OR THROUGH USE  OF THIS  SOURCE CODE  WITHOUT
 | 
				
			||||||
 | 
					/// THE EXPRESS WRITTEN CONSENT OF COMPANY IS STRICTLY PROHIBITED,
 | 
				
			||||||
 | 
					/// AND IN VIOLATION OF APPLICABLE LAWS AND INTERNATIONAL TREATIES.
 | 
				
			||||||
 | 
					/// THE RECEIPT OR POSSESSION OF THIS SOURCE CODE AND/OR RELATED INFORMATION
 | 
				
			||||||
 | 
					/// DOES NOT CONVEY OR IMPLY ANY RIGHTS TO REPRODUCE, DISCLOSE OR DISTRIBUTE ITS CONTENTS,
 | 
				
			||||||
 | 
					/// OR TO MANUFACTURE, USE, OR SELL ANYTHING THAT IT  MAY DESCRIBE, IN WHOLE OR IN PART.
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import {Component, Inject, OnInit} from '@angular/core';
 | 
				
			||||||
 | 
					import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog';
 | 
				
			||||||
 | 
					import {Store} from '@ngrx/store';
 | 
				
			||||||
 | 
					import {AppState} from '@core/core.state';
 | 
				
			||||||
 | 
					import {UntypedFormBuilder, UntypedFormGroup} from '@angular/forms';
 | 
				
			||||||
 | 
					import {DashboardService} from '@core/http/dashboard.service';
 | 
				
			||||||
 | 
					import {Dashboard, DashboardInfo} from '@app/shared/models/dashboard.models';
 | 
				
			||||||
 | 
					import {ActionNotificationShow} from '@core/notification/notification.actions';
 | 
				
			||||||
 | 
					import {TranslateService} from '@ngx-translate/core';
 | 
				
			||||||
 | 
					import {DialogComponent} from '@shared/components/dialog.component';
 | 
				
			||||||
 | 
					import {Router} from '@angular/router';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface DashboardInfoDialogData {
 | 
				
			||||||
 | 
					  dashboard: Dashboard;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Component({
 | 
				
			||||||
 | 
					  selector: 'tb-import-dashboard-file-dialog',
 | 
				
			||||||
 | 
					  templateUrl: './import-dashboard-file-dialog.component.html',
 | 
				
			||||||
 | 
					  styleUrls: []
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					export class ImportDashboardFileDialogComponent extends DialogComponent<ImportDashboardFileDialogComponent> implements OnInit {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  dashboard: Dashboard;
 | 
				
			||||||
 | 
					  currentFileName: string = '';
 | 
				
			||||||
 | 
					  uploadFileFormGroup: UntypedFormGroup;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  constructor(protected store: Store<AppState>,
 | 
				
			||||||
 | 
					              protected router: Router,
 | 
				
			||||||
 | 
					              @Inject(MAT_DIALOG_DATA) public data: DashboardInfoDialogData,
 | 
				
			||||||
 | 
					              public translate: TranslateService,
 | 
				
			||||||
 | 
					              private dashboardService: DashboardService,
 | 
				
			||||||
 | 
					              public dialogRef: MatDialogRef<ImportDashboardFileDialogComponent>,
 | 
				
			||||||
 | 
					              public fb: UntypedFormBuilder) {
 | 
				
			||||||
 | 
					    super(store, router, dialogRef);
 | 
				
			||||||
 | 
					    this.dashboard = data.dashboard;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ngOnInit(): void {
 | 
				
			||||||
 | 
					    this.uploadFileFormGroup = this.fb.group({
 | 
				
			||||||
 | 
					      file: [null]
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  cancel(): void {
 | 
				
			||||||
 | 
					    this.dialogRef.close();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  save(){
 | 
				
			||||||
 | 
					    const fileControl = this.uploadFileFormGroup.get('file');
 | 
				
			||||||
 | 
					    if(!fileControl || !fileControl.value){
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const dashboardContent = {
 | 
				
			||||||
 | 
					      ...fileControl.value,
 | 
				
			||||||
 | 
					      description: this.dashboard.configuration.description
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    this.dashboard.configuration = dashboardContent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    this.dashboardService.saveDashboard(this.dashboard).subscribe(()=>{
 | 
				
			||||||
 | 
					      this.dialogRef.close(true);
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  loadDataFromJsonContent(content: string): any {
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					      const importData = JSON.parse(content);
 | 
				
			||||||
 | 
					      return importData ? importData['configuration'] : importData;
 | 
				
			||||||
 | 
					    } catch (err) {
 | 
				
			||||||
 | 
					      this.store.dispatch(new ActionNotificationShow({message: err.message, type: 'error'}));
 | 
				
			||||||
 | 
					      return null;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1348,6 +1348,7 @@
 | 
				
			|||||||
        "mobile-hide": "Hide dashboard in mobile application",
 | 
					        "mobile-hide": "Hide dashboard in mobile application",
 | 
				
			||||||
        "update-image": "Update dashboard image",
 | 
					        "update-image": "Update dashboard image",
 | 
				
			||||||
        "update-dashboard": "Update the dashboard",
 | 
					        "update-dashboard": "Update the dashboard",
 | 
				
			||||||
 | 
					        "upload-file-to-update": "Upload file to update",
 | 
				
			||||||
        "take-screenshot": "Take screenshot",
 | 
					        "take-screenshot": "Take screenshot",
 | 
				
			||||||
        "select-widget-title": "Select widget",
 | 
					        "select-widget-title": "Select widget",
 | 
				
			||||||
        "select-widget-value": "{{title}}: select widget",
 | 
					        "select-widget-value": "{{title}}: select widget",
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user