Refactoring to simplify reading and merge
This commit is contained in:
		
							parent
							
								
									ae8564110a
								
							
						
					
					
						commit
						712e756e58
					
				@ -21,11 +21,13 @@ export interface SysParamsState {
 | 
			
		||||
  allowedDashboardIds: string[];
 | 
			
		||||
  edgesSupportEnabled: boolean;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface AuthPayload extends SysParamsState {
 | 
			
		||||
  authUser: AuthUser;
 | 
			
		||||
  userDetails: User;
 | 
			
		||||
  forceFullscreen: boolean;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface AuthState extends AuthPayload {
 | 
			
		||||
  isAuthenticated: boolean;
 | 
			
		||||
  isUserLoaded: boolean;
 | 
			
		||||
 | 
			
		||||
@ -295,9 +295,9 @@ export class RuleChainService {
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public getEdgeRuleChains(edgeId: string, pageLink: PageLink, config?:RequestConfig): Observable<PageData<RuleChain>> {
 | 
			
		||||
  public getEdgeRuleChains(edgeId: string, pageLink: PageLink, config?: RequestConfig): Observable<PageData<RuleChain>> {
 | 
			
		||||
    return this.http.get<PageData<RuleChain>>(`/api/edge/${edgeId}/ruleChains${pageLink.toQuery()}`,
 | 
			
		||||
      defaultHttpOptionsFromConfig(config) )
 | 
			
		||||
      defaultHttpOptionsFromConfig(config));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public assignRuleChainToEdge(edgeId: string, ruleChainId: string, config?: RequestConfig): Observable<RuleChain> {
 | 
			
		||||
 | 
			
		||||
@ -26,7 +26,6 @@ import { NULL_UUID } from '@shared/models/id/has-uuid';
 | 
			
		||||
import { ActionNotificationShow } from '@core/notification/notification.actions';
 | 
			
		||||
import { generateSecret, guid } from '@core/utils';
 | 
			
		||||
import { EntityTableConfig } from '@home/models/entity/entities-table-config.models';
 | 
			
		||||
import { WINDOW } from '@core/services/window.service';
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
  selector: 'tb-edge',
 | 
			
		||||
@ -43,15 +42,14 @@ export class EdgeComponent extends EntityComponent<EdgeInfo> {
 | 
			
		||||
              protected translate: TranslateService,
 | 
			
		||||
              @Inject('entity') protected entityValue: EdgeInfo,
 | 
			
		||||
              @Inject('entitiesTableConfig') protected entitiesTableConfigValue: EntityTableConfig<EdgeInfo>,
 | 
			
		||||
              public fb: FormBuilder,
 | 
			
		||||
              @Inject(WINDOW) protected window: Window) {
 | 
			
		||||
              public fb: FormBuilder) {
 | 
			
		||||
    super(store, fb, entityValue, entitiesTableConfigValue);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ngOnInit() {
 | 
			
		||||
    this.edgeScope = this.entitiesTableConfig.componentsData.edgeScope;
 | 
			
		||||
    this.entityForm.patchValue({
 | 
			
		||||
      cloudEndpoint: this.window.location.origin
 | 
			
		||||
      cloudEndpoint: window.location.origin
 | 
			
		||||
    });
 | 
			
		||||
    super.ngOnInit();
 | 
			
		||||
  }
 | 
			
		||||
@ -94,7 +92,7 @@ export class EdgeComponent extends EntityComponent<EdgeInfo> {
 | 
			
		||||
      name: entity.name,
 | 
			
		||||
      type: entity.type,
 | 
			
		||||
      label: entity.label,
 | 
			
		||||
      cloudEndpoint: entity.cloudEndpoint ? entity.cloudEndpoint : this.window.location.origin,
 | 
			
		||||
      cloudEndpoint: entity.cloudEndpoint ? entity.cloudEndpoint : window.location.origin,
 | 
			
		||||
      edgeLicenseKey: entity.edgeLicenseKey,
 | 
			
		||||
      routingKey: entity.routingKey,
 | 
			
		||||
      secret: entity.secret,
 | 
			
		||||
 | 
			
		||||
@ -49,6 +49,7 @@ import { isUndefined } from '@core/utils';
 | 
			
		||||
import { PageLink } from '@shared/models/page/page-link';
 | 
			
		||||
import { Edge } from '@shared/models/edge.models';
 | 
			
		||||
import { mergeMap } from 'rxjs/operators';
 | 
			
		||||
import { PageData } from '@shared/models/page/page-data';
 | 
			
		||||
 | 
			
		||||
@Injectable()
 | 
			
		||||
export class RuleChainsTableConfigResolver implements Resolve<EntityTableConfig<RuleChain>> {
 | 
			
		||||
@ -83,25 +84,27 @@ export class RuleChainsTableConfigResolver implements Resolve<EntityTableConfig<
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  resolve(route: ActivatedRouteSnapshot): EntityTableConfig<RuleChain> {
 | 
			
		||||
    const routeParams = route.params;
 | 
			
		||||
    const edgeId = route.params?.edgeId;
 | 
			
		||||
    const ruleChainScope = route.data?.ruleChainsType ? route.data?.ruleChainsType : 'tenant';
 | 
			
		||||
    this.config.componentsData = {
 | 
			
		||||
      ruleChainScope: route.data.ruleChainsType,
 | 
			
		||||
      edgeId: routeParams.edgeId
 | 
			
		||||
      ruleChainScope,
 | 
			
		||||
      edgeId
 | 
			
		||||
    };
 | 
			
		||||
    this.config.columns = this.configureEntityTableColumns(this.config.componentsData.ruleChainScope);
 | 
			
		||||
    this.configureEntityFunctions(this.config.componentsData.ruleChainScope);
 | 
			
		||||
    this.config.groupActionDescriptors = this.configureGroupActions(this.config.componentsData.ruleChainScope);
 | 
			
		||||
    this.config.addActionDescriptors = this.configureAddActions(this.config.componentsData.ruleChainScope);
 | 
			
		||||
    this.config.cellActionDescriptors = this.configureCellActions(this.config.componentsData.ruleChainScope);
 | 
			
		||||
    if (this.config.componentsData.ruleChainScope === 'tenant' || this.config.componentsData.ruleChainScope === 'edges') {
 | 
			
		||||
    this.config.columns = this.configureEntityTableColumns(ruleChainScope);
 | 
			
		||||
    this.config.entitiesFetchFunction = this.configureEntityFunctions(ruleChainScope, edgeId);
 | 
			
		||||
    this.config.groupActionDescriptors = this.configureGroupActions(ruleChainScope);
 | 
			
		||||
    this.config.addActionDescriptors = this.configureAddActions(ruleChainScope);
 | 
			
		||||
    this.config.cellActionDescriptors = this.configureCellActions(ruleChainScope);
 | 
			
		||||
    if (ruleChainScope === 'tenant' || ruleChainScope === 'edges') {
 | 
			
		||||
      this.config.entitySelectionEnabled = ruleChain => ruleChain && !ruleChain.root;
 | 
			
		||||
      this.config.deleteEnabled = (ruleChain) => ruleChain && !ruleChain.root;
 | 
			
		||||
      this.config.entitiesDeleteEnabled = true;
 | 
			
		||||
    } else if (this.config.componentsData.ruleChainScope === 'edge') {
 | 
			
		||||
      this.config.entitySelectionEnabled = ruleChain => this.config.componentsData.edge.rootRuleChainId.id != ruleChain.id.id;
 | 
			
		||||
      this.edgeService.getEdge(this.config.componentsData.edgeId).subscribe(edge => {
 | 
			
		||||
      this.config.tableTitle = this.configureTableTitle(ruleChainScope, null);
 | 
			
		||||
    } else if (ruleChainScope === 'edge') {
 | 
			
		||||
      this.config.entitySelectionEnabled = ruleChain => this.config.componentsData.edge.rootRuleChainId.id !== ruleChain.id.id;
 | 
			
		||||
      this.edgeService.getEdge(edgeId).subscribe(edge => {
 | 
			
		||||
        this.config.componentsData.edge = edge;
 | 
			
		||||
        this.config.tableTitle = edge.name + ': ' + this.translate.instant('edge.rulechains');
 | 
			
		||||
        this.config.tableTitle = this.configureTableTitle(ruleChainScope, edge);
 | 
			
		||||
      });
 | 
			
		||||
      this.config.entitiesDeleteEnabled = false;
 | 
			
		||||
    }
 | 
			
		||||
@ -110,24 +113,23 @@ export class RuleChainsTableConfigResolver implements Resolve<EntityTableConfig<
 | 
			
		||||
 | 
			
		||||
  configureEntityTableColumns(ruleChainScope: string): Array<EntityColumn<RuleChain>> {
 | 
			
		||||
    const columns: Array<EntityColumn<RuleChain>> = [];
 | 
			
		||||
    columns.push(
 | 
			
		||||
      new DateEntityTableColumn<RuleChain>('createdTime', 'common.created-time', this.datePipe, '150px'),
 | 
			
		||||
      new EntityTableColumn<RuleChain>('name', 'rulechain.name', '100%')
 | 
			
		||||
    );
 | 
			
		||||
    if (ruleChainScope === 'tenant' || ruleChainScope === 'edge') {
 | 
			
		||||
      columns.push(
 | 
			
		||||
        new DateEntityTableColumn<RuleChain>('createdTime', 'common.created-time', this.datePipe, '150px'),
 | 
			
		||||
        new EntityTableColumn<RuleChain>('name', 'rulechain.name', '100%'),
 | 
			
		||||
        new EntityTableColumn<RuleChain>('root', 'rulechain.root', '60px',
 | 
			
		||||
          entity => {
 | 
			
		||||
          if (ruleChainScope === 'edge') {
 | 
			
		||||
            return checkBoxCell((this.config.componentsData.edge.rootRuleChainId.id == entity.id.id));
 | 
			
		||||
            return checkBoxCell((this.config.componentsData.edge.rootRuleChainId.id === entity.id.id));
 | 
			
		||||
          } else {
 | 
			
		||||
            return checkBoxCell(entity.root);
 | 
			
		||||
          }
 | 
			
		||||
          })
 | 
			
		||||
      );
 | 
			
		||||
    }
 | 
			
		||||
    if (ruleChainScope === 'edges') {
 | 
			
		||||
    } else if (ruleChainScope === 'edges') {
 | 
			
		||||
      columns.push(
 | 
			
		||||
        new DateEntityTableColumn<RuleChain>('createdTime', 'common.created-time', this.datePipe, '150px'),
 | 
			
		||||
        new EntityTableColumn<RuleChain>('name', 'rulechain.name', '100%'),
 | 
			
		||||
        new EntityTableColumn<RuleChain>('root', 'rulechain.edge-template-root', '60px',
 | 
			
		||||
          entity => {
 | 
			
		||||
            return checkBoxCell(entity.root);
 | 
			
		||||
@ -157,7 +159,7 @@ export class RuleChainsTableConfigResolver implements Resolve<EntityTableConfig<
 | 
			
		||||
          isEnabled: () => true,
 | 
			
		||||
          onAction: ($event) => this.importRuleChain($event)
 | 
			
		||||
        }
 | 
			
		||||
      )
 | 
			
		||||
      );
 | 
			
		||||
    }
 | 
			
		||||
    if (ruleChainScope === 'edge') {
 | 
			
		||||
      actions.push(
 | 
			
		||||
@ -167,20 +169,28 @@ export class RuleChainsTableConfigResolver implements Resolve<EntityTableConfig<
 | 
			
		||||
          isEnabled: () => true,
 | 
			
		||||
          onAction: ($event) => this.addRuleChainsToEdge($event)
 | 
			
		||||
        }
 | 
			
		||||
      )
 | 
			
		||||
      );
 | 
			
		||||
    }
 | 
			
		||||
    return actions;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  configureEntityFunctions(ruleChainScope: string): void {
 | 
			
		||||
  configureEntityFunctions(ruleChainScope: string, edgeId: string): (pageLink) => Observable<PageData<RuleChain>> {
 | 
			
		||||
    if (ruleChainScope === 'tenant') {
 | 
			
		||||
      this.config.tableTitle = this.translate.instant('rulechain.rulechains');
 | 
			
		||||
      this.config.entitiesFetchFunction = pageLink => this.fetchRuleChains(pageLink);
 | 
			
		||||
      return pageLink => this.fetchRuleChains(pageLink);
 | 
			
		||||
    } else if (ruleChainScope === 'edges') {
 | 
			
		||||
      this.config.tableTitle = this.translate.instant('edge.rulechain-templates');
 | 
			
		||||
      this.config.entitiesFetchFunction = pageLink => this.fetchEdgeRuleChains(pageLink);
 | 
			
		||||
      return pageLink => this.fetchEdgeRuleChains(pageLink);
 | 
			
		||||
    } else if (ruleChainScope === 'edge') {
 | 
			
		||||
      this.config.entitiesFetchFunction = pageLink => this.ruleChainService.getEdgeRuleChains(this.config.componentsData.edgeId, pageLink);
 | 
			
		||||
      return pageLink => this.ruleChainService.getEdgeRuleChains(edgeId, pageLink);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  configureTableTitle(ruleChainScope: string, edge: Edge): string {
 | 
			
		||||
    if (ruleChainScope === 'tenant') {
 | 
			
		||||
      return this.translate.instant('rulechain.rulechains');
 | 
			
		||||
    } else if (ruleChainScope === 'edges') {
 | 
			
		||||
      return this.translate.instant('edge.rulechain-templates');
 | 
			
		||||
    } else if (ruleChainScope === 'edge') {
 | 
			
		||||
      return this.config.tableTitle = edge.name + ': ' + this.translate.instant('edge.rulechains');
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@ -194,7 +204,7 @@ export class RuleChainsTableConfigResolver implements Resolve<EntityTableConfig<
 | 
			
		||||
          isEnabled: true,
 | 
			
		||||
          onAction: ($event, entities) => this.unassignRuleChainsFromEdge($event, entities)
 | 
			
		||||
        }
 | 
			
		||||
      )
 | 
			
		||||
      );
 | 
			
		||||
    }
 | 
			
		||||
    return actions;
 | 
			
		||||
  }
 | 
			
		||||
@ -215,7 +225,7 @@ export class RuleChainsTableConfigResolver implements Resolve<EntityTableConfig<
 | 
			
		||||
          isEnabled: () => true,
 | 
			
		||||
          onAction: ($event, entity) => this.exportRuleChain($event, entity)
 | 
			
		||||
        }
 | 
			
		||||
      )
 | 
			
		||||
      );
 | 
			
		||||
      if (ruleChainScope === 'tenant') {
 | 
			
		||||
        actions.push(
 | 
			
		||||
          {
 | 
			
		||||
@ -224,7 +234,7 @@ export class RuleChainsTableConfigResolver implements Resolve<EntityTableConfig<
 | 
			
		||||
            isEnabled: (entity) => this.isNonRootRuleChain(entity),
 | 
			
		||||
            onAction: ($event, entity) => this.setRootRuleChain($event, entity)
 | 
			
		||||
          }
 | 
			
		||||
        )
 | 
			
		||||
        );
 | 
			
		||||
      }
 | 
			
		||||
      if (ruleChainScope === 'edges') {
 | 
			
		||||
        actions.push(
 | 
			
		||||
@ -246,7 +256,7 @@ export class RuleChainsTableConfigResolver implements Resolve<EntityTableConfig<
 | 
			
		||||
            isEnabled: (entity) => this.isAutoAssignToEdgeRuleChain(entity),
 | 
			
		||||
            onAction: ($event, entity) => this.unsetAutoAssignToEdgeRuleChain($event, entity)
 | 
			
		||||
          }
 | 
			
		||||
        )
 | 
			
		||||
        );
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    if (ruleChainScope === 'edge') {
 | 
			
		||||
@ -260,10 +270,10 @@ export class RuleChainsTableConfigResolver implements Resolve<EntityTableConfig<
 | 
			
		||||
        {
 | 
			
		||||
          name: this.translate.instant('edge.unassign-from-edge'),
 | 
			
		||||
          icon: 'assignment_return',
 | 
			
		||||
          isEnabled: (entity) => entity.id.id != this.config.componentsData.edge.rootRuleChainId.id,
 | 
			
		||||
          isEnabled: (entity) => entity.id.id !== this.config.componentsData.edge.rootRuleChainId.id,
 | 
			
		||||
          onAction: ($event, entity) => this.unassignFromEdge($event, entity)
 | 
			
		||||
        }
 | 
			
		||||
      )
 | 
			
		||||
      );
 | 
			
		||||
    }
 | 
			
		||||
    return actions;
 | 
			
		||||
  }
 | 
			
		||||
@ -298,9 +308,9 @@ export class RuleChainsTableConfigResolver implements Resolve<EntityTableConfig<
 | 
			
		||||
 | 
			
		||||
  saveRuleChain(ruleChain: RuleChain) {
 | 
			
		||||
    if (isUndefined(ruleChain.type)) {
 | 
			
		||||
      if (this.config.componentsData.ruleChainScope == 'tenant') {
 | 
			
		||||
      if (this.config.componentsData.ruleChainScope === 'tenant') {
 | 
			
		||||
        ruleChain.type = RuleChainType.CORE;
 | 
			
		||||
      } else if (this.config.componentsData.ruleChainScope == 'edges') {
 | 
			
		||||
      } else if (this.config.componentsData.ruleChainScope === 'edges') {
 | 
			
		||||
        ruleChain.type = RuleChainType.EDGE;
 | 
			
		||||
      } else {
 | 
			
		||||
        // safe fallback to default core type
 | 
			
		||||
@ -335,13 +345,13 @@ export class RuleChainsTableConfigResolver implements Resolve<EntityTableConfig<
 | 
			
		||||
                this.config.componentsData.edge = edge;
 | 
			
		||||
                this.config.table.updateData();
 | 
			
		||||
              }
 | 
			
		||||
            )
 | 
			
		||||
            );
 | 
			
		||||
          } else {
 | 
			
		||||
            this.ruleChainService.setRootRuleChain(ruleChain.id.id).subscribe(
 | 
			
		||||
              () => {
 | 
			
		||||
                this.config.table.updateData();
 | 
			
		||||
              }
 | 
			
		||||
            )
 | 
			
		||||
            );
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
@ -415,14 +425,14 @@ export class RuleChainsTableConfigResolver implements Resolve<EntityTableConfig<
 | 
			
		||||
          this.edgeService.findMissingToRelatedRuleChains(this.config.componentsData.edgeId).subscribe(
 | 
			
		||||
            (missingRuleChains) => {
 | 
			
		||||
              if (missingRuleChains && Object.keys(missingRuleChains).length > 0) {
 | 
			
		||||
                let formattedMissingRuleChains: Array<string> = new Array<string>();
 | 
			
		||||
                const formattedMissingRuleChains: Array<string> = new Array<string>();
 | 
			
		||||
                for (const missingRuleChain of Object.keys(missingRuleChains)) {
 | 
			
		||||
                  const arrayOfMissingRuleChains = missingRuleChains[missingRuleChain];
 | 
			
		||||
                  const tmp = "- '" + missingRuleChain + "': '" + arrayOfMissingRuleChains.join("', ") + "'";
 | 
			
		||||
                  const tmp = '- \'' + missingRuleChain + '\': \'' + arrayOfMissingRuleChains.join('\', ') + '\'';
 | 
			
		||||
                  formattedMissingRuleChains.push(tmp);
 | 
			
		||||
                }
 | 
			
		||||
                const message = this.translate.instant('edge.missing-related-rule-chains-text',
 | 
			
		||||
                  {missingRuleChains: formattedMissingRuleChains.join("<br>")});
 | 
			
		||||
                  {missingRuleChains: formattedMissingRuleChains.join('<br>')});
 | 
			
		||||
                this.dialogService.alert(this.translate.instant('edge.missing-related-rule-chains-title'),
 | 
			
		||||
                  message, this.translate.instant('action.close'), true).subscribe(
 | 
			
		||||
                  () => {
 | 
			
		||||
@ -433,10 +443,10 @@ export class RuleChainsTableConfigResolver implements Resolve<EntityTableConfig<
 | 
			
		||||
                this.config.table.updateData();
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
          )
 | 
			
		||||
          );
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    )
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  unassignFromEdge($event: Event, ruleChain: RuleChain) {
 | 
			
		||||
@ -505,7 +515,7 @@ export class RuleChainsTableConfigResolver implements Resolve<EntityTableConfig<
 | 
			
		||||
          () => {
 | 
			
		||||
            this.config.table.updateData();
 | 
			
		||||
          }
 | 
			
		||||
        )
 | 
			
		||||
        );
 | 
			
		||||
      }
 | 
			
		||||
      }
 | 
			
		||||
    );
 | 
			
		||||
@ -527,7 +537,7 @@ export class RuleChainsTableConfigResolver implements Resolve<EntityTableConfig<
 | 
			
		||||
            () => {
 | 
			
		||||
              this.config.table.updateData();
 | 
			
		||||
            }
 | 
			
		||||
          )
 | 
			
		||||
          );
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    );
 | 
			
		||||
