<commit_before><!--
Copyright (c) 2008,2020 <NAME>.

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.
-->

<template>
  <div v-show="selectedEndpointTypeId.length != 0">
    <q-scroll-area style="height: 100vh; max-width: 200vh">
      <q-card flat square>
        <div class="row">
          <q-toolbar>
            <q-toolbar-title style="font-weight: bolder">
              Endpoint
              {{ this.endpointId[this.selectedEndpointId] }} Clusters
            </q-toolbar-title>
          </q-toolbar>
        </div>
        <div class="row bar align=left;">
          <div class="row">
            <div
              style="
                vertical-align: middle;
                text-align: center;
                padding: 10px 0 0 0;
              "
            >
              Show
            </div>
            &nbsp; &nbsp;

            <div>
              <q-select
                outlined
                :value="filter"
                :options="filterOptions"
                dense
                class="col-2"
                @input="changeDomainFilter($event)"
              />
            </div>
            &nbsp;
            <div v-for="actionOption in actionOptions" :key="actionOption">
              <q-btn
                outline
                @click="doActionFilter(actionOption)"
                :label="actionOption.label"
              />
            </div>
          </div>
          <q-space />
          <q-input
            dense
            outlined
            clearable
            class="col-4"
            placeholder="Search Clusters"
            @input="changeFilterString($event)"
            @clear="changeFilterString('')"
            :value="filterString"
          >
            <template v-slot:prepend>
              <q-icon name="search" />
            </template>
          </q-input>
        </div>
        <q-list>
          <div v-for="domainName in domainNames" :key="domainName">
            <div v-show="clusterDomains(domainName).length > 0">
              <q-expansion-item
                :id="domainName"
                switch-toggle-side
                :label="domainName"
                @input="setOpenDomain(domainName, $event)"
                :value="getDomainOpenState(domainName)"
              >
                <zcl-domain-cluster-view
                  :domainName="domainName"
                  :clusters="clusterDomains(domainName)"
                />
              </q-expansion-item>
              <q-separator />
            </div>
          </div>
        </q-list>
      </q-card>
    </q-scroll-area>
  </div>
</template>
<script>
import ZclDomainClusterView from './ZclDomainClusterView.vue'
import CommonMixin from '../util/common-mixin'
import { scroll } from 'quasar'
const { getScrollTarget, setScrollPosition } = scroll

