## Spec for DisplayItems Package

A module for displaying and filtering data with tools for hooking actions into the resulting records

## Table of Contents

- [Spec for DisplayItems Package](#spec-for-displayitems-package)
- [Table of Contents](#table-of-contents)
- [Workflow](#workflow)
- [User Stories](#user-stories)
- [Test Plan](#test-plan)
- [Acceptance Tests](#acceptance-tests)
- [Screens / States](#screens--states)
- [Components](#components)
  - [Layouts](#layouts)
  - [Containers](#containers)
  - [Components](#components-1)
- [Schema](#schema)
  - [Component Schema](#component-schema)
    - [DisplayItems](#displayitems)
      - [Schema](#schema-1)
      - [Tests](#tests)
    - [DataCard](#datacard)
      - [Schema](#schema-2)
      - [Tests](#tests-1)
    - [FilterGroup](#filtergroup)
      - [Schema](#schema-3)
      - [Tests](#tests-2)
    - [AlphabetFilter](#alphabetfilter)
      - [Schema](#schema-4)
      - [Tests](#tests-3)
    - [BulkActionsMenu](#bulkactionsmenu)
      - [Schema](#schema-5)
      - [Tests](#tests-4)
    - [BulkSelectedActions](#bulkselectedactions)
      - [Schema](#schema-6)
      - [Tests](#tests-5)
    - [EmptyStateComponent](#emptystatecomponent)
      - [Schema](#schema-7)
      - [Tests](#tests-6)
  - [Database Schema](#database-schema)
  - [Store/Reducers](#storereducers)
  - [APIs/Hook Schema](#apishook-schema)

## Workflow

![]()

## User Stories

- As a user I would like to display data I retrieve from an external source in user friendly ways
- As a user I would like a way to quickly switch between various views (e.g. table, card, kanban)
- As a developer I would like ways to customize the appears and feature set of the CRUD that I am using (show/hide components, replace components, customize menu items, hook into user actions, etc.)
- As a user I would like tools that help me filter the incoming data in various ways (e.g. column 'email' contains 'gmail.com')
- As a user I would like to 'stack' filters for a more granular search
- As a user I would like those filters to filter data that has already been provided or convert filter requests into instructions to query my data source for a filtered response
- As a user I would like a quick way to save and re-deploy filters I create as 'Saved Searches'
- As a user I would like to sort my data by any of the available columns (or just a default 'name' column)
- As a user I would like a way to select multiple items and apply customizable BULK actions to my selected list (e.g. 'Delete All', 'Send Broadcast Email')
- As a user I would like a quick way to export my filtered view as a CSV/Excel Spreadsheet
- As a user I would like to customize the main label/header that's displayed in the CRUD component (e.g. Products, Users, Campaigns, etc.)
- As a user I may have a very large data set, so would like to show a limited number of records at a time
- As a user I would like to choose how much records to show at a time
- As a user I would like to paginate between my large list of records

## Test Plan

| Scenario                                  | Expected                                                                                    | Automated | Type        |
| ----------------------------------------- | ------------------------------------------------------------------------------------------- | --------- | ----------- |
| Bulk Action Menu is Clicked               | Should show a menu of items                                                                 | Yes       | Integration |
| Item Action Menu button is Clicked        | Should show a menu of items that match items found in the dataItemActions prop              | Yes       | Integration |
| New Record is Created                     | A new record should be displayed in the list of records                                     | Yes       | Integration |
| Existing Record Changes                   | The data underlying the record should reflect the change                                    | Yes       | Integration |
| Existing Record is Deleted                | The deleted record should no longer be in the dom                                           | Yes       | Integration |
| A filter is saved                         | Should show another item in the list of saved filters                                       | Yes       | Integration |
| The active filter changes                 | A different/matching set of records should be displayed in the dom                          | Yes       | Integration |
| A column is sorted                        | The list of data records should be shown in alphabetical order based on the column selected | Yes       | Integration |
| Data export is requested                  | A CSV file should be generated and downloaded                                               | Yes       | Integration |
| Navigates to a different page             | The next set of records should be shown                                                     | Yes       | Integration |
| Number of rows to show per page changes   | The total list of records rendered should match the number proved                           | Yes       | Integration |
| 'Select All' option is triggered          | The checkbox for all visible records should be checked                                      | Yes       | Integration |
| 'Select All (filter)' option is triggered | The checkbox for all matching records should be checked                                     | Yes       | Integration |

## Acceptance Tests

(N/A)

## Screens / States

![](http://ambid-backups.s3.amazonaws.com/screenshots/sandcastle/crud_screen_cards1.png)
![](http://ambid-backups.s3.amazonaws.com/screenshots/sandcastle/crud_screen_cards2.png)
![](http://ambid-backups.s3.amazonaws.com/screenshots/sandcastle/crud_screen_cards3.png)

## Components

### Layouts

N/A

### Containers

N/A

### Components

| Type       | Name                | Description                                                                                                        | Behaviors                             | Exists | Package |
| ---------- | ------------------- | ------------------------------------------------------------------------------------------------------------------ | ------------------------------------- | ------ | ------- |
| Components | DataCard            | The default card to use to display a record in the DisplayItems component                                          |                                       | No     | No      |
| Components | FilterGroup         | A component that provides filter controls against a provided data set and hooks for handling the filter selections |                                       | No     | No      |
| Components | AlphabetFilter      | A vertical list of letters (the alphabet) that filter the DisplayItems when clicked                                |                                       | No     | No      |
| Components | BulkActionsMenu     | A list of actions to be applied to the selected items in the data display.                                         | Able to create a menu/sub-menu system | No     | No      |
| Components | BulkSelectedActions | Shows when there are one or more items selected. Provides a quick way to perform bulk actions on the selected list |                                       | No     | No      |
| Components | EmptyStateComponent | Shows an empty state message, image, and optional action item                                                      |                                       | No     | No      |

## Schema

### Component Schema

#### DisplayItems

##### Schema

| Schema Type | Name                 | Type     | Description                                                                                                                   |
| ----------- | -------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------- |
| prop        | name                 | string   | The name to use for the dataDisplay component. Useful for plugins that want to hook into your specific data display vs others |
| prop        | type                 | enum     | Establishes the type of data display to show (card view or table view)                                                        |
| prop        | data                 | any[]    | The list of items to display                                                                                                  |
| prop        | columns              | any[]    | The list of fields (and their settings) you plan to use for this data display                                                 |
| prop        | loading              | Boolean  | Whether or not to show the loading component instead of the data records                                                      |
| prop        | loadingComponent     | element  | The component to use instead of the default loading component                                                                 |
| prop        | title                | string   | The title to show for the display                                                                                             |
| prop        | bulkActions          | any[]    | The list of bulk actions (and their settings) to provide the bulkActionControls component                                     |
| prop        | bulkActionsComponent | element  | The component to use instead of the default BulkActions component                                                             |
| prop        | showbulkActions      | Boolean  | Whether or not to show the bulkAction component                                                                               |
| prop        | dataItemActions      | any[]    | The list of available actions (and their settings) that can be applied to each data item that is displayed                    |
| prop        | dataItemComponent    | element  | The component to use for each item instead of the default DataDisplayCard component                                           |
| prop        | showCheckboxes       | Boolean  | Whether or not to show selectable checkboxes next to each item                                                                |
| prop        | filterComponent      | element  | The component to use instead of the default FilterGroup component                                                             |
| prop        | showFilterControls   | Boolean  | Whether or not to show the filter controls                                                                                    |
| prop        | showAlphabetFilter   | Boolean  | Whether or not to show the alphabet controls                                                                                  |
| prop        | emptyStateComponent  | element  | The component to use instead of the default EmptyStateComponent                                                               |
| prop        | tags                 | string[] | The list of tags (one-click search filters) to show                                                                           |
| prop        | showTags             | Boolean  | Whether or not the list of tags are to be showing or not                                                                      |
| prop        | showHeaders          | Boolean  | Whether or not to show the header                                                                                             |
| prop        | showPagination       | Boolean  | Whether or not to show pagination controls                                                                                    |
| prop        | paginationSettings   | any      | The settings to use for pagination                                                                                            |
| prop        | enableSorting        | Boolean  | Whether or not a sort icon is showing next to the field headers of a display table                                            |
| prop        | onCreate             | method   | Triggers with appropriate payload when a new record is to be created                                                          |
| prop        | onUpdate             | method   | Triggers with appropriate payload when an existing record is updated                                                          |
| prop        | onDelete             | method   | Triggers with appropriate payload when the delete option on a record is selected                                              |
| prop        | onSelect             | method   | Triggers when an individual record is selected (e.g. clicked)                                                                 |
| prop        | onSelectAll          | method   | Triggers when all items are to be selected                                                                                    |
| prop        | onRowActionSelect    | method   | Triggers when one of the row action items are selected                                                                        |
| prop        | onFilterChange       | method   | Triggers when the filter is to be changed                                                                                     |
| prop        | onFilterSave         | method   | Triggers when the current filter is to be saved                                                                               |
| prop        | onSort               | method   | Triggers when a sort is supposed to happen                                                                                    |
| prop        | onExport             | method   | Triggers when an export is supposed to happen                                                                                 |
| prop        | onImport             | method   | Triggers when an import is supposed to happen                                                                                 |
| prop        | onBulkActionSelect   | method   | Triggers when one of the bulk actions are selected                                                                            |
| prop        | onPaginationChange   | method   | Triggers when the page is supposed to change                                                                                  |
| method      | goToPage             | method   | Triggered when page change occurs                                                                                             |
| method      | setRowsPerPage       | method   | Triggered when pagination rows per page option changes                                                                        |
| method      | exportData           | method   | CSV download of the active filtered record set                                                                                |
| method      | selectAll            | method   | Method to select all of the items in the current view or filter                                                               |

##### Tests

| It                                                                                                                                          | Type       |
| ------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| -- Actions --                                                                                                                               | End to End |
| Should perform filter on local data if onChange prop does not return false                                                                  | End to End |
| Should display total pages in pagination set based on the rowsPerPage property in the paginationSettings prop                               | End to End |
| Should start record list on the designated page as specified by the 'page' property in the paginationSettings prop                          | End to End |
| -- Rendering --                                                                                                                             | End to End |
| Should render component in the dom                                                                                                          | End to End |
| Should render the same number of records as the amount of items found in the data prop                                                      | End to End |
| Should render a custom row card in the dom (instead of the default) when one is specified in dataItemComponent prop                         | End to End |
| Should render the default filter component in dom                                                                                           | End to End |
| Should render a custom filter component in dom when specified in filterComponent prop                                                       | End to End |
| Should not render any filter components when showFilterControls prop is false                                                               | End to End |
| Should render alphabet strip in dom when specified                                                                                          | End to End |
| Should render default bulk selected action component in dom when buttons are selected                                                       | End to End |
| Should render a custom bulk selected action component in dom when one is provided in the bulkActionsComponent prop                          | End to End |
| Should not render any bulk action components when showBulkActions prop is false                                                             | End to End |
| Should render a list of saved filter tags if the showTags prop is true and there is data in the tags prop                                   | End to End |
| Should not render any header components when showHeaders prop is false                                                                      | End to End |
| Should not render any sort icons when enableSorting prop is false                                                                           | End to End |
| Should not render any checkboxes (in cards or table) when the showCheckboxes prop is false                                                  | End to End |
| Should not render any pagination controls when showPagination prop is false                                                                 | End to End |
| Should render the AlphabetFilter component when showAlphabetFilter prop is true                                                             | End to End |
| Should render the loading component found in the loadingComponent prop in the dom if the loading prop is true                               | End to End |
| Should render a default loading image if loading prop is true and no loadingComponent is provided                                           | End to End |
| -- Props --                                                                                                                                 | End to End |
| Should show a list of cards if type prop is CARD                                                                                            | End to End |
| Should show a table if type prop is TABLE                                                                                                   | End to End |
| Should show a list of columns in the table that match the columns provided in the components prop                                           | End to End |
| Should render the text in title prop as an h2                                                                                               | End to End |
| Should show a menu of items when bulk action button is clicked that matches the items found in the bulkActions object provided in the props | End to End |
| Should show a menu of items when the 'actions' button on each row/record is clicked that matches items found in the dataItemActions prop    | End to End |
| -- Events --                                                                                                                                | End to End |
| Should trigger onCreate() with appropriate payload when a new record is to be created                                                       | End to End |
| Should trigger onUpdate() with appropriate payload when an existing record is updated                                                       | End to End |
| Should trigger onDelete() with appropriate payload when the delete option on a record is selected                                           | End to End |
| Should trigger onFilterSave() when the current filter is to be saved                                                                        | End to End |
| Should trigger onSelect() when an individual record is selected (e.g. clicked)                                                              | End to End |
| Should trigger onRowActionSelect() when one of the row action items are selected                                                            | End to End |
| Should trigger onFilterChange() when the filter is to be changed                                                                            | End to End |
| Should trigger onSort() when a sort is supposed to happen                                                                                   | End to End |
| Should trigger onExport() when an export is supposed to happen                                                                              | End to End |
| Should trigger onImport() when an import is supposed to happen                                                                              | End to End |
| Should trigger onBulkActionSelect(action) when one of the bulk actions are selected                                                         | End to End |
| Should trigger onPaginationChange() when the page is supposed to change                                                                     | End to End |
| -- Methods --                                                                                                                               | End to End |
| Should trigger goToPage() method when page change occurs                                                                                    | End to End |
| Should trigger setRowsPerPage() method when pagination rows per page option changes                                                         | End to End |
| Should trigger exportData() method when csv download/export option is selected                                                              | End to End |
| Should select all visible items when selectAll(visible) method is triggered                                                                 | End to End |
| Should select all items that match the existing filter when selectAll(filter) method is triggered                                           | End to End |

#### DataCard

##### Schema

| Schema Type | Name               | Type    | Description                                                                                                           |
| ----------- | ------------------ | ------- | --------------------------------------------------------------------------------------------------------------------- |
| prop        | icon               | string  | Display an optional icon in the card view                                                                             |
| prop        | image              | string  | Display an image in the main card view                                                                                |
| prop        | component          | element | Display component in the main card view                                                                               |
| prop        | tags               | any[]   | A list of tags, and associated actions to display on the card                                                         |
| prop        | label              | string  | The caption to show on the card                                                                                       |
| prop        | canEditLabel       | Boolean | Whether or not the label's name can be edited. Triggers onDataChange() event when clicked away, or [enter] is pressed |
| prop        | actions            | any[]   | The list of items you want to show in the actions dropdown menu, and the associated function to perform when selected |
| prop        | showActionControls | Boolean | Whether or not a clickable menu of 'actions' should be showing or not                                                 |
| method      | updateData         | method  | Method to update the data for that record                                                                             |
| prop        | onClick            | method  | Triggered when the card is clicked                                                                                    |
| prop        | onDoubleClick      | method  | Triggered when the card is double-clicked                                                                             |
| prop        | onActionSelect     | method  | Triggered when an action item is selected                                                                             |
| prop        | onDataChange       | method  | Triggered when the data needs to change in some way (e.g. the title of the card is renamed)                           |

##### Tests

| It                                                                                                                | Type        |
| ----------------------------------------------------------------------------------------------------------------- | ----------- |
| Should render the component in the dom                                                                            | Integration |
| Should show an icon if one is provided in the props                                                               | Integration |
| Should show a component if one is provided in the component prop                                                  | Integration |
| Should show a list of tags if any are provided in the tags prop                                                   | Integration |
| Should show a caption if one is provided in the label prop                                                        | Integration |
| Should turn the label caption into an editable text field when clicked if the labelIsEditable prop is set to true | Integration |
| Should trigger the onDataChange event when the textfield is blurred                                               | Integration |
| Should trigger the onDataChange event when the [enter] key is pressed while in the text field                     | Integration |
| Should revert to original text if the [esc] key is pressed while in the text field                                | Integration |
| Should revert back to text mode after the onDataChange event has been called                                      | Integration |
| Should show a dropdown menu (in the form of an icon) if the showActionControls prop is set to true                | Integration |
| Should show a list of items in the action controls dropdown menu as specified by the actions prop                 | Integration |
| Should trigger the onActionSelect event when an action item is selected                                           | Integration |
| Should trigger the onClick event when the card is clicked                                                         | Integration |
| Should trigger the onDoubleClick event when the card is double-clicked                                            | Integration |

#### FilterGroup

##### Schema

| Schema Type | Name                  | Type    | Description                                                                                         |
| ----------- | --------------------- | ------- | --------------------------------------------------------------------------------------------------- |
| prop        | showDateRange         | Boolean | Whether or not the date range controls are visible                                                  |
| prop        | data                  | object  | object representing the filter query                                                                |
| prop        | columns               | object  | The list of fields (and their settings) you plan to use for filtering                               |
| prop        | savedFilters          | array   | All the previous filters that were saved                                                            |
| prop        | savedFiltersIsEnabled | Boolean | Whether or not the Save Filter feature is enabled and the existing list of Saved Filters is showing |
| prop        | onChange              | method  | Triggers whenever a filter is selected                                                              |
| prop        | onDelete              | method  | Triggers when a filter group is deleted                                                             |
| prop        | onCreate              | method  | Trigger when a new filter is created or added to the group                                          |
| prop        | onClear               | method  | Trigger when all the filters are cleared                                                            |
| prop        | onSave                | method  | Trigger when the chosen group of filters are saved                                                  |

##### Tests

| It                                                                                                                                         | Type        |
| ------------------------------------------------------------------------------------------------------------------------------------------ | ----------- |
| Should render in the dom                                                                                                                   | Integration |
| Should show a date range picker when dateRangeIsVisible in props is true                                                                   | Integration |
| Should trigger onChange event when date picker changes                                                                                     | Integration |
| Should show a list of filters in the dom that corresponds with the list provided in the data props                                         | Integration |
| Should show a list of columns that are available for filtering that corresponds with the columns provided in the columns prop              | Integration |
| Should show a list of savedFilters in the dom that corresponds with the savedFilters prop if the savedFiltersIsEnabled prop is set to true | Integration |
| Should trigger the onChange event whenever a filter is selected                                                                            | Integration |
| Should trigger the onCreate event when a new filter is created or added to the group                                                       | Integration |
| Should trigger the onDelete event when a filter group is deleted                                                                           | Integration |
| Should trigger the onClear event when all the filters are cleared                                                                          | Integration |
| Should trigger the onSave event when the chosen group of filters are saved                                                                 | Integration |

#### AlphabetFilter

##### Schema

| Schema Type | Name           | Type   | Description                                                      |
| ----------- | -------------- | ------ | ---------------------------------------------------------------- |
| prop        | containerStyle | any    | The style to use for the component that wraps the character list |
| prop        | characterStyle | any    | The style to use for each character rendered                     |
| prop        | onClick        | method | Triggers when any of the characters are clicked                  |

##### Tests

| It                                                                                           | Type        |
| -------------------------------------------------------------------------------------------- | ----------- |
| Should render in the dom                                                                     | Integration |
| Should overwrite the default container style with the containerStyle prop if one is provided | Integration |
| Should overwrite the character style with the characterStyle prop if one is provided         | Integration |
| Should triggers an onClick event when a alphabet character is clicked                        | Integration |

#### BulkActionsMenu

##### Schema

| Schema Type | Name     | Type   | Description                                     |
| ----------- | -------- | ------ | ----------------------------------------------- |
| prop        | type     | enum   | Whether to show a button or an icon as the menu |
| prop        | icon     | string | The icon to show                                |
| prop        | label    | string | The text to display in the button               |
| prop        | data     | object | An array of items to show as the menu           |
| prop        | onSelect | method | Triggers when an item is selected               |

##### Tests

| It                                                                                  | Type        |
| ----------------------------------------------------------------------------------- | ----------- |
| Should render component in dom                                                      | Integration |
| Should show an icon when type prop calls for it                                     | Integration |
| Should show a button when type prop calls for it.                                   | Integration |
| Button label should be what the label prop calls for                                | Integration |
| Should show a dropdown menu of items from the data prop when button/icon is clicked | Integration |
| Should trigger the onSelect event when a bulk action menu item is selected          | Integration |

#### BulkSelectedActions

##### Schema

| Schema Type | Name              | Type    | Description                                                                                                                                               |
| ----------- | ----------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| prop        | children          | element | custom components to display inside                                                                                                                       |
| prop        | data              | array   | The array of selected items                                                                                                                               |
| prop        | location          | enum    | The location to show the component                                                                                                                        |
| prop        | actionButtons     | array   | An array of data object items to show that represents a button to perform the most common action for the selected records (e.g. 'Delete These Campaigns') |
| prop        | showActionButtons | Boolean | Whether or not a single action button is showing (e.g. 'Archive')                                                                                         |
| prop        | style             | any     | For styling the object                                                                                                                                    |

##### Tests

| It                                                                                                                                          | Type        |
| ------------------------------------------------------------------------------------------------------------------------------------------- | ----------- |
| Should render component in dom                                                                                                              | Integration |
| Should display child components in dom                                                                                                      | Integration |
| Should pass child component its props                                                                                                       | Integration |
| Should show a dropdown menu of items from data prop when bulk action button is clicked                                                      | Integration |
| Should show the component in the location specified by the location prop (e.g. TOP/BOTTOM/LEFT/RIGHT)                                       | Integration |
| Should show a list of buttons as specified by the actionsButtons prop intended to perform the most common actions for the selected records. | Integration |
| Should not show any action buttons if the showActionButtons prop is set to false                                                            | Integration |

#### EmptyStateComponent

##### Schema

| Schema Type | Name     | Type    | Description                                                          |
| ----------- | -------- | ------- | -------------------------------------------------------------------- |
| prop        | message  | element | The message to display                                               |
| prop        | image    | element | The empty state image to display next to the message                 |
| prop        | children | element | The content to display below the empty state (e.g. an action button) |

##### Tests

| It                                          | Type        |
| ------------------------------------------- | ----------- |
| Should render in the dom                    | Integration |
| Should show the provided message in the dom | Integration |
| Should show the provided image in the dom   | Integration |
| Should render any children provided         | Integration |

### Database Schema

### Store/Reducers

### APIs/Hook Schema
