From 1fc5cc453f931d99cf690bfde78891137bf2d929 Mon Sep 17 00:00:00 2001
From: paulr34 <64710345+paulr34@users.noreply.github.com>
Date: Fri, 15 Mar 2024 15:18:37 -0400
Subject: [PATCH] matter centric UI (#1278)

* matter centric UI

* only allow selection of server if Matter project

* removing cypress tests because Zigbee and Matter GUI diverged - follow up task for separating them

* centralizing data
---
 cypress/e2e/clusters/cluster-filter.cy.js  |  42 -----
 cypress/e2e/clusters/dimmable-light.cy.js  |  16 --
 src/components/ZclAttributeManager.vue     | 200 +++++++++++----------
 src/components/ZclCreateModifyEndpoint.vue |  22 +--
 src/components/ZclDomainClusterView.vue    |  24 ++-
 src/components/ZclEndpointCard.vue         |   7 +-
 src/util/ui-options.js                     |  31 ++++
 7 files changed, 165 insertions(+), 177 deletions(-)
 create mode 100644 src/util/ui-options.js

diff --git a/cypress/e2e/clusters/cluster-filter.cy.js b/cypress/e2e/clusters/cluster-filter.cy.js
index 6441699e..0f9b01d4 100644
--- a/cypress/e2e/clusters/cluster-filter.cy.js
+++ b/cypress/e2e/clusters/cluster-filter.cy.js
@@ -29,46 +29,4 @@ describe('Testing cluster filters', () => {
       })
     }
   )
-  it(
-    'enable power configuration cluster',
-    { retries: { runMode: 2, openMode: 2 } },
-    () => {
-      cy.get('[data-test="filter-input"]').click({ force: true })
-      cy.get('.q-virtual-scroll__content > :nth-child(1)').click()
-      cy.fixture('data').then((data) => {
-        cy.get('tbody').children().should('contain', data.cluster2)
-      })
-      cy.get('#General').click({ force: true })
-      cy.get(
-        '#General > .q-expansion-item__container > .q-expansion-item__content > .q-card > .q-card__section > .row >  .q-table__container > .q-table__middle > .q-table > tbody > :nth-child(2) > :nth-child(6) > .q-field > .q-field__inner > .q-field__control'
-      ).click({ force: true })
-      cy.fixture('data').then((data) => {
-        cy.get('.q-virtual-scroll__content > :nth-child(3)')
-          .contains(data.server1)
-          .click()
-      })
-      cy.get(
-        '.v-step-7 > .q-field > .q-field__inner > .q-field__control'
-      ).click({ force: true })
-    }
-  )
-  it(
-    'checks if power configuration exists',
-    { retries: { runMode: 2, openMode: 2 } },
-    () => {
-      cy.get('.q-virtual-scroll__content > :nth-child(2)').click({
-        force: true,
-        multiple: true,
-      })
-      cy.fixture('data').then((data) => {
-        cy.get('tbody').children().should('contain', data.cluster2)
-      })
-    }
-  )
-  it('Close all the clusters', () => {
-    cy.dataCy('cluster-btn-closeall').click()
-    cy.get('[data-test=Cluster').each(($row) => {
-      cy.wrap($row).should('have.class', 'q-expansion-item--collapsed')
-    })
-  })
 })
diff --git a/cypress/e2e/clusters/dimmable-light.cy.js b/cypress/e2e/clusters/dimmable-light.cy.js
index 88a8c6f4..1453e29d 100644
--- a/cypress/e2e/clusters/dimmable-light.cy.js
+++ b/cypress/e2e/clusters/dimmable-light.cy.js
@@ -25,21 +25,5 @@ describe(
           .type(data.cluster4)
       })
     })
-    it('Enabling Client & Server', () => {
-      cy.get(
-        ':nth-child(6) > .q-field > .q-field__inner > .q-field__control'
-      ).click({ force: true })
-      cy.fixture('data').then((data) => {
-        cy.get('.q-menu').contains(data.server2).click()
-      })
-    })
-    it('Check Configuration page', () => {
-      cy.get(':nth-child(7) > .q-btn > .q-btn__content > .notranslate').click({
-        force: true,
-      })
-      cy.fixture('data').then((data) => {
-        cy.get('tr.table_body').contains(data.attribute3).should('be.visible')
-      })
-    })
   }
 )
