github.com/Ilhicas/nomad@v1.0.4-0.20210304152020-e86851182bc3/ui/app/components/topo-viz/node.js (about)

     1  import Component from '@glimmer/component';
     2  import { tracked } from '@glimmer/tracking';
     3  import { action } from '@ember/object';
     4  import { guidFor } from '@ember/object/internals';
     5  
     6  export default class TopoVizNode extends Component {
     7    @tracked data = { cpu: [], memory: [] };
     8    @tracked dimensionsWidth = 0;
     9    @tracked padding = 5;
    10    @tracked activeAllocation = null;
    11  
    12    get height() {
    13      return this.args.heightScale ? this.args.heightScale(this.args.node.memory) : 15;
    14    }
    15  
    16    get labelHeight() {
    17      return this.height / 2;
    18    }
    19  
    20    get paddingLeft() {
    21      const labelWidth = 20;
    22      return this.padding + labelWidth;
    23    }
    24  
    25    // Since strokes are placed centered on the perimeter of fills, The width of the stroke needs to be removed from
    26    // the height of the fill to match unstroked height and avoid clipping.
    27    get selectedHeight() {
    28      return this.height - 1;
    29    }
    30  
    31    // Since strokes are placed centered on the perimeter of fills, half the width of the stroke needs to be added to
    32    // the yOffset to match heights with unstroked shapes.
    33    get selectedYOffset() {
    34      return this.height + 2.5;
    35    }
    36  
    37    get yOffset() {
    38      return this.height + 2;
    39    }
    40  
    41    get maskHeight() {
    42      return this.height + this.yOffset;
    43    }
    44  
    45    get totalHeight() {
    46      return this.maskHeight + this.padding * 2;
    47    }
    48  
    49    get maskId() {
    50      return `topo-viz-node-mask-${guidFor(this)}`;
    51    }
    52  
    53    get count() {
    54      return this.allocations.length;
    55    }
    56  
    57    get allocations() {
    58      // Sort by the delta between memory and cpu percent. This creates the least amount of
    59      // drift between the positional alignment of an alloc's cpu and memory representations.
    60      return this.args.node.allocations.filterBy('allocation.isScheduled').sort((a, b) => {
    61        const deltaA = Math.abs(a.memoryPercent - a.cpuPercent);
    62        const deltaB = Math.abs(b.memoryPercent - b.cpuPercent);
    63        return deltaA - deltaB;
    64      });
    65    }
    66  
    67    @action
    68    async reloadNode() {
    69      if (this.args.node.isPartial) {
    70        await this.args.node.reload();
    71        this.data = this.computeData(this.dimensionsWidth);
    72      }
    73    }
    74  
    75    @action
    76    render(svg) {
    77      this.dimensionsWidth = svg.clientWidth - this.padding - this.paddingLeft;
    78      this.data = this.computeData(this.dimensionsWidth);
    79    }
    80  
    81    @action
    82    updateRender(svg) {
    83      // Only update all data when the width changes
    84      const newWidth = svg.clientWidth - this.padding - this.paddingLeft;
    85      if (newWidth !== this.dimensionsWidth) {
    86        this.dimensionsWidth = newWidth;
    87        this.data = this.computeData(this.dimensionsWidth);
    88      }
    89    }
    90  
    91    @action
    92    highlightAllocation(allocation, { target }) {
    93      this.activeAllocation = allocation;
    94      this.args.onAllocationFocus && this.args.onAllocationFocus(allocation, target);
    95    }
    96  
    97    @action
    98    allocationBlur() {
    99      this.args.onAllocationBlur && this.args.onAllocationBlur();
   100    }
   101  
   102    @action
   103    clearHighlight() {
   104      this.activeAllocation = null;
   105    }
   106  
   107    @action
   108    selectNode() {
   109      if (this.args.isDense && this.args.onNodeSelect) {
   110        this.args.onNodeSelect(this.args.node.isSelected ? null : this.args.node);
   111      }
   112    }
   113  
   114    @action
   115    selectAllocation(allocation) {
   116      if (this.args.onAllocationSelect) this.args.onAllocationSelect(allocation);
   117    }
   118  
   119    containsActiveTaskGroup() {
   120      return this.args.node.allocations.some(
   121        allocation =>
   122          allocation.taskGroupName === this.args.activeTaskGroup &&
   123          allocation.belongsTo('job').id() === this.args.activeJobId
   124      );
   125    }
   126  
   127    computeData(width) {
   128      const allocations = this.allocations;
   129      let cpuOffset = 0;
   130      let memoryOffset = 0;
   131  
   132      const cpu = [];
   133      const memory = [];
   134      for (const allocation of allocations) {
   135        const { cpuPercent, memoryPercent, isSelected } = allocation;
   136        const isFirst = allocation === allocations[0];
   137  
   138        let cpuWidth = cpuPercent * width - 1;
   139        let memoryWidth = memoryPercent * width - 1;
   140        if (isFirst) {
   141          cpuWidth += 0.5;
   142          memoryWidth += 0.5;
   143        }
   144        if (isSelected) {
   145          cpuWidth--;
   146          memoryWidth--;
   147        }
   148  
   149        cpu.push({
   150          allocation,
   151          offset: cpuOffset * 100,
   152          percent: cpuPercent * 100,
   153          width: Math.max(cpuWidth, 0),
   154          x: cpuOffset * width + (isFirst ? 0 : 0.5) + (isSelected ? 0.5 : 0),
   155          className: allocation.allocation.clientStatus,
   156        });
   157        memory.push({
   158          allocation,
   159          offset: memoryOffset * 100,
   160          percent: memoryPercent * 100,
   161          width: Math.max(memoryWidth, 0),
   162          x: memoryOffset * width + (isFirst ? 0 : 0.5) + (isSelected ? 0.5 : 0),
   163          className: allocation.allocation.clientStatus,
   164        });
   165  
   166        cpuOffset += cpuPercent;
   167        memoryOffset += memoryPercent;
   168      }
   169  
   170      const cpuRemainder = {
   171        x: cpuOffset * width + 0.5,
   172        width: Math.max(width - cpuOffset * width, 0),
   173      };
   174      const memoryRemainder = {
   175        x: memoryOffset * width + 0.5,
   176        width: Math.max(width - memoryOffset * width, 0),
   177      };
   178  
   179      return {
   180        cpu,
   181        memory,
   182        cpuRemainder,
   183        memoryRemainder,
   184        cpuLabel: { x: -this.paddingLeft / 2, y: this.height / 2 + this.yOffset },
   185        memoryLabel: { x: -this.paddingLeft / 2, y: this.height / 2 },
   186      };
   187    }
   188  }