github.com/v2pro/plz@v0.0.0-20221028024117-e5f9aec5b631/witch/webroot/state-viewer.html (about)

     1  <script type="text/x-template" id="state-node-template">
     2      <div style="padding-left:18px">
     3          <div @click="callbacks.onNodeClick(node)">
     4          <span class="el-tree-node__expand-icon el-icon-caret-right"
     5                :class="{ 'is-leaf': node.isLeaf, expanded: !node.isLeaf && callbacks.isExpanded(node) }"></span>
     6          {{ node.label }}
     7              <span v-if="node.value">: {{ node.value }}</span>
     8              <el-button v-if="node.isDumpVar" size="mini" @click="callbacks.visualize(node,$event)">visualize</el-button>
     9          </div>
    10          <state-node v-for="child in node.children" :node="child"
    11                      :callbacks="callbacks" :key="child.id"
    12                      v-show="!node.isLeaf && callbacks.isExpanded(node)"/>
    13      </div>
    14  </script>
    15  <script type="text/x-template" id="state-viewer-template">
    16      <div>
    17          <el-row>
    18              <el-col :span="20">
    19                  <div v-show="selectedSnapshot === null">No snapshot to show, please click "Poll Current State"</div>
    20                  <div v-if="selectedSnapshot" style="margin-bottom: 8px;">Snapshot Taken
    21                      At: {{ selectedSnapshot.timestamp }}</div>
    22                  <state-node v-for="node in tree.children" :node="node" :callbacks="callbacks" :key="node.id">
    23                  </state-node>
    24              </el-col>
    25              <el-col :span="4" style="pdding-right: 1em; padding-left: 1em;">
    26                  <snapshots ref="snapshots" :selectedSnapshot.sync="selectedSnapshot"></snapshots>
    27              </el-col>
    28          </el-row>
    29          <el-dialog
    30                  :title="dialogTitle"
    31                  :visible.sync="dialogVisible"
    32                  :fullscreen="true">
    33              <viz :addrMap="addrMap"></viz>
    34          </el-dialog>
    35      </div>
    36  </script>
    37  <script>
    38      function Node(options) {
    39          this.id = '';
    40          this.label = '';
    41          this.value = null;
    42          this.isLeaf = false;
    43          this.data = null;
    44          this.indention = 0;
    45          this.children = [];
    46          this.root = null;
    47          for (var k in options) {
    48              this[k] = options[k];
    49          }
    50      }
    51  
    52      Node.prototype.addChild = function (options) {
    53          var child = new Node(options);
    54          child.root = this.root;
    55          child.id = this.id + '>' + options.label;
    56          child.indention = this.indention + 18;
    57          this.children.push(child);
    58          this.root.all_nodes[child.id] = child;
    59          return child;
    60      };
    61      Node.prototype.addObject = function (object, addrMap) {
    62          var isArray = Array.isArray(object);
    63          for (var k in object) {
    64              var label = k;
    65              if (isArray) {
    66                  label = '[' + label + ']';
    67              }
    68              var v = object[k];
    69              if (Array.isArray(v)) {
    70                  var childNode = this.addChild({label: label, addrMap: addrMap});
    71                  childNode.addObject(v, addrMap);
    72              } else if (v === null) {
    73                  this.addChild({label: label, addrMap: addrMap, value: '<null>', isLeaf: true});
    74                  break;
    75              } else {
    76                  this.addValue(label, v, addrMap)
    77              }
    78          }
    79      };
    80      Node.prototype.addValue = function (label, v, addrMap) {
    81          switch (typeof v) {
    82              case 'string':
    83                  this.addChild({label: label, addrMap: addrMap, value: v, isLeaf: true});
    84                  break;
    85              case 'boolean':
    86                  this.addChild({label: label, addrMap: addrMap, value: '' + v, isLeaf: true});
    87                  break;
    88              case 'number':
    89                  this.addChild({label: label, addrMap: addrMap, value: '' + v, isLeaf: true});
    90                  break;
    91              case 'object':
    92                  if (v.__root__) {
    93                      var childNode = this.addChild({
    94                          label: label, addrMap: v, isDumpVar: true, data: v.__root__
    95                      });
    96                      childNode.addObject(v.__root__, v);
    97                  } else if (v.__ptr__) {
    98                      this.addChild({label: label, addrMap: addrMap, data: v})
    99                  } else {
   100                      var childNode = this.addChild({label: label, addrMap: addrMap});
   101                      childNode.addObject(v, addrMap);
   102                  }
   103                  break;
   104          }
   105      };
   106      Vue.component('state-node', {
   107          template: '#state-node-template',
   108          props: ['node', 'callbacks']
   109      });
   110      Vue.component('state-viewer', {
   111          template: '#state-viewer-template',
   112          data: function () {
   113              return {
   114                  tree: new Node(), // view model
   115                  selectedSnapshot: null,
   116                  callbacks: this,
   117                  expansion: {},
   118                  dialogVisible: false,
   119                  dialogTitle: '',
   120                  addrMap: null
   121              }
   122          },
   123          watch: {
   124              selectedSnapshot: function () {
   125                  this.tree = new Node({id: 'root'});
   126                  this.tree.root = this.tree;
   127                  this.tree.all_nodes = {};
   128                  this.tree.addObject(this.selectedSnapshot.data);
   129                  for (var nodeId in this.expansion) {
   130                      var node = this.tree.all_nodes[nodeId];
   131                      if (node) {
   132                          this.expandPtr(node);
   133                      }
   134                  }
   135              }
   136          },
   137          methods: {
   138              onNodeClick: function (node) {
   139                  Vue.set(this.expansion, node.id, !this.expansion[node.id]);
   140                  this.expandPtr(node);
   141              },
   142              expandPtr: function (node) {
   143                  if (node.data && node.data.__ptr__) {
   144                      var objectAddr = node.data.__ptr__;
   145                      node.data = null; // avoid reload children
   146                      var object = node.addrMap[objectAddr];
   147                      if ((typeof object) === 'object') {
   148                          node.addObject(object, node.addrMap);
   149                      } else {
   150                          node.addValue('value', object, node.addrMap);
   151                      }
   152                  }
   153              },
   154              isExpanded: function (node) {
   155                  return this.expansion[node.id];
   156              },
   157              visualize: function (node, event) {
   158                  event.stopPropagation();
   159                  this.addrMap = node.addrMap;
   160                  this.dialogTitle = node.label;
   161                  this.dialogVisible = true;
   162              }
   163          }
   164      });
   165  </script>