diff --git a/src/components/ZclAttributeManager.vue b/src/components/ZclAttributeManager.vue
index 1469d468..aa5461b7 100644
--- a/src/components/ZclAttributeManager.vue
+++ b/src/components/ZclAttributeManager.vue
@@ -123,8 +123,14 @@ limitations under the License.
               "
             />
           </q-td>
-          <q-td key="singleton" :props="props" auto-width>
+          <q-td
+            key="singleton"
+            v-if="enableSingleton"
+            :props="props"
+            auto-width
+          >
             <q-checkbox
+              v-if="enableSingleton"
               class="q-mt-xs"
               :model-value="selectionSingleton"
               :val="hashAttributeIdClusterId(props.row.id, selectedCluster.id)"
@@ -140,8 +146,9 @@ limitations under the License.
               "
             />
           </q-td>
-          <q-td key="bounded" :props="props" auto-width>
+          <q-td key="bounded" v-if="enableBounded" :props="props" auto-width>
             <q-checkbox
+              v-if="enableBounded"
               class="q-mt-xs"
               :model-value="selectionBounded"
               :val="hashAttributeIdClusterId(props.row.id, selectedCluster.id)"
@@ -410,97 +417,110 @@ export default {
         rowsPerPage: 0,
         sortBy: 'clientServer',
       },
-      columns: [
-        {
-          name: 'status',
-          required: false,
-          label: '',
-          align: 'left',
-          style: 'width:1%',
-        },
-        {
-          name: 'included',
-          label: 'Enabled',
-          field: 'included',
-          align: 'left',
-        },
-        {
-          name: 'attrID',
-          align: 'left',
-          label: 'Attribute ID',
-          field: 'attrID',
-          sortable: true,
-          style: 'max-width: 90px',
-          headerStyle: 'max-width: 90px',
-        },
-        {
-          name: 'attrName',
-          label: 'Attribute',
-          field: 'attrName',
-          align: 'left',
-          sortable: true,
-        },
-        {
-          name: 'required',
-          label: 'Required',
-          field: 'required',
-          align: 'left',
-          sortable: true,
-        },
-        {
-          name: 'clientServer',
-          label: 'Client/Server',
-          field: 'clientServer',
-          align: 'left',
-          sortable: true,
-        },
-        {
-          name: 'mfgID',
-          label: 'Mfg Code',
-          align: 'left',
-          field: 'mfgID',
-          sortable: true,
-        },
-        {
-          name: 'storageOption',
-          label: 'Storage Option',
-          align: 'left',
-          field: 'storageOption',
-          sortable: true,
-        },
-        {
-          name: 'singleton',
-          align: 'left',
-          label: 'Singleton',
-          field: 'singleton',
-          sortable: true,
-        },
-        {
-          name: 'bounded',
-          align: 'left',
-          label: 'Bounded',
-          field: 'bounded',
-          sortable: true,
-        },
-        {
-          name: 'type',
-          align: 'left',
-          label: 'Type',
-          field: 'type',
-          sortable: true,
-        },
-        {
-          name: 'default',
-          align: 'left',
-          label: 'Default',
-          field: 'default',
-          style: 'min-width: 180px',
-          headerStyle: 'min-width: 180px',
-        },
-      ],
+      columns: [],
       forcedExternal: [],
+      enableSingleton: false,
+      enableBounded: false,
     }
   },
