Browse Source

[ui] Vue 3 - Migrated ERD components

sreenaths 4 years ago
parent
commit
8b5b81d679

+ 14 - 8
desktop/core/src/desktop/js/components/er-diagram/comps/literal-entity.vue

@@ -27,14 +27,20 @@
 </template>
 
 <script lang="ts">
-  import { Component, Prop, Vue } from 'vue-property-decorator';
+  import { defineComponent } from 'vue';
   import { Literal } from '../lib/entities';
 
-  import './literal-entity.scss';
-
-  @Component
-  export default class LiteralEntity extends Vue {
-    @Prop()
-    entity!: Literal;
-  }
+  export default defineComponent({
+    props: {
+      entity: {
+        type: Literal,
+        required: true
+      }
+    },
+    emits: ['click']
+  });
 </script>
+
+<style lang="scss">
+  @import './literal-entity.scss';
+</style>

+ 6 - 6
desktop/core/src/desktop/js/components/er-diagram/comps/table-entity.test.ts

@@ -74,14 +74,14 @@ describe('TableEntity UTs', () => {
     expect(wrapper.findAll('.columns-container .column-entity .left-point')).toHaveLength(2);
     expect(wrapper.findAll('.columns-container .column-entity .right-point')).toHaveLength(2);
 
-    expect(wrapper.findAll('.columns-container .column-entity').at(0).text()).toBe(columnNames[0]);
+    expect(wrapper.findAll('.columns-container .column-entity')[0].text()).toBe(columnNames[0]);
     expect(
-      wrapper.findAll('.columns-container .column-entity').at(0).attributes('data-entity-id')
+      wrapper.findAll('.columns-container .column-entity')[0].attributes('data-entity-id')
     ).toBe(`${tableId}.${columnNames[0]}`);
 
-    expect(wrapper.findAll('.columns-container .column-entity').at(1).text()).toBe(columnNames[1]);
+    expect(wrapper.findAll('.columns-container .column-entity')[1].text()).toBe(columnNames[1]);
     expect(
-      wrapper.findAll('.columns-container .column-entity').at(1).attributes('data-entity-id')
+      wrapper.findAll('.columns-container .column-entity')[1].attributes('data-entity-id')
     ).toBe(`${tableId}.${columnNames[1]}`);
 
     expect(wrapper.find('.grouped-columns').exists()).toBeFalsy();
@@ -120,8 +120,8 @@ describe('TableEntity UTs', () => {
     const columnElements = wrapper.findAll('.columns-container .column-entity');
     columns.forEach((column: Column, index: number) => {
       if (index < defaultMaxColumns) {
-        expect(columnElements.at(index).text()).toBe(column.name);
-        expect(columnElements.at(index).attributes('data-entity-id')).toBe(column.id);
+        expect(columnElements[index].text()).toBe(column.name);
+        expect(columnElements[index].attributes('data-entity-id')).toBe(column.id);
       } else {
         expect(groupedEntitiesIds.includes(column.id)).toBeTruthy();
       }

+ 33 - 13
desktop/core/src/desktop/js/components/er-diagram/comps/table-entity.vue

@@ -59,28 +59,48 @@
 </template>
 
 <script lang="ts">
-  import { Component, Prop, Vue } from 'vue-property-decorator';
+  import { defineComponent, PropType } from 'vue';
+
   import { Table } from '../lib/entities';
 
-  import './table-entity.scss';
+  export default defineComponent({
+    props: {
+      entity: {
+        type: Object as PropType<Table>,
+        required: true
+      },
+      maxColumns: {
+        type: Number,
+        default: 10
+      }
+    },
 
-  @Component
-  export default class TableEntity extends Vue {
-    @Prop() entity: Table;
-    @Prop({ default: 10 }) maxColumns: number;
+    emits: ['click', 'updated'],
 
-    maxCols = 0;
+    data(): {
+      maxCols: number;
+    } {
+      return {
+        maxCols: 0
+      };
+    },
 
     created(): void {
       this.maxCols = this.maxColumns;
-    }
-
-    expandColumns(): void {
-      this.maxCols = Number.MAX_SAFE_INTEGER;
-    }
+    },
 
     updated(): void {
       this.$emit('updated');
+    },
+
+    methods: {
+      expandColumns(): void {
+        this.maxCols = Number.MAX_SAFE_INTEGER;
+      }
     }
-  }
+  });
 </script>
+
+<style lang="scss">
+  @import './table-entity.scss';
+</style>

+ 5 - 5
desktop/core/src/desktop/js/components/er-diagram/er-diagram.test.ts

@@ -154,8 +154,8 @@ describe('ERDiagram integration tests', () => {
     expect(wrapper.findAll('.entity-container')).toHaveLength(tableCount);
     expect(wrapper.findAll('.relation-path')).toHaveLength(2);
 
-    expect(wrapper.findAll('.relation-path').at(0).attributes('d')).toBe('M 0,1 C 40,1 -40,1 0,1');
-    expect(wrapper.findAll('.relation-path').at(1).attributes('d')).toBe('M 0,1 C 40,1 -40,1 0,1');
+    expect(wrapper.findAll('.relation-path')[0].attributes('d')).toBe('M 0,1 C 40,1 -40,1 0,1');
+    expect(wrapper.findAll('.relation-path')[1].attributes('d')).toBe('M 0,1 C 40,1 -40,1 0,1');
   });
 
   test('Real data test', () => {
@@ -171,8 +171,8 @@ describe('ERDiagram integration tests', () => {
 
     expect(wrapper.findAll('.entity-group')).toHaveLength(2);
 
-    expect(wrapper.findAll('.relation-path').at(0).attributes('d')).toBe('M 0,1 C 40,1 -40,1 0,1');
-    expect(wrapper.findAll('.relation-path').at(1).attributes('d')).toBe('M 0,1 C 40,1 -40,1 0,1');
-    expect(wrapper.findAll('.relation-path').at(2).attributes('d')).toBe('M 0,1 C 40,1 -40,1 0,1');
+    expect(wrapper.findAll('.relation-path')[0].attributes('d')).toBe('M 0,1 C 40,1 -40,1 0,1');
+    expect(wrapper.findAll('.relation-path')[1].attributes('d')).toBe('M 0,1 C 40,1 -40,1 0,1');
+    expect(wrapper.findAll('.relation-path')[2].attributes('d')).toBe('M 0,1 C 40,1 -40,1 0,1');
   });
 });

+ 94 - 73
desktop/core/src/desktop/js/components/er-diagram/index.vue

@@ -17,15 +17,15 @@
 -->
 
 <template>
-  <div class="er-diagram">
+  <div ref="erd" class="er-diagram">
     <div class="buttons-panel">
       <button class="btn btn-default btn-sm" title="Toggle Fullscreen" @click="toggleFS">
-        <expand-icon v-pre class="fa fa-expand" />
+        <expand-icon v-pre class="fa fa-expand">&#8203;</expand-icon>
       </button>
     </div>
 
     <div class="erd-scroll-panel">
-      <div class="erd-container">
+      <div v-if="groups" class="erd-container">
         <div v-for="(group, index) in groups" :key="index" class="entity-group">
           <div v-for="entity in group" :key="entity.id" class="entity-container">
             <TableEntity
@@ -44,7 +44,7 @@
         </div>
 
         <!-- Relations -->
-        <svg class="erd-relations">
+        <svg v-if="relations" class="erd-relations">
           <path
             v-for="(relation, index) in relations"
             :key="index"
@@ -59,7 +59,7 @@
 </template>
 
 <script lang="ts">
-  import { Component, Prop, Vue } from 'vue-property-decorator';
+  import { defineComponent, PropType } from 'vue';
 
   import { groupEntities } from './lib/processor';
   import { IEntity, IRelation } from './lib/interfaces';
@@ -70,8 +70,6 @@
   import TableEntity from './comps/table-entity.vue';
   import LiteralEntity from './comps/literal-entity.vue';
 
-  import './er-diagram.scss';
-
   const CURVATURE = 40;
 
   interface IPos {
@@ -79,84 +77,107 @@
     y: number;
   }
 
-  @Component({
+  export default defineComponent({
     components: {
       TableEntity,
       LiteralEntity
-    }
-  })
-  export default class ERDiagram extends Vue {
-    @Prop()
-    entities!: IEntity[];
-    @Prop()
-    relations!: IRelation[];
-
-    EntityTypes = EntityTypes;
-
-    get groups(): IEntity[][] | undefined {
-      if (this.entities && this.relations) {
-        return groupEntities(this.entities, this.relations);
+    },
+
+    props: {
+      entities: {
+        type: Object as PropType<IEntity[]>,
+        default: []
+      },
+      relations: {
+        type: Object as PropType<IRelation[]>,
+        default: []
       }
-    }
+    },
 
-    getSelectorPosition(selector: string, offset: IPos | undefined = undefined): IPos | undefined {
-      const element = this.$el.querySelector(selector);
-      if (element) {
-        const rect = element.getBoundingClientRect();
-        let x = rect.left;
-        let y = rect.top;
+    emits: ['toggle-fullscreen', 'entity-clicked'],
 
-        if (offset) {
-          x = x - offset.x;
-          y = y - offset.y + 1;
-        }
+    setup() {
+      return {
+        EntityTypes
+      };
+    },
 
-        return { x, y };
+    computed: {
+      groups(): IEntity[][] | undefined {
+        if (this.entities && this.relations) {
+          return groupEntities(this.entities, this.relations);
+        }
+        return undefined;
       }
-    }
+    },
 
-    plotRelations(): void {
-      const relationPaths: NodeListOf<HTMLElement> = this.$el.querySelectorAll<HTMLElement>(
-        '.relation-path'
-      );
-      const offset: IPos | undefined = this.getSelectorPosition('.erd-relations');
-
-      relationPaths.forEach(element => {
-        const leftPos = this.getSelectorPosition(
-          `[data-entity-id~="${element.dataset.entityIdLeft}"] .right-point`,
-          offset
-        );
-        const rightPos = this.getSelectorPosition(
-          `[data-entity-id~="${element.dataset.entityIdRight}"] .left-point`,
-          offset
-        );
-
-        if (leftPos && rightPos) {
-          const path: string =
-            `M ${leftPos.x},${leftPos.y} C ${leftPos.x + CURVATURE},${leftPos.y} ` +
-            `${rightPos.x - CURVATURE},${rightPos.y} ${rightPos.x},${rightPos.y}`;
-          element.setAttribute('d', path);
-
-          element.style.visibility = 'visible';
-        } else {
-          element.style.visibility = 'hidden';
-        }
-      });
-    }
     updated(): void {
       this.plotRelations();
-    }
+    },
     mounted(): void {
       this.plotRelations();
+    },
+
+    methods: {
+      getSelectorPosition(
+        selector: string,
+        offset: IPos | undefined = undefined
+      ): IPos | undefined {
+        const element = this.$el.querySelector(selector);
+        if (element) {
+          const rect = element.getBoundingClientRect();
+          let x = rect.left;
+          let y = rect.top;
+
+          if (offset) {
+            x = x - offset.x;
+            y = y - offset.y + 1;
+          }
+
+          return { x, y };
+        }
+      },
+      plotRelations(): void {
+        const erdEl = this.$refs.erd as HTMLElement;
+        const relationPaths: NodeListOf<HTMLElement> = erdEl.querySelectorAll<HTMLElement>(
+          '.relation-path'
+        );
+        const offset: IPos | undefined = this.getSelectorPosition('.erd-relations');
+
+        relationPaths.forEach(element => {
+          const leftPos = this.getSelectorPosition(
+            `[data-entity-id~="${element.dataset.entityIdLeft}"] .right-point`,
+            offset
+          );
+          const rightPos = this.getSelectorPosition(
+            `[data-entity-id~="${element.dataset.entityIdRight}"] .left-point`,
+            offset
+          );
+
+          if (leftPos && rightPos) {
+            const path: string =
+              `M ${leftPos.x},${leftPos.y} C ${leftPos.x + CURVATURE},${leftPos.y} ` +
+              `${rightPos.x - CURVATURE},${rightPos.y} ${rightPos.x},${rightPos.y}`;
+            element.setAttribute('d', path);
+
+            element.style.visibility = 'visible';
+          } else {
+            element.style.visibility = 'hidden';
+          }
+        });
+      },
+      toggleFS(): void {
+        toggleFullScreen(this.$el);
+        this.$emit('toggle-fullscreen');
+      },
+
+      entityClicked(entity: IEntity): void {
+        this.$emit('entity-clicked', entity);
+      }
     }
-
-    toggleFS(): void {
-      toggleFullScreen(this.$el);
-      this.$emit('toggle-fullscreen');
-    }
-
-    entityClicked(entity: IEntity): void {
-      this.$emit('entity-clicked', entity);
-    }
-  }
+  });
 </script>
+
+<style lang="scss">
+  @import './er-diagram.scss';
+</style>

+ 1 - 1
desktop/core/src/desktop/js/components/er-diagram/webcomp.ts

@@ -17,7 +17,7 @@
  */
 
 import ERDiagram from './index.vue';
-import { wrap } from 'vue/webComponentWrapper';
+import { wrap } from 'vue/webComponentWrap';
 
 export const COMPONENT_NAME = 'er-diagram';
 wrap(COMPONENT_NAME, ERDiagram);