From 906860ee74c12de308a24136c6c232dad1bc4b45 Mon Sep 17 00:00:00 2001
From: Satish Khanna <skhanna@associates.nsf.gov>
Date: Wed, 4 Jan 2023 20:18:10 -0500
Subject: [PATCH] feat(ui-filter): added  input field title property
 feat(ui-table): added  no records text , no filter results text  and filter
 title property feat(ui-table): added  ui-table tests

---
 addon/components/ui-filter/input/component.ts |   5 +
 addon/components/ui-filter/input/template.hbs |   1 +
 addon/components/ui-table/component.ts        |  15 +++
 addon/components/ui-table/template.hbs        |  13 ++
 addon/components/ui-table/ui-table.stories.ts |   3 +
 tests/integration/components/ui-table-test.ts | 112 ++++++++++++++++++
 6 files changed, 149 insertions(+)
 create mode 100644 tests/integration/components/ui-table-test.ts

diff --git a/addon/components/ui-filter/input/component.ts b/addon/components/ui-filter/input/component.ts
index 503dabc..486a9ef 100644
--- a/addon/components/ui-filter/input/component.ts
+++ b/addon/components/ui-filter/input/component.ts
@@ -15,6 +15,11 @@ export default class UiFilterInput extends Component {
    */
   public label?: string = 'Filter Input Field';
 
+  /**
+   * The text input's title text.
+   */
+  public title?: string;
+
   /**
    * The text input's placeholder text.
    */
diff --git a/addon/components/ui-filter/input/template.hbs b/addon/components/ui-filter/input/template.hbs
index ab1da71..5254798 100644
--- a/addon/components/ui-filter/input/template.hbs
+++ b/addon/components/ui-filter/input/template.hbs
@@ -20,6 +20,7 @@
   value="{{this.value}}"
   class="form-control"
   placeholder={{this.placeholder}}
+  title={{this.title}}
   disabled={{this.disabled}}
   aria-label="{{this.label}}"
   oninput={{this.handleInputChange}}
diff --git a/addon/components/ui-table/component.ts b/addon/components/ui-table/component.ts
index 63101ea..e2ab074 100644
--- a/addon/components/ui-table/component.ts
+++ b/addon/components/ui-table/component.ts
@@ -44,6 +44,11 @@ export default class UiTable extends Component {
    */
   public filterPlaceholder?: string;
 
+  /**
+   * The filter text input's title text.
+   */
+  public filterTitle?: string;
+
   /**
    * Whether filtering of the table's contents is enabled. By default, this
    * includes adding some UI to the top control bar such a text input to
@@ -57,6 +62,16 @@ export default class UiTable extends Component {
    */
   public pagingEnabled = true;
 
+  /**
+   * Text to display when there are no records.
+   */
+  public noRecordsText?: string = 'No records exist';
+
+  /**
+   * Text to display when there are no records found while filtering.
+   */
+  public noFilterResultsText?: string = 'Nothing found to display';
+
   protected get tableGuid() {
     return `${guidFor(this)}-table`;
   }
diff --git a/addon/components/ui-table/template.hbs b/addon/components/ui-table/template.hbs
index 9377804..6f118d9 100644
--- a/addon/components/ui-table/template.hbs
+++ b/addon/components/ui-table/template.hbs
@@ -27,6 +27,7 @@ input of the next tier down.
             filters         = this.filters
             showClearButton = this.showFilterClearButton
             placeholder     = this.filterPlaceholder
+            title           = this.filterTitle
           )
         as |PagerSizeOptions PagerNavbar FilterInput|}}
           {{#if (has-block "topControlBar")}}
@@ -113,6 +114,17 @@ input of the next tier down.
                 </tr>
               {{/each}}
             {{/if}}
+            {{#if (or (eq Filter.filteredRecords.length 0) (eq this.records.length 0))}}
+              <tr>
+                <td class='text-center' colspan='{{this.columns.length}}'>
+                  {{#if (eq this.records.length 0)}}
+                    {{this.noRecordsText}}
+                  {{else}}
+                    {{this.noFilterResultsText}}
+                  {{/if}}
+                </td>
+              </tr>
+            {{/if}}
           </tbody>
         </table>
 
@@ -135,6 +147,7 @@ input of the next tier down.
             filters         = this.filters
             showClearButton = this.showFilterClearButton
             placeholder     = this.filterPlaceholder
+            title           = this.filterTitle
           )
         as |PagerSizeOptions PagerNavbar FilterInput|}}
           {{#if (has-block "bottomControlBar")}}
diff --git a/addon/components/ui-table/ui-table.stories.ts b/addon/components/ui-table/ui-table.stories.ts
index 9027400..13e5a03 100644
--- a/addon/components/ui-table/ui-table.stories.ts
+++ b/addon/components/ui-table/ui-table.stories.ts
@@ -59,8 +59,11 @@ export const Default = (context: unknown) => {
         @filterRules={{this.filterRules}}
         @showFilterClearButton={{this.showFilterClearButton}}
         @filterPlaceholder={{this.filterPlaceholder}}
+        @filterTitle={{this.filterTitle}}
         @pagingEnabled={{this.pagingEnabled}}
         @filterEnabled={{this.filterEnabled}}
+        @noRecordsText={{this.noRecordsText}}
+        @noFilterResultsText={{this.noFilterResultsText}}
       />
     `,
   };
diff --git a/tests/integration/components/ui-table-test.ts b/tests/integration/components/ui-table-test.ts
new file mode 100644
index 0000000..5c6f43f
--- /dev/null
+++ b/tests/integration/components/ui-table-test.ts
@@ -0,0 +1,112 @@
+import { module, test } from 'qunit';
+import { setupRenderingTest } from 'ember-qunit';
+import { click, fillIn, render } from '@ember/test-helpers';
+import hbs from 'htmlbars-inline-precompile';
+
+module('Integration | Component | ui-table', function (hooks) {
+  setupRenderingTest(hooks);
+
+  const filterRules = ['firstName', 'lastName'];
+
+  const columns = [
+    { propertyName: 'firstName', sortOn: 'firstName', label: 'First Name' },
+    { propertyName: 'lastName', sortOn: 'lastName', label: 'Last Name' },
+  ];
+
+  const recordSet = [
+    { firstName: 'Herbert', lastName: 'Labadie' },
+    { firstName: 'Caleb', lastName: 'Welch' },
+    { firstName: 'Lila', lastName: 'Yundt' },
+    { firstName: 'Brittany', lastName: 'Kuhic' },
+    { firstName: 'Terence', lastName: 'Brakus' },
+    { firstName: 'Iris', lastName: 'Feil' },
+    { firstName: 'Homer', lastName: 'Dietrich' },
+    { firstName: 'Stacy', lastName: 'Dietrich' },
+    { firstName: 'Karla', lastName: 'Dietrich' },
+    { firstName: 'Clifton', lastName: 'Koelpin' },
+    { firstName: 'Olive', lastName: 'Abernathy' },
+    { firstName: 'Debra', lastName: 'Feil' },
+    { firstName: 'Melody', lastName: 'Kreiger' },
+    { firstName: 'Belinda', lastName: 'Emard' },
+    { firstName: 'Lyle', lastName: 'Halvorson' },
+  ];
+
+  async function renderComponent() {
+    // language=handlebars
+    await render(hbs`
+      <UiTable
+        @columns={{this.columns}}
+        @records={{this.records}}
+        @pagingEnabled={{this.pagingEnabled}}
+        @filterEnabled={{this.filterEnabled}}
+        @filterRules={{this.filterRules}}
+        @showFilterClearButton={{this.showFilterClearButton}}
+        @filterPlaceholder={{this.filterPlaceholder}}
+        @filterTitle={{this.filterTitle}}
+        @noRecordsText={{this.noRecordsText}}
+        @noFilterResultsText={{this.noFilterResultsText}}
+      />
+    `);
+  }
+
+  /**
+   * Basic Table Display, no results.
+   */
+  test('ui table display, when there no records displays a row with no records text', async function (assert) {
+    this.set('columns', columns);
+    this.set('records', recordSet);
+
+    await renderComponent();
+
+    assert.dom('.ui-table').isVisible();
+    assert.dom('.ui-table').hasTagName('div');
+
+    assert.strictEqual(recordSet.length, 15, 'Table has 15 rows');
+
+    assert.dom('table thead tr').exists({ count: 1 });
+
+    // No records
+    this.set('records', []);
+    this.set('noRecordsText', 'No records exist');
+
+    await renderComponent();
+    assert.dom('table tbody tr').hasText('No records exist');
+  });
+
+  /**
+   * Filter Tests.
+   */
+  test('ui table filter tests, it filters an array using string filter rules', async function (assert) {
+    this.set('columns', columns);
+    this.set('records', recordSet);
+    this.set('filterEnabled', true);
+    this.set('filterRules', filterRules);
+    this.set('showFilterClearButton', true);
+    this.set('filterPlaceholder', 'Filter');
+    this.set('filterTitle', 'Filter title');
+    this.set('noFilterResultsText', 'Nothing found to display');
+
+    await renderComponent();
+
+    assert.dom('table tbody tr').exists({ count: 15 });
+    assert.dom('input[type="text"]').hasNoValue();
+    assert.dom('input[type="text"]').hasProperty('placeholder', 'Filter');
+    assert.dom('input[type="text"]').hasProperty('title', 'Filter title');
+
+    await fillIn('input[type="text"]', 'Dietrich');
+    assert.dom('table tbody tr').exists({ count: 3 });
+
+    await fillIn('input[type="text"]', 'Caleb');
+    assert.dom('table tbody tr').exists({ count: 1 });
+
+    await fillIn('input[type="text"]', 'asjd');
+
+    assert.dom('table tbody tr td').hasText('Nothing found to display');
+
+    assert.dom('.input-group button.ui-filter-reset').hasAria('label', 'Reset Filter Input Field');
+
+    await click('.input-group button.ui-filter-reset');
+
+    assert.dom('input[type="text"]').hasNoValue();
+  });
+});