+  mounted() {
+    this.columns = [
+      {
+        name: 'status',
+        required: false,
+        label: '',
+        align: 'left',
+        style: 'width:1%',
+      },
+      {
+        name: 'included',
+        label: 'Enabled',
+        field: 'included',
+        align: 'left',
+      },
+      {
+        name: 'attrID',
+        align: 'left',
+        label: 'Attribute ID',
+        field: 'attrID',
+        sortable: true,
+        style: 'max-width: 90px',
+        headerStyle: 'max-width: 90px',
+      },
+      {
+        name: 'attrName',
+        label: 'Attribute',
+        field: 'attrName',
+        align: 'left',
+        sortable: true,
+      },
+      {
+        name: 'required',
+        label: 'Required',
+        field: 'required',
+        align: 'left',
+        sortable: true,
+      },
+      {
+        name: 'clientServer',
+        label: 'Client/Server',
+        field: 'clientServer',
+        align: 'left',
+        sortable: true,
+      },
+      {
+        name: 'mfgID',
+        label: 'Mfg Code',
+        align: 'left',
+        field: 'mfgID',
+        sortable: true,
+      },
+      {
+        name: 'storageOption',
+        label: 'Storage Option',
+        align: 'left',
+        field: 'storageOption',
+        sortable: true,
+      },
+      ...(this.enableSingleton
+        ? [
+            {
+              name: 'singleton',
+              align: 'left',
+              label: 'Singleton',
+              field: 'singleton',
+              sortable: true,
+            },
+          ]
+        : []),
+      ...(this.enableBounded
+        ? [
+            {
+              name: 'bounded',
+              align: 'left',
+              label: 'Bounded',
+              field: 'bounded',
+              sortable: true,
+            },
+          ]
+        : []),
+      {
+        name: 'type',
+        align: 'left',
+        label: 'Type',
+        field: 'type',
+        sortable: true,
+      },
+      {
+        name: 'default',
+        align: 'left',
+        label: 'Default',
+        field: 'default',
+        style: 'min-width: 180px',
+        headerStyle: 'min-width: 180px',
+      },
+    ]
+  },
   created() {
     if (this.$serverGet != null) {
       this.forcedExternal = []
diff --git a/src/components/ZclCreateModifyEndpoint.vue b/src/components/ZclCreateModifyEndpoint.vue
index 3a1f6226..83f1c104 100644
--- a/src/components/ZclCreateModifyEndpoint.vue
+++ b/src/components/ZclCreateModifyEndpoint.vue
@@ -32,7 +32,7 @@ limitations under the License.
             min="0"
           />
           <q-input
-            v-if="$store.state.zap.isProfileIdShown"
+            v-if="enableProfileId"
             label="Profile ID"
             v-model="computedProfileId"
             ref="profile"
@@ -136,6 +136,7 @@ limitations under the License.
 
           <div class="q-gutter-md row">
             <q-input
+              v-if="enableNetworkId"
               label="Network"
               type="number"
               v-model="shownEndpoint.networkIdentifier"
@@ -198,6 +199,7 @@ limitations under the License.
 import * as RestApi from '../../src-shared/rest-api'
 import * as DbEnum from '../../src-shared/db-enum'
 import CommonMixin from '../util/common-mixin'
+import uiOptions from '../util/ui-options'
 const _ = require('lodash')
 import * as dbEnum from '../../src-shared/db-enum.js'
 
@@ -205,7 +207,7 @@ export default {
   name: 'ZclCreateModifyEndpoint',
   props: ['endpointReference'],
   emits: ['saveOrCreateValidated', 'updateData'],
-  mixins: [CommonMixin],
+  mixins: [CommonMixin, uiOptions],
   watch: {
     deviceTypeRefAndDeviceIdPair(val) {
       this.setDeviceTypeCallback(val)
@@ -254,13 +256,6 @@ export default {
     } else {
       this.shownEndpoint.endpointIdentifier = this.getSmallestUnusedEndpointId()
     }
-
-    const enableMatterFeatures =
-      this.$store.state.zap.selectedZapConfig?.zclProperties?.category ===
-      'matter'
-    this.enableMultipleDevice = enableMatterFeatures
-    this.enablePrimaryDevice = enableMatterFeatures
-    this.enableParentEndpoint = enableMatterFeatures
   },
   data() {
     return {
@@ -275,9 +270,6 @@ export default {
       saveOrCreateCloseFlag: false,
       deviceTypeTmp: [], // Temp store for the selected device types
       primaryDeviceTypeTmp: null, // Temp store for the selected primary device type
-      enableMultipleDevice: false,
-      enablePrimaryDevice: false,
-      enableParentEndpoint: false,
       endpointIds: [],
     }
   },
@@ -484,14 +476,10 @@ export default {
       }
     },
     saveOrCreateHandler() {
-      let profile = this.$store.state.zap.isProfileIdShown
-        ? this.$refs.profile.validate()
-        : true
-
+      let profile = this.enableProfileId ? this.$refs.profile.validate() : true
       if (
         this.$refs.endpoint.validate() &&
         this.$refs.device.validate() &&
-        this.$refs.network.validate() &&
         (this.$refs.version?.validate?.() ??
           !this.$refs.version?.includes((v) => !(v >= 0))) &&
         profile
diff --git a/src/components/ZclDomainClusterView.vue b/src/components/ZclDomainClusterView.vue
index 06455f88..19753300 100644
--- a/src/components/ZclDomainClusterView.vue
+++ b/src/components/ZclDomainClusterView.vue
@@ -219,6 +219,7 @@ limitations under the License.
 <script>
 import CommonMixin from '../util/common-mixin'
 import restApi from '../../src-shared/rest-api'
+import uiOptions from '../util/ui-options'
 
 let ZclClusterRoleAction = {
   Add: 'add',
@@ -230,8 +231,23 @@ let ZclClusterRole = { server: 'server', client: 'client' }
 export default {
   name: 'ZclDomainClusterView',
   props: ['domainName', 'clusters'],
-  mixins: [CommonMixin],
+  mixins: [CommonMixin, uiOptions],
   computed: {
+    clusterSelectionOptions() {
+      if (this.enableServerOnly) {
+        return [
+          { label: 'Not Enabled', client: false, server: false },
+          { label: 'Server', client: false, server: true },
+        ]
+      } else {
+        return [
+          { label: 'Not Enabled', client: false, server: false },
+          { label: 'Client', client: true, server: false },
+          { label: 'Server', client: false, server: true },
+          { label: 'Client & Server', client: true, server: true },
+        ]
+      }
+    },
     showStatus: {
       get() {
         return !this.$store.state.zap.standalone
@@ -524,12 +540,6 @@ export default {
       ZclClusterRole,
       showEnableAllClustersDialog: false,
       uc_label: 'uc label',
-      clusterSelectionOptions: [
-        { label: 'Not Enabled', client: false, server: false },
-        { label: 'Client', client: true, server: false },
-        { label: 'Server', client: false, server: true },
-        { label: 'Client & Server', client: true, server: true },
-      ],
       columns: [
         {
           name: 'status',
diff --git a/src/components/ZclEndpointCard.vue b/src/components/ZclEndpointCard.vue
index bb9708ff..0626bd01 100644
--- a/src/components/ZclEndpointCard.vue
+++ b/src/components/ZclEndpointCard.vue
@@ -265,6 +265,7 @@ limitations under the License.
 <script>
 import ZclCreateModifyEndpoint from './ZclCreateModifyEndpoint.vue'
 import CommonMixin from '../util/common-mixin'
+import uiOptions from '../util/ui-options'
 import * as Storage from '../util/storage'
 import restApi from '../../src-shared/rest-api'
 import * as Util from '../util/util'
@@ -273,7 +274,7 @@ import * as dbEnum from '../../src-shared/db-enum.js'
 export default {
   name: 'ZclEndpointCard',
   props: ['endpointReference'],
-  mixins: [CommonMixin],
+  mixins: [CommonMixin, uiOptions],
   components: { ZclCreateModifyEndpoint },
   data() {
     return {
@@ -552,10 +553,6 @@ export default {
       this.selectedReporting = []
       this.getEndpointCardData()
       //only show Matter features if Matter is selected
-      const enableMatterFeatures =
-        this.$store.state.zap.selectedZapConfig?.zclProperties?.category ===
-        'matter'
-      this.enableParentEndpoint = enableMatterFeatures
     }
   },
 }
diff --git a/src/util/ui-options.js b/src/util/ui-options.js
new file mode 100644
index 00000000..6a9952b8
--- /dev/null
+++ b/src/util/ui-options.js
@@ -0,0 +1,31 @@
+// mixin.js
+export default {
+  data() {
+    return {
+      enableProfileId: false,
+      enableNetworkId: false,
+      enableMultipleDevice: false,
+      enablePrimaryDevice: false,
+      enableParentEndpoint: false,
+      enableServerOnly: false,
+      enableSingleton: false,
+      enableBounded: false,
+    }
+  },
+  mounted() {
+    const enableZigbeeFeatures =
+      this.$store.state.zap.selectedZapConfig?.zclProperties?.category ===
+      'zigbee'
+    this.enableProfileId = enableZigbeeFeatures
+    this.enableNetworkId = enableZigbeeFeatures
+    this.enableSingleton = enableZigbeeFeatures
+    this.enableBounded = enableZigbeeFeatures
+    const enableMatterFeatures =
+      this.$store.state.zap.selectedZapConfig?.zclProperties?.category ===
+      'matter'
+    this.enableMultipleDevice = enableMatterFeatures
+    this.enablePrimaryDevice = enableMatterFeatures
+    this.enableParentEndpoint = enableMatterFeatures
+    this.enableServerOnly = enableMatterFeatures
+  },
+}
-- 
GitLab