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

     1  <script type="text/x-template" id="filters-template">
     2  <div>
     3      <h4>Filters<i class="el-icon-refresh" style="cursor: pointer" @click="clearFilters()"></i></h4>
     4      <el-select v-model="editingFilter.propKey"
     5                 allow-create
     6                 filterable
     7                 placeholder="Property...">
     8          <el-option
     9                  v-for="propKey in propKeys"
    10                  :key="propKey"
    11                  :label="propKey"
    12                  :value="propKey">
    13          </el-option>
    14      </el-select>
    15      <el-select v-model="editingFilter.operator" filterable placeholder="Operator..." style="margin-top: 8px;">
    16          <el-option
    17                  v-for="operator in operators"
    18                  :key="operator[1]"
    19                  :label="operator[0]"
    20                  :value="operator[1]">
    21          </el-option>
    22      </el-select>
    23      <el-select
    24              v-model="editingFilter.operand"
    25              filterable
    26              allow-create
    27              placeholder="Value..." style="margin-top: 8px;">
    28          <el-option
    29                  v-for="propValue in editingPropValues"
    30                  :key="propValue"
    31                  :label="propValue"
    32                  :value="propValue">
    33          </el-option>
    34      </el-select>
    35      <el-button style="margin-top: 8px;" @click="addFilter()">Add Filter</el-button>
    36      <div v-for="(filter, index) in editableFilters" :key="filter.key"
    37           style="margin-top: 8px; word-wrap: break-word; line-height: 2em;">
    38          <i class="el-icon-circle-close-outline" style="cursor: pointer" @click="removeFilter(index)"></i>
    39          {{ filter.propKey }} {{ filter.operator}} {{ formatOperand(filter.operand) }}
    40      </div>
    41  </div>
    42  </script>
    43  <script>
    44      Vue.component('filters', {
    45          template: '#filters-template',
    46          props: ['propValues', 'filters'],
    47          data: function () {
    48              var editableFilters = [];
    49              var persistedModel = localStorage.getItem('filters::persistedModel');
    50              if (persistedModel) {
    51                  var model = JSON.parse(persistedModel);
    52                  editableFilters = model.editableFilters || [];
    53              }
    54              return {
    55                  editingFilter: {
    56                      propKey: '',
    57                      operator: 'equals',
    58                      operand: ''
    59                  },
    60                  operators: [
    61                      ['Equals', 'equals'],
    62                      ['Contains', 'contains'],
    63                      ['Not Equals', 'not-equals'],
    64                      ['Not Contains', 'not-contains']
    65                  ],
    66                  editableFilters: editableFilters
    67              }
    68          },
    69          watch: {
    70              editableFilters: function (val) {
    71                  this.onEditableFiltersUpdated();
    72              }
    73          },
    74          mounted: function() {
    75              this.onEditableFiltersUpdated();
    76          },
    77          computed: {
    78              propKeys: function() {
    79                  var propKeys = [];
    80                  for (var propKey in this.propValues) {
    81                      propKeys.push(propKey);
    82                  }
    83                  return propKeys;
    84              },
    85              editingPropValues: function() {
    86                  if (!this.editingFilter.propKey) {
    87                      return [];
    88                  }
    89                  return this.propValues[this.editingFilter.propKey];
    90              }
    91          },
    92          methods: {
    93              clearFilters: function() {
    94                  this.editingFilter = {
    95                      propKey: '',
    96                      operator: 'equals',
    97                      operand: ''
    98                  };
    99                  this.editableFilters = [];
   100                  this.$notify.info({
   101                      title: 'info',
   102                      message: 'filters cleared'
   103                  });
   104              },
   105              onEditableFiltersUpdated: function() {
   106                  var whitelist = {};
   107                  var blacklist = {};
   108                  for (var i in this.editableFilters) {
   109                      var editableFilter = this.editableFilters[i];
   110                      if (editableFilter.operator.indexOf('not-') === 0) {
   111                          blacklist[editableFilter.propKey] = createFilterFunc(
   112                              editableFilter, blacklist[editableFilter.propKey]);
   113                      } else {
   114                          whitelist[editableFilter.propKey] = createFilterFunc(
   115                              editableFilter, whitelist[editableFilter.propKey]);
   116                      }
   117                  }
   118                  var filters = {
   119                      cacheKey: '__filtered_by_' + new Date().getTime(),
   120                      filterFunc: mergeWhitelistAndBlacklist(whitelist, blacklist)
   121                  };
   122                  this.$emit('update:filters', filters);
   123                  localStorage.setItem('filters::persistedModel', JSON.stringify({
   124                      'editableFilters': this.editableFilters
   125                  }));
   126              },
   127              addFilter: function(propKey, operator, operand) {
   128                  propKey = propKey || this.editingFilter.propKey;
   129                  operator = operator || this.editingFilter.operator;
   130                  operand = operand || this.editingFilter.operand;
   131                  if (!(propKey)) {
   132                      $vue.$notify.error({
   133                          title: 'Add filter missing parameter',
   134                          message: 'Property not specified'
   135                      });
   136                      return;
   137                  }
   138                  if (!(operand)) {
   139                      $vue.$notify.error({
   140                          title: 'Add filter missing parameter',
   141                          message: 'Filter operand not specified'
   142                      });
   143                      return;
   144                  }
   145                  this.editableFilters.push({
   146                      propKey: propKey,
   147                      operator: operator,
   148                      operand: operand,
   149                      key: new Date().getTime()
   150                  });
   151                  this.editingFilter.propKey = '';
   152                  this.editingFilter.operand = '';
   153              },
   154              removeFilter: function(index) {
   155                  this.editableFilters.splice(index, 1);
   156              },
   157              formatTimestamp: function(val) {
   158                  var d = new Date(val / 1000000);
   159                  return d.getHours() + ':' + d.getMinutes() + ':' + d.getSeconds() + '.' + d.getMilliseconds();
   160              },
   161              formatOperand: function(operand) {
   162                  if (Array.isArray(operand)) {
   163                      return this.formatTimestamp(operand[0]) + ' ~ ' + this.formatTimestamp(operand[1]);
   164                  } else {
   165                      return operand;
   166                  }
   167              }
   168          }
   169      });
   170  
   171      function mergeWhitelistAndBlacklist(whitelist, blacklist) {
   172          return function(event) {
   173              // if blacklist, do not show
   174              for (var propKey in blacklist) {
   175                  var filterFunc = blacklist[propKey];
   176                  var propValue = event[propKey];
   177                  if (propValue && !filterFunc(propValue)) {
   178                      return false;
   179                  }
   180              }
   181              // if no whitelist, show by default
   182              if (Object.keys(whitelist).length === 0) {
   183                  return true;
   184              }
   185              // test if whitelist matched
   186              for (var propKey in whitelist) {
   187                  var filterFunc = whitelist[propKey];
   188                  var propValue = event[propKey];
   189                  if (propValue && filterFunc(propValue)) {
   190                      return true;
   191                  }
   192              }
   193              // if not covered by whitelist, do not show
   194              return false;
   195          }
   196      }
   197  
   198      function createFilterFunc(editableFilter, previousFunc) {
   199          switch (editableFilter.operator) {
   200              case 'contains':
   201                  return function(val) {
   202                      if (val.indexOf(editableFilter.operand) !== -1) {
   203                          return true;
   204                      }
   205                      if (previousFunc) {
   206                          return previousFunc(val)
   207                      } else {
   208                          return false;
   209                      }
   210                  };
   211              case 'not-contains':
   212                  return function(val) {
   213                      var myResult = val.indexOf(editableFilter.operand) === -1;
   214                      if (previousFunc) {
   215                          return myResult && previousFunc(val)
   216                      }
   217                      return myResult;
   218                  };
   219              case 'equals':
   220                  return function(val) {
   221                      if (val === editableFilter.operand) {
   222                          return true;
   223                      }
   224                      if (previousFunc) {
   225                          return previousFunc(val)
   226                      } else {
   227                          return false;
   228                      }
   229                  };
   230              case 'not-equals':
   231                  return function(val) {
   232                      var myResult = val !== editableFilter.operand;
   233                      if (previousFunc) {
   234                          return myResult && previousFunc(val)
   235                      }
   236                      return myResult;
   237                  };
   238              case 'between':
   239                  return function(val) {
   240                      if (val >= editableFilter.operand[0] && val <= editableFilter.operand[1]) {
   241                          return true;
   242                      }
   243                      if (previousFunc) {
   244                          return previousFunc(val)
   245                      } else {
   246                          return false;
   247                      }
   248                  };
   249              default:
   250                  console.log('unknown filter operator: ' + editableFilter.operator);
   251                  return function(val) { return false; }
   252          }
   253      }
   254  </script>