@ -536,7 +546,7 @@ export class RuleChainsTableConfigResolver implements Resolve<EntityTableConfig<
 | 
			
		||||
  isNonRootRuleChain(ruleChain: RuleChain) {
 | 
			
		||||
    if (this.config.componentsData.ruleChainScope === 'edge') {
 | 
			
		||||
      return this.config.componentsData.edge.rootRuleChainId &&
 | 
			
		||||
        this.config.componentsData.edge.rootRuleChainId.id != ruleChain.id.id;
 | 
			
		||||
        this.config.componentsData.edge.rootRuleChainId.id !== ruleChain.id.id;
 | 
			
		||||
    }
 | 
			
		||||
    return !ruleChain.root;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@ -1,93 +0,0 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Copyright © 2016-2020 The Thingsboard Authors
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
md-list.tb-edge-downlinks-table {
 | 
			
		||||
  padding: 0;
 | 
			
		||||
 | 
			
		||||
  md-list-item {
 | 
			
		||||
    padding: 0;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .tb-row {
 | 
			
		||||
    height: 48px;
 | 
			
		||||
    padding: 0;
 | 
			
		||||
    overflow: hidden;
 | 
			
		||||
 | 
			
		||||
    .tb-cell {
 | 
			
		||||
      text-overflow: ellipsis;
 | 
			
		||||
 | 
			
		||||
      &.tb-scroll {
 | 
			
		||||
        overflow-x: auto;
 | 
			
		||||
        overflow-y: hidden;
 | 
			
		||||
        white-space: nowrap;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      &.tb-nowrap {
 | 
			
		||||
        white-space: nowrap;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .tb-row:hover {
 | 
			
		||||
    background-color: #eee;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .tb-header:hover {
 | 
			
		||||
    background: none;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .tb-header {
 | 
			
		||||
    .tb-cell {
 | 
			
		||||
      font-size: 12px;
 | 
			
		||||
      font-weight: 700;
 | 
			
		||||
      color: rgba(0, 0, 0, .54);
 | 
			
		||||
      white-space: nowrap;
 | 
			
		||||
      background: none;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .tb-cell {
 | 
			
		||||
    &:first-child {
 | 
			
		||||
      padding-left: 14px;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &:last-child {
 | 
			
		||||
      padding-right: 14px;
 | 
			
		||||
    }
 | 
			
		||||
    padding: 0 6px;
 | 
			
		||||
    margin: auto 0;
 | 
			
		||||
    overflow: hidden;
 | 
			
		||||
    font-size: 13px;
 | 
			
		||||
    color: rgba(0, 0, 0, .87);
 | 
			
		||||
    text-align: left;
 | 
			
		||||
    vertical-align: middle;
 | 
			
		||||
 | 
			
		||||
    .md-button {
 | 
			
		||||
      padding: 0;
 | 
			
		||||
      margin: 0;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .tb-cell.tb-number {
 | 
			
		||||
    text-align: right;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#tb-edge-downlinks-content {
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  min-width: 400px;
 | 
			
		||||
  height: 100%;
 | 
			
		||||
  min-height: 50px;
 | 
			
		||||
}
 | 
			
		||||
@ -1,92 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright © 2016-2020 The Thingsboard Authors
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
import $ from 'jquery';
 | 
			
		||||
import 'brace/ext/language_tools';
 | 
			
		||||
import 'brace/ext/searchbox';
 | 
			
		||||
import 'brace/mode/java';
 | 
			
		||||
import 'brace/theme/github';
 | 
			
		||||
import beautify from 'js-beautify';
 | 
			
		||||
 | 
			
		||||
/* eslint-disable angular/angularelement */
 | 
			
		||||
 | 
			
		||||
const js_beautify = beautify.js;
 | 
			
		||||
 | 
			
		||||
/*@ngInject*/
 | 
			
		||||
export default function EdgeDownlinksContentDialogController($mdDialog, types, content, contentType, title, showingCallback) {
 | 
			
		||||
 | 
			
		||||
    var vm = this;
 | 
			
		||||
 | 
			
		||||
    showingCallback.onShowing = function(scope, element) {
 | 
			
		||||
        updateEditorSize(element);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vm.content = content;
 | 
			
		||||
    vm.title = title;
 | 
			
		||||
 | 
			
		||||
    var mode;
 | 
			
		||||
    if (contentType) {
 | 
			
		||||
        mode = types.contentType[contentType].code;
 | 
			
		||||
        if (contentType == types.contentType.JSON.value && vm.content) {
 | 
			
		||||
            vm.content = js_beautify(vm.content, {indent_size: 4});
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        mode = 'java';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vm.contentOptions = {
 | 
			
		||||
        useWrapMode: false,
 | 
			
		||||
        mode: mode,
 | 
			
		||||
        showGutter: false,
 | 
			
		||||
        showPrintMargin: false,
 | 
			
		||||
        theme: 'github',
 | 
			
		||||
        advanced: {
 | 
			
		||||
            enableSnippets: false,
 | 
			
		||||
            enableBasicAutocompletion: false,
 | 
			
		||||
            enableLiveAutocompletion: false
 | 
			
		||||
        },
 | 
			
		||||
        onLoad: function (_ace) {
 | 
			
		||||
            vm.editor = _ace;
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    function updateEditorSize(element) {
 | 
			
		||||
        var newHeight = 400;
 | 
			
		||||
        var newWidth = 600;
 | 
			
		||||
        if (vm.content && vm.content.length > 0) {
 | 
			
		||||
            var lines = vm.content.split('\n');
 | 
			
		||||
            newHeight = 16 * lines.length + 16;
 | 
			
		||||
            var maxLineLength = 0;
 | 
			
		||||
            for (var i = 0; i < lines.length; i++) {
 | 
			
		||||
                var line = lines[i].replace(/\t/g, '    ').replace(/\n/g, '');
 | 
			
		||||
                var lineLength = line.length;
 | 
			
		||||
                maxLineLength = Math.max(maxLineLength, lineLength);
 | 
			
		||||
            }
 | 
			
		||||
            newWidth = 8 * maxLineLength + 16;
 | 
			
		||||
        }
 | 
			
		||||
        $('#tb-edge-downlinks-content', element).height(newHeight.toString() + "px")
 | 
			
		||||
            .width(newWidth.toString() + "px");
 | 
			
		||||
        vm.editor.resize();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    vm.close = close;
 | 
			
		||||
 | 
			
		||||
    function close () {
 | 
			
		||||
        $mdDialog.hide();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* eslint-enable angular/angularelement */
 | 
			
		||||
@ -1,42 +0,0 @@
 | 
			
		||||
<!--
 | 
			
		||||
 | 
			
		||||
    Copyright © 2016-2020 The Thingsboard Authors
 | 
			
		||||
 | 
			
		||||
    Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
    you may not use this file except in compliance with the License.
 | 
			
		||||
    You may obtain a copy of the License at
 | 
			
		||||
 | 
			
		||||
        http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 | 
			
		||||
    Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
    distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
    See the License for the specific language governing permissions and
 | 
			
		||||
    limitations under the License.
 | 
			
		||||
 | 
			
		||||
-->
 | 
			
		||||
<md-dialog aria-label="{{ vm.title | translate }}">
 | 
			
		||||
        <md-toolbar>
 | 
			
		||||
            <div class="md-toolbar-tools">
 | 
			
		||||
                <h2 translate>{{ vm.title }}</h2>
 | 
			
		||||
                <span flex></span>
 | 
			
		||||
                <md-button class="md-icon-button" ng-click="vm.close()">
 | 
			
		||||
                    <ng-md-icon icon="close" aria-label="{{ 'dialog.close' | translate }}"></ng-md-icon>
 | 
			
		||||
                </md-button>
 | 
			
		||||
            </div>
 | 
			
		||||
        </md-toolbar>
 | 
			
		||||
        <md-dialog-content>
 | 
			
		||||
            <div class="md-dialog-content">
 | 
			
		||||
                <div flex id="tb-edge-downlinks-content" readonly
 | 
			
		||||
                     ui-ace="vm.contentOptions"
 | 
			
		||||
                     ng-model="vm.content">
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
        </md-dialog-content>
 | 
			
		||||
        <md-dialog-actions layout="row">
 | 
			
		||||
            <span flex></span>
 | 
			
		||||
            <md-button ng-disabled="$root.loading" ng-click="vm.close()" style="margin-right:20px;">{{ 'action.close' |
 | 
			
		||||
                translate }}
 | 
			
		||||
            </md-button>
 | 
			
		||||
        </md-dialog-actions>
 | 
			
		||||
</md-dialog>
 | 
			
		||||
@ -1,39 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright © 2016-2020 The Thingsboard Authors
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
/* eslint-disable import/no-unresolved, import/default */
 | 
			
		||||
 | 
			
		||||
import edgeDownlinksHeaderTemplate from './edge-downlinks-header.tpl.html'
 | 
			
		||||
 | 
			
		||||
/* eslint-enable import/no-unresolved, import/default */
 | 
			
		||||
 | 
			
		||||
/*@ngInject*/
 | 
			
		||||
export default function EdgeDownlinksHeaderDirective($compile, $templateCache) {
 | 
			
		||||
 | 
			
		||||
    var linker = function (scope, element) {
 | 
			
		||||
 | 
			
		||||
        var template = edgeDownlinksHeaderTemplate;
 | 
			
		||||
 | 
			
		||||
        element.html($templateCache.get(template));
 | 
			
		||||
        $compile(element.contents())(scope);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return {
 | 
			
		||||
        restrict: "A",
 | 
			
		||||
        replace: false,
 | 
			
		||||
        link: linker,
 | 
			
		||||
        scope: false
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
@ -1,124 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright © 2016-2020 The Thingsboard Authors
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
/* eslint-disable import/no-unresolved, import/default */
 | 
			
		||||
 | 
			
		||||
import edgeDownlinksContentTemplate from './edge-downlinks-content-dialog.tpl.html';
 | 
			
		||||
import edgeDownlinlsRowTemplate from './edge-downlinks-row.tpl.html';
 | 
			
		||||
 | 
			
		||||
/* eslint-enable import/no-unresolved, import/default */
 | 
			
		||||
 | 
			
		||||
/*@ngInject*/
 | 
			
		||||
export default function EdgeDownlinksRowDirective($compile, $templateCache, $mdDialog, $document, $translate,
 | 
			
		||||
                                          types, utils, toast, entityService, ruleChainService) {
 | 
			
		||||
 | 
			
		||||
    var linker = function (scope, element, attrs) {
 | 
			
		||||
 | 
			
		||||
        var template = edgeDownlinlsRowTemplate;
 | 
			
		||||
 | 
			
		||||
        element.html($templateCache.get(template));
 | 
			
		||||
        $compile(element.contents())(scope);
 | 
			
		||||
 | 
			
		||||
        scope.types = types;
 | 
			
		||||
        scope.downlink = attrs.downlink;
 | 
			
		||||
 | 
			
		||||
        scope.showEdgeEntityContent = function($event, title, contentType) {
 | 
			
		||||
            var onShowingCallback = {
 | 
			
		||||
                onShowing: function(){}
 | 
			
		||||
            }
 | 
			
		||||
            if (!contentType) {
 | 
			
		||||
                contentType = null;
 | 
			
		||||
            }
 | 
			
		||||
            var content = '';
 | 
			
		||||
            switch(scope.downlink.type) {
 | 
			
		||||
                case types.edgeEventType.relation:
 | 
			
		||||
                    content = angular.toJson(scope.downlink.body);
 | 
			
		||||
                    showDialog();
 | 
			
		||||
                    break;
 | 
			
		||||
                case types.edgeEventType.ruleChainMetaData:
 | 
			
		||||
                    content = ruleChainService.getRuleChainMetaData(scope.downlink.entityId, {ignoreErrors: true}).then(
 | 
			
		||||
                        function success(info) {
 | 
			
		||||
                            showDialog();
 | 
			
		||||
                            return angular.toJson(info);
 | 
			
		||||
                        }, function fail() {
 | 
			
		||||
                            showError();
 | 
			
		||||
                        });
 | 
			
		||||
                    break;
 | 
			
		||||
                default:
 | 
			
		||||
                    content = entityService.getEntity(scope.downlink.type, scope.downlink.entityId, {ignoreErrors: true}).then(
 | 
			
		||||
                        function success(info) {
 | 
			
		||||
                            showDialog();
 | 
			
		||||
                            return angular.toJson(info);
 | 
			
		||||
                        }, function fail() {
 | 
			
		||||
                            showError();
 | 
			
		||||
                        });
 | 
			
		||||
                    break;
 | 
			
		||||
            }
 | 
			
		||||
            function showDialog() {
 | 
			
		||||
                $mdDialog.show({
 | 
			
		||||
                    controller: 'EdgeDownlinksContentDialogController',
 | 
			
		||||
                    controllerAs: 'vm',
 | 
			
		||||
                    templateUrl: edgeDownlinksContentTemplate,
 | 
			
		||||
                    locals: {content: content, title: title, contentType: contentType, showingCallback: onShowingCallback},
 | 
			
		||||
                    parent: angular.element($document[0].body),
 | 
			
		||||
                    fullscreen: true,
 | 
			
		||||
                    targetEvent: $event,
 | 
			
		||||
                    multiple: true,
 | 
			
		||||
                    onShowing: function(scope, element) {
 | 
			
		||||
                        onShowingCallback.onShowing(scope, element);
 | 
			
		||||
                    }
 | 
			
		||||
                });
 | 
			
		||||
            }
 | 
			
		||||
            function showError() {
 | 
			
		||||
                toast.showError($translate.instant('edge.load-entity-error'));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        scope.checkEdgeDownlinksType = function (type) {
 | 
			
		||||
            return !(type === types.edgeEventType.widgetType ||
 | 
			
		||||
                type === types.edgeEventType.adminSettings ||
 | 
			
		||||
                type === types.edgeEventType.widgetsBundle );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        scope.checkTooltip = function($event) {
 | 
			
		||||
            var el = $event.target;
 | 
			
		||||
            var $el = angular.element(el);
 | 
			
		||||
            if(el.offsetWidth < el.scrollWidth && !$el.attr('title')){
 | 
			
		||||
                $el.attr('title', $el.text());
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $compile(element.contents())(scope);
 | 
			
		||||
 | 
			
		||||
        scope.updateStatus = function(downlinkCreatedTime) {
 | 
			
		||||
            var status;
 | 
			
		||||
            if (downlinkCreatedTime < scope.queueStartTs) {
 | 
			
		||||
                status = $translate.instant(types.edgeEventStatus.DEPLOYED.name);
 | 
			
		||||
                scope.statusColor = types.edgeEventStatus.DEPLOYED.color;
 | 
			
		||||
            } else {
 | 
			
		||||
                status = $translate.instant(types.edgeEventStatus.PENDING.name);
 | 
			
		||||
                scope.statusColor = types.edgeEventStatus.PENDING.color;
 | 
			
		||||
            }
 | 
			
		||||
            return status;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return {
 | 
			
		||||
        restrict: "A",
 | 
			
		||||
        replace: false,
 | 
			
		||||
        link: linker,
 | 
			
		||||
        scope: false
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
@ -1,230 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright © 2016-2020 The Thingsboard Authors
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
import './downlink.scss';
 | 
			
		||||
 | 
			
		||||
/* eslint-disable import/no-unresolved, import/default */
 | 
			
		||||
 | 
			
		||||
import edgeDownlinksTableTemplate from './edge-downlinks-table.tpl.html';
 | 
			
		||||
 | 
			
		||||
/* eslint-enable import/no-unresolved, import/default */
 | 
			
		||||
 | 
			
		||||
/*@ngInject*/
 | 
			
		||||
export default function EdgeDownlinksDirective($compile, $templateCache, $rootScope, $translate, types, edgeService, attributeService) {
 | 
			
		||||
 | 
			
		||||
    var linker = function (scope, element) {
 | 
			
		||||
 | 
			
		||||
        var template = $templateCache.get(edgeDownlinksTableTemplate);
 | 
			
		||||
        element.html(template);
 | 
			
		||||
 | 
			
		||||
        var pageSize = 20;
 | 
			
		||||
        var startTime = 0;
 | 
			
		||||
        var endTime = 0;
 | 
			
		||||
 | 
			
		||||
        scope.timewindow = {
 | 
			
		||||
            history: {
 | 
			
		||||
                timewindowMs: 24 * 60 * 60 * 1000 // 1 day
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        scope.topIndex = 0;
 | 
			
		||||
 | 
			
		||||
        scope.theDownlinks = {
 | 
			
		||||
            getItemAtIndex: function (index) {
 | 
			
		||||
                if (index > scope.downlinks.data.length) {
 | 
			
		||||
                    scope.theDownlinks.fetchMoreItems_(index);
 | 
			
		||||
                    return null;
 | 
			
		||||
                }
 | 
			
		||||
                var item = scope.downlinks.data[index];
 | 
			
		||||
                if (item) {
 | 
			
		||||
                    item.indexNumber = index + 1;
 | 
			
		||||
                }
 | 
			
		||||
                return item;
 | 
			
		||||
            },
 | 
			
		||||
 | 
			
		||||
            getLength: function () {
 | 
			
		||||
                if (scope.downlinks.hasNext) {
 | 
			
		||||
                    return scope.downlinks.data.length + scope.downlinks.nextPageLink.limit;
 | 
			
		||||
                } else {
 | 
			
		||||
                    return scope.downlinks.data.length;
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
 | 
			
		||||
            fetchMoreItems_: function () {
 | 
			
		||||
                if (scope.downlinks.hasNext && !scope.downlinks.pending) {
 | 
			
		||||
                    if (scope.entityType && scope.entityId && scope.tenantId) {
 | 
			
		||||
                        scope.loadEdgeInfo();
 | 
			
		||||
                        scope.downlinks.pending = true;
 | 
			
		||||
                        edgeService.getEdgeEvents(scope.entityId, scope.downlinks.nextPageLink).then(
 | 
			
		||||
                            function success(downlinks) {
 | 
			
		||||
                                scope.downlinks.data = scope.downlinks.data.concat(prepareEdgeDownlinksData(downlinks.data));
 | 
			
		||||
                                scope.downlinks.nextPageLink = downlinks.nextPageLink;
 | 
			
		||||
                                scope.downlinks.hasNext = downlinks.hasNext;
 | 
			
		||||
                                if (scope.downlinks.hasNext) {
 | 
			
		||||
                                    scope.downlinks.nextPageLink.limit = pageSize;
 | 
			
		||||
                                }
 | 
			
		||||
                                scope.downlinks.pending = false;
 | 
			
		||||
                            },
 | 
			
		||||
                            function fail() {
 | 
			
		||||
                                scope.downlinks.hasNext = false;
 | 
			
		||||
                                scope.downlinks.pending = false;
 | 
			
		||||
                            });
 | 
			
		||||
                    } else {
 | 
			
		||||
                        scope.downlinks.hasNext = false;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        scope.$watch("entityId", function(newVal, prevVal) {
 | 
			
		||||
            if (newVal && !angular.equals(newVal, prevVal)) {
 | 
			
		||||
                scope.resetFilter();
 | 
			
		||||
                scope.reload();
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        scope.$watch("timewindow", function(newVal, prevVal) {
 | 
			
		||||
            if (newVal && !angular.equals(newVal, prevVal)) {
 | 
			
		||||
                scope.reload();
 | 
			
		||||
            }
 | 
			
		||||
        }, true);
 | 
			
		||||
 | 
			
		||||
        scope.resetFilter = function() {
 | 
			
		||||
            scope.timewindow = {
 | 
			
		||||
                history: {
 | 
			
		||||
                    timewindowMs: 24 * 60 * 60 * 1000 // 1 day
 | 
			
		||||
                }
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        scope.updateTimeWindowRange = function() {
 | 
			
		||||
            if (scope.timewindow.history.timewindowMs) {
 | 
			
		||||
                var currentTime = (new Date).getTime();
 | 
			
		||||
                startTime = currentTime - scope.timewindow.history.timewindowMs;
 | 
			
		||||
                endTime = currentTime;
 | 
			
		||||
            } else {
 | 
			
		||||
                startTime = scope.timewindow.history.fixedTimewindow.startTimeMs;
 | 
			
		||||
                endTime = scope.timewindow.history.fixedTimewindow.endTimeMs;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        scope.reload = function() {
 | 
			
		||||
            scope.topIndex = 0;
 | 
			
		||||
            scope.selected = [];
 | 
			
		||||
            scope.updateTimeWindowRange();
 | 
			
		||||
            scope.downlinks = {
 | 
			
		||||
                data: [],
 | 
			
		||||
                nextPageLink: {
 | 
			
		||||
                    limit: pageSize,
 | 
			
		||||
                    startTime: startTime,
 | 
			
		||||
                    endTime: endTime
 | 
			
		||||
                },
 | 
			
		||||
                hasNext: true,
 | 
			
		||||
                pending: false
 | 
			
		||||
            };
 | 
			
		||||
            scope.theDownlinks.getItemAtIndex(pageSize);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        scope.noData = function() {
 | 
			
		||||
            return scope.downlinks.data.length == 0 && !scope.downlinks.hasNext;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        scope.hasData = function() {
 | 
			
		||||
            return scope.downlinks.data.length > 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        scope.loading = function() {
 | 
			
		||||
            return $rootScope.loading;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        scope.hasScroll = function() {
 | 
			
		||||
            var repeatContainer = scope.repeatContainer[0];
 | 
			
		||||
            if (repeatContainer) {
 | 
			
		||||
                var scrollElement = repeatContainer.children[0];
 | 
			
		||||
                if (scrollElement) {
 | 
			
		||||
                    return scrollElement.scrollHeight > scrollElement.clientHeight;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        scope.subscriptionId = null;
 | 
			
		||||
 | 
			
		||||
        scope.loadEdgeInfo = function() {
 | 
			
		||||
            attributeService.getEntityAttributesValues(
 | 
			
		||||
                scope.entityType,
 | 
			
		||||
                scope.entityId,
 | 
			
		||||
                types.attributesScope.server.value,
 | 
			
		||||
                types.edgeAttributeKeys.queueStartTs,
 | 
			
		||||
                null).then(
 | 
			
		||||
                    function success(attributes) {
 | 
			
		||||
                        attributes.length > 0 ? scope.onEdgeAttributesUpdate(attributes) : scope.queueStartTs = 0;
 | 
			
		||||
                    });
 | 
			
		||||
            scope.checkSubscription();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        scope.onEdgeAttributesUpdate = function(attributes) {
 | 
			
		||||
            let edgeAttributes = attributes.reduce(function (map, attribute) {
 | 
			
		||||
                map[attribute.key] = attribute;
 | 
			
		||||
                return map;
 | 
			
		||||
            }, {});
 | 
			
		||||
            if (edgeAttributes.queueStartTs) {
 | 
			
		||||
                scope.queueStartTs = edgeAttributes.queueStartTs.lastUpdateTs;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        scope.checkSubscription = function() {
 | 
			
		||||
            var newSubscriptionId = null;
 | 
			
		||||
            if (scope.entityId && scope.entityType && types.attributesScope.server.value) {
 | 
			
		||||
                newSubscriptionId =
 | 
			
		||||
                    attributeService.subscribeForEntityAttributes(scope.entityType, scope.entityId, types.attributesScope.server.value);
 | 
			
		||||
            }
 | 
			
		||||
            if (scope.subscriptionId && scope.subscriptionId != newSubscriptionId) {
 | 
			
		||||
                attributeService.unsubscribeForEntityAttributes(scope.subscriptionId);
 | 
			
		||||
            }
 | 
			
		||||
            scope.subscriptionId = newSubscriptionId;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        scope.$on('$destroy', function () {
 | 
			
		||||
            if (scope.subscriptionId) {
 | 
			
		||||
                attributeService.unsubscribeForEntityAttributes(scope.subscriptionId);
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        scope.reload();
 | 
			
		||||
 | 
			
		||||
        $compile(element.contents())(scope);
 | 
			
		||||
    }
 | 
			
		||||
    function prepareEdgeDownlinksData(data) {
 | 
			
		||||
 | 
			
		||||
        data.forEach(
 | 
			
		||||
            edgeDownlink => {
 | 
			
		||||
                edgeDownlink.edgeEventActionText = $translate.instant(types.edgeEventActionTypeTranslations[edgeDownlink.action].name);
 | 
			
		||||
                edgeDownlink.edgeEventTypeText = $translate.instant(types.edgeEventTypeTranslations[edgeDownlink.type].name);
 | 
			
		||||
            }
 | 
			
		||||
        );
 | 
			
		||||
        return data;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return {
 | 
			
		||||
        restrict: "E",
 | 
			
		||||
        link: linker,
 | 
			
		||||
        scope: {
 | 
			
		||||
            entityType: '=',
 | 
			
		||||
            entityId: '=',
 | 
			
		||||
            tenantId: '='
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
@ -1,46 +0,0 @@
 | 
			
		||||
<!--
 | 
			
		||||
 | 
			
		||||
    Copyright © 2016-2020 The Thingsboard Authors
 | 
			
		||||
 | 
			
		||||
    Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
    you may not use this file except in compliance with the License.
 | 
			
		||||
    You may obtain a copy of the License at
 | 
			
		||||
 | 
			
		||||
        http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 | 
			
		||||
    Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
    distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
    See the License for the specific language governing permissions and
 | 
			
		||||
    limitations under the License.
 | 
			
		||||
 | 
			
		||||
-->
 | 
			
		||||
<md-content flex class="md-padding tb-absolute-fill" layout="column">
 | 
			
		||||
    <section layout="row">
 | 
			
		||||
        <tb-timewindow flex ng-model="timewindow" history-only as-button="true"></tb-timewindow>
 | 
			
		||||
        <md-button ng-disabled="$root.loading"
 | 
			
		||||
                   class="md-icon-button" ng-click="reload()">
 | 
			
		||||
            <md-icon>refresh</md-icon>
 | 
			
		||||
            <md-tooltip md-direction="top">
 | 
			
		||||
                {{ 'action.refresh' | translate }}
 | 
			
		||||
            </md-tooltip>
 | 
			
		||||
        </md-button>
 | 
			
		||||
    </section>
 | 
			
		||||
    <md-list flex layout="column" class="md-whiteframe-z1 tb-edge-downlinks-table">
 | 
			
		||||
           <md-list class="tb-row tb-header" layout="row" layout-align="start center" tb-edge-downlinks-header>
 | 
			
		||||
           </md-list>
 | 
			
		||||
        <md-progress-linear style="max-height: 0px;" md-mode="indeterminate" ng-disabled="!$root.loading"
 | 
			
		||||
                            ng-show="$root.loading"></md-progress-linear>
 | 
			
		||||
        <md-divider></md-divider>
 | 
			
		||||
        <span translate layout-align="center center"
 | 
			
		||||
              style="margin-top: 25px;"
 | 
			
		||||
              class="tb-prompt" ng-show="noData()">edge.no-downlinks-prompt</span>
 | 
			
		||||
        <md-virtual-repeat-container ng-show="hasData()" flex md-top-index="topIndex" tb-scope-element="repeatContainer">
 | 
			
		||||
           <md-list-item md-virtual-repeat="downlink in theDownlinks" md-on-demand flex ng-style="hasScroll() ? {'margin-right':'-15px'} : {}">
 | 
			
		||||
               <md-list class="tb-row" flex layout="row" layout-align="start center" tb-edge-downlinks-row downlink="{{downlink}}">
 | 
			
		||||
               </md-list>
 | 
			
		||||
               <md-divider flex></md-divider>
 | 
			
		||||
           </md-list-item>
 | 
			
		||||
       </md-virtual-repeat-container>
 | 
			
		||||
    </md-list>
 | 
			
		||||
</md-content>
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user