export default {
  name: 'ZclClusterManager',
  props: ['endpointTypeReference'],
  mixins: [CommonMixin],
  mounted() {
    if (this.domainNames.length > 0 && this.lastSelectedDomain) {
      this.scrollToElementById(this.lastSelectedDomain)
    }
  },
  computed: {
    domainNames: {
      get() {
        return this.$store.state.zap.domains
      },
    },
    openDomains: {
      get() {
        return this.$store.state.zap.clusterManager.openDomains
      },
    },
    clusters: {
      get() {
        return this.$store.state.zap.clusters
      },
    },
    lastSelectedDomain: {
      get() {
        return this.$store.state.zap.clusterManager.lastSelectedDomain
      },
    },
    relevantClusters: {
      get() {
        return this.clusters.filter((cluster) =>
          this.filterString == ''
            ? true
            : cluster.label
                .toLowerCase()
                .includes(this.filterString.toLowerCase())
        )
      },
    },
    enabledClusters: {
      get() {
        return this.relevantClusters.filter((cluster) => {
          return this.isClusterEnabled(cluster.id)
        })
      },
    },
    filterOptions: {
      get() {
        return this.$store.state.zap.clusterManager.filterOptions
      },
    },
    filter: {
      get() {
        return this.$store.state.zap.clusterManager.filter
      },
    },
    filterString: {
      get() {
        return this.$store.state.zap.clusterManager.filterString
      },
    },
    actionOptions: {
      get() {
        return this.$store.state.zap.clusterManager.actionOptions
      },
    },
  },
  methods: {
    scrollToElementById(tag) {
      const el = document.getElementById(tag)
      const target = getScrollTarget(el)
      const offset = el.offsetTop
      setScrollPosition(target, offset)
    },
    clusterDomains(domainName) {
      return this.relevantClusters
        .filter((a) => {
          return a.domainName == domainName
        })
        .filter((a) => {
          return typeof this.filter.clusterFilterFn === 'function'
            ? this.filter.clusterFilterFn(a, {
                enabledClusters: this.enabledClusters,
              })
            : true
        })
        .sort(function (b, a) {
          return a.code > b.code
        })
    },
    isClusterEnabled(clusterReference) {
      return (
        this.selectionClients.includes(clusterReference) ||
        this.selectionServers.includes(clusterReference)
      )
    },
    setOpenDomain(domainName, event) {
      this.$store.dispatch('zap/setOpenDomain', {
        domainName: domainName,
        value: event,
      })
    },
    getDomainOpenState(domainName) {
      return this.openDomains[domainName] || this.filterString != ''
    },
    changeDomainFilter(filter) {
      this.$store.dispatch('zap/setDomainFilter', {
        filter: filter,
        enabledClusters: this.enabledClusters,
      })
    },
    doActionFilter(filter) {
      this.$store.dispatch('zap/doActionFilter', {
        filter: filter,
        enabledClusters: this.enabledClusters,
      })
    },
    changeFilterString(filterString) {
      this.$store.dispatch('zap/setFilterString', filterString)
    },
  },
  components: {
    ZclDomainClusterView,
  },
}
</script>

<!-- Notice lang="scss" -->
<style lang="scss">
.bar {
  padding: 15px 15px 15px 15px;
}
</style>
<commit_msg>Fix a weird Vue issue with non-primitive keys.<commit_after><!--
Copyright (c) 2008,2020 <NAME>.

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.
-->

<template>
  <div v-show="selectedEndpointTypeId.length != 0">
    <q-scroll-area style="height: 100vh; max-width: 200vh">
      <q-card flat square>
        <div class="row">
          <q-toolbar>
            <q-toolbar-title style="font-weight: bolder">
              Endpoint
              {{ this.endpointId[this.selectedEndpointId] }} Clusters
            </q-toolbar-title>
          </q-toolbar>
        </div>
        <div class="row bar align=left;">
          <div class="row">
            <div
              style="
                vertical-align: middle;
                text-align: center;
                padding: 10px 0 0 0;
              "
            >
              Show
            </div>
            &nbsp; &nbsp;

            <div>
              <q-select
                outlined
                :value="filter"
                :options="filterOptions"
                dense
                class="col-2"
                @input="changeDomainFilter($event)"
              />
            </div>
            &nbsp;
            <div
              v-for="actionOption in actionOptions"
              :key="actionOption.label"
            >
              <q-btn
                outline
                @click="doActionFilter(actionOption)"
                :label="actionOption.label"
              />
            </div>
          </div>
          <q-space />
          <q-input
            dense
            outlined
            clearable
            class="col-4"
            placeholder="Search Clusters"
            @input="changeFilterString($event)"
            @clear="changeFilterString('')"
            :value="filterString"
          >
            <template v-slot:prepend>
              <q-icon name="search" />
            </template>
          </q-input>
        </div>
        <q-list>
          <div v-for="domainName in domainNames" :key="domainName.id">
            <div v-show="clusterDomains(domainName).length > 0">
              <q-expansion-item
                :id="domainName"
                switch-toggle-side
                :label="domainName"
                @input="setOpenDomain(domainName, $event)"
                :value="getDomainOpenState(domainName)"
              >
                <zcl-domain-cluster-view
                  :domainName="domainName"
                  :clusters="clusterDomains(domainName)"
                />
              </q-expansion-item>
              <q-separator />
            </div>
          </div>
        </q-list>
      </q-card>
    </q-scroll-area>
  </div>
</template>
<script>
import ZclDomainClusterView from './ZclDomainClusterView.vue'
import CommonMixin from '../util/common-mixin'
import { scroll } from 'quasar'
const { getScrollTarget, setScrollPosition } = scroll

export default {
  name: 'ZclClusterManager',
  props: ['endpointTypeReference'],
  mixins: [CommonMixin],
  mounted() {
    if (this.domainNames.length > 0 && this.lastSelectedDomain) {
      this.scrollToElementById(this.lastSelectedDomain)
    }
  },
  computed: {
    domainNames: {
      get() {
        return this.$store.state.zap.domains
      },
    },
    openDomains: {
      get() {
        return this.$store.state.zap.clusterManager.openDomains
      },
    },
    clusters: {
      get() {
        return this.$store.state.zap.clusters
      },
    },
    lastSelectedDomain: {
      get() {
        return this.$store.state.zap.clusterManager.lastSelectedDomain
      },
    },
    relevantClusters: {
      get() {
        return this.clusters.filter((cluster) =>
          this.filterString == ''
            ? true
            : cluster.label
                .toLowerCase()
                .includes(this.filterString.toLowerCase())
        )
      },
    },
    enabledClusters: {
      get() {
        return this.relevantClusters.filter((cluster) => {
          return this.isClusterEnabled(cluster.id)
        })
      },
    },
    filterOptions: {
      get() {
        return this.$store.state.zap.clusterManager.filterOptions
      },
    },
    filter: {
      get() {
        return this.$store.state.zap.clusterManager.filter
      },
    },
    filterString: {
      get() {
        return this.$store.state.zap.clusterManager.filterString
      },
    },
    actionOptions: {
      get() {
        return this.$store.state.zap.clusterManager.actionOptions
      },
    },
  },
  methods: {
    scrollToElementById(tag) {
      const el = document.getElementById(tag)
      const target = getScrollTarget(el)
      const offset = el.offsetTop
      setScrollPosition(target, offset)
    },
    clusterDomains(domainName) {
      return this.relevantClusters
        .filter((a) => {
          return a.domainName == domainName
        })
        .filter((a) => {
          return typeof this.filter.clusterFilterFn === 'function'
            ? this.filter.clusterFilterFn(a, {
                enabledClusters: this.enabledClusters,
              })
            : true
        })
        .sort(function (b, a) {
          return a.code > b.code
        })
    },
    isClusterEnabled(clusterReference) {
      return (
        this.selectionClients.includes(clusterReference) ||
        this.selectionServers.includes(clusterReference)
      )
    },
    setOpenDomain(domainName, event) {
      this.$store.dispatch('zap/setOpenDomain', {
        domainName: domainName,
        value: event,
      })
    },
    getDomainOpenState(domainName) {
      return this.openDomains[domainName] || this.filterString != ''
    },
    changeDomainFilter(filter) {
      this.$store.dispatch('zap/setDomainFilter', {
        filter: filter,
        enabledClusters: this.enabledClusters,
      })
    },
    doActionFilter(filter) {
      this.$store.dispatch('zap/doActionFilter', {
        filter: filter,
        enabledClusters: this.enabledClusters,
      })
    },
    changeFilterString(filterString) {
      this.$store.dispatch('zap/setFilterString', filterString)
    },
  },
  components: {
    ZclDomainClusterView,
  },
}
</script>

<!-- Notice lang="scss" -->
<style lang="scss">
.bar {
  padding: 15px 15px 15px 15px;
}
</style>

{'fraction_non_alphanumeric': 0.12027721886876816, 'fraction_numerical': 0.0053655264922870555, 'mean_word_length': 1.7248730964467005, 'pattern_counts': {'":': 0, '<': 101, '<?xml version=': 0, '>': 115, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1440474', 'n_tokens_mistral': 3819, 'n_tokens_neox': 3700, 'n_words': 713}