Fuuz Master Data Management Table Screen Standard

Fuuz Master Data Management Table Screen Standard

Specification for Creating a Master Data Management (MDM) Table Screen in Fuuz

Example - for Columns with no image data to keep consistent height

Design Philosophy


Master Data Management Principles


Master Data screens in the Fuuz Application Designer serve as the primary interface for managing critical business entities (customers, products, locations, equipment, users, etc.). The design standard is built on four core principles:

1. Consistency First: All master data screens follow identical patterns for predictable user experience
2. Filter-Then-Act: Users filter to find data, then act upon selections
3. Preserve User Context: Layouts remain stable; users customize views via tool panels
4. Relationship Clarity: Table structures clearly articulate data relationships


Purpose of Master Data Screens


Master data screens are **NOT** for:
- High-frequency transactional data entry
- Real-time operational dashboards
- Complex multi-entity workflows

Master data screens **ARE** for:
- Creating, reading, updating, and deleting reference data
- Managing organizational entities that change infrequently
- Maintaining data quality and consistency
- Bulk operations on similar records


Target Users

- System administrators
- Data stewards
- Department managers
- Power users with data management responsibilities


---


Template Architecture


Container Hierarchy


The standard template uses a three-level container architecture with a resizable filter panel:

ROOT (Screen)
└── ContainerOuter (Horizontal flex container)
    ├── ResizableFilterPanel (0-300px, collapsible)
    │   └── ContainerFilterOuter
    │       ├── ContainerFilterHeader (Action buttons)
    │       └── ContainerFilterBody (Scrollable filters)
    │           └── Form1 (Filter form)
    └── ContainerBody (Flexible main area)
        ├── ContainerTableHeader (Action toolbar)
        └── Table1 (Master data table)



Container Specifications

ContainerOuter
Purpose: Primary horizontal layout container  
Properties:
- `width: 100%`, `height: 0px` (with flexGrow: true)
- `flexDirection: row`
- `justifyContent: flex-start`
- `alignItems: stretch`
- `flexGrow: true`, `flexShrink: false`

Why: Creates a horizontal split between filter panel and main content area, both filling viewport height.


ResizableFilterPanel

Purpose: Collapsible, resizable filter panel  
Properties:
- `handle: "right"`
- `defaultSize: 300` (pixels)
- `minSize: 0` (fully collapsed)
- `maxSize: 300` (maximum width)

User Control: Users can drag to resize or collapse completely to maximize table viewing area.

Why: Provides flexible filtering without permanently consuming screen space. Power users can expand for complex filters; casual users can collapse for maximum data visibility.


ContainerFilterOuter

Purpose: Filter panel content wrapper  
Properties:
- `width: 100%`, `height: 100%`
- `flexDirection: column`
- `justifyContent: flex-start`
- `flexGrow: true`, `flexShrink: true`

Children:
- ContainerFilterHeader (action buttons)
- ContainerFilterBody (scrollable filter inputs)


ContainerFilterHeader

Purpose: Filter panel action buttons  
Properties:
- `height: 60px` (fixed)
- `width: 100%`
- `flexDirection: row`
- `justifyContent: flex-start`
- `alignItems: center`
- `padding: 4`

Content: Action buttons for Search, Clear, Create, etc.


ContainerFilterBody

Purpose: Scrollable filter inputs area  
Properties:
- `height: 0px` (with flexGrow: true)
- `width: 100%`
- `flexGrow: true`
- `overflow-y: auto`
- `overflow-x: hidden`
- `padding: 6`

Content: Form with filter inputs arranged vertically


ContainerBody

Purpose: Main content area for table  
Properties:
- `width: 0px` (with flexGrow: true)
- `height: 100%`
- `flexDirection: column`
- `flexGrow: true`, `flexShrink: false`
- `borderLeft: "0.5px solid #5b30df"` (visual separator)

Children:
- ContainerTableHeader (toolbar with actions)
- Table1 (main data table)


ContainerTableHeader

Purpose: Table action toolbar  
Properties:
- `height: 60px` (fixed)
- `width: 100%`
- `flexDirection: row`
- `justifyContent: space-between`
- `alignItems: center`
- `padding: 4`
- `borderBottom: "0.5px solid rgba(0, 0, 0, 0.12)"`

Content: Table-level actions (bulk operations, menu actions, etc.)


---


Layout Principles


Horizontal Split Pattern


Master data screens use a horizontal split layout:

Left Panel (Filter):
- Resizable from 0-300px
- Collapses completely when not needed
- Contains all search/filter controls
- Scrolls independently if filters exceed viewport

Right Panel (Data):
- Fills remaining horizontal space
- Contains table and table actions
- Table fills vertical space completely
- Table scrolls independently


Responsive Behavior


Filter Panel:
- Default 300px on large screens (>1600px)
- Default 250px on medium screens (1200-1600px)
- Default collapsed on small screens (<1200px)
- User preference persists across sessions

Table Area:
- Always fills remaining space
- Columns auto-size based on available width
- Horizontal scroll enabled if columns exceed width
- Tool panel accessible via sidebar


Thought Process for Layout

When Building Master Data Screens:

1. Start with the Data Model
   - What entity are you managing?
   - What fields are essential for identification?
   - What relationships exist?

2. Define Filter Strategy
   - What are the most common search patterns?
   - Which fields need filtering?
   - How can you minimize filter count?

3. Plan Column Layout
   - Selection column needed? (Add first, 40px)
   - Actions needed? (Add second, 40px)
   - What's the primary identifier? (Add third, make it linkTarget)
   - What additional context is needed?
   - Where do audit fields go? (Always last)

4. Consider Relationships
   - Is this 1:many (consider masterDetail)?
   - Is this many:many (avoid masterDetail, use separate screen)?
   - Do actions need to navigate to related entities?



Filter Panel Standards


Filter Organization Hierarchy


Filters must be organized in a specific order for consistency and usability:

1. SelectInput Filters (Top Priority)
- Maximum 4 select inputs
- Most commonly used selections first
- Example: Department, Location, Status, Type

2. Switch/Checkbox Filters (Secondary)
- Maximum 3 switches/checkboxes
- If more needed, use side-by-side container layout
- Example: Active Only, Include Deleted, Show Archived

3. GraphQL Advanced Filters (Last Resort)
- For power users needing complex queries
- Placed at bottom of filter panel
- Allows ad-hoc filtering without cluttering UI


Filter Input Configuration


SelectInput Filters


Standard Configuration:

  1. {
      "type": "select",
      "height": "80px",
      "width": "100%",
      "variant": "outlined",
      "labelFontSize": 12,
      "dataFontSize": 14,
      "dialogMode": "never",
      "isClearable": true,
      "searchPredicate": "contains",
      "stateTracking": "full"
    }

Key Properties:
- height: "80px" (consistent vertical spacing)
- isClearable: true (allow filter reset)
- dialogMode: "never" (inline dropdown, no modal)
- stateTracking: "full" (maintain filter state)
Predicate Filtering:

Most filter inputs should NOT use predicates that hide data (e.g., active only), UNLESS:
- The data is truly inaccessible (deleted records)
- Business rules prohibit access (compliance)
- The data volume makes unfiltered results unusable

Why: Users may need to access deprecated or inactive data for reporting, auditing, or reactivation purposes.


Exception Example:
  1. {
      "additionalFilter": {
        "_and": [
          {
            "deleted": { "_eq": false }
          }
        ]
      }
    }



Switch/Checkbox Filters

Standard Configuration:
  1. {
      "type": "switch",
      "width": "100%",
      "label": "Active Only",
      "dataPath": "activeOnly"
    }



Side-by-Side Layout for Multiple Switches:

ContainerSwitches (flexDirection: row)
├── Container (width: 50%)
│   └── Switch 1
└── Container (width: 50%)
    └── Switch 2


Why: Switches take less vertical space than selects, but more than 3 can clutter. Side-by-side layout reduces vertical scroll.


GraphQL Advanced Filters

Standard Configuration:
  1. {
      "type": "graphqlBuilder",
      "width": "100%",
      "model": "YourDataModel",
      "dataPath": "advancedFilter"
    }

Placement: Always last in filter panel

Purpose: Allows power users to construct complex queries without adding dozens of individual filter inputs

When to Use: 
- Screen has been in use and users request specific complex filters
- Data model has many optional filter points
- User base includes technical users comfortable with GraphQL


Filter Actions


Search Button

Configuration:
  1. {
      "icon": { "icon": "magnifying-glass" },
      "text": "Search",
      "action": [
        {
          "type": "transformation",
          "transformation": "$components.Table1.fn.search()"
        }
      ]
    }
Behavior: Applies all filter values and refreshes table

Why Icon + Text: "Search" is universal and explicit; icon reinforces action

Clear/Reset Button


Configuration:
  1. {
      "icon": { "icon": "eraser" },
      "text": "Clear",
      "action": [
        {
          "type": "transformation",
          "transformation": "$components.Form1.fn.reset()"
        }
      ]
    }

Behavior: Resets all filter inputs to default/empty

Why: Users need quick escape from complex filter combinations


Auto-Search Configuration

Critical Setting: Auto-search must be **DISABLED** on master data tables

Table Query Property:
  1. {
      "query": {
        "autoLoad": false
      }
    }

Why: 
- Master data tables can contain thousands or millions of records
- Unfiltered loads impact performance
- Users should explicitly choose their filter criteria
- Prevents accidental full-table queries


Table Configuration


Essential Table Properties


Core Settings
  1. {
      "width": "100%",
      "height": "0px",
      "flexGrow": true,
      "selectable": "single",
      "showToolPanels": true,
      "showStatusBar": true,
      "enableGrouping": true,
      "enableCharts": false,
      "showColumnMenu": false,
      "enableRowDragging": false,
      "disableColumnDragging": true,
      "disableDragLeaveHidesColumns": true,
      "masterDetail": false,
      "hideTableHeader": false,
      "rowMultiSelectWithClick": false
    }

Property Explanations

selectable: 
- "none" - No row selection
- "single" - Select one row at a time (most common)
- "multiple" - Select multiple rows (for bulk operations)

showToolPanels: true
- Users access column visibility, filters, and grouping via sidebar
- Provides power-user capabilities without cluttering UI

showStatusBar: true
- Displays row count, selected rows, aggregations
- Essential for data management tasks

enableGrouping: true
- Allows users to drag columns to group by
- Useful for hierarchical data analysis

enableCharts: false
- Charts are for dashboards, not master data management
- Keeps focus on data editing/viewing

showColumnMenu: false (globally disabled)
- Individual columns can enable as needed
- Prevents UI clutter from excessive menu icons

enableRowDragging: false
- Master data order should not be user-draggable
- Order comes from sort configuration or data model

disableColumnDragging: true
- Maintains consistent column layout across all users
- Users can still reorder via tool panel

disableDragLeaveHidesColumns: true
- Prevents accidental column hiding
- Users explicitly hide via tool panel

masterDetail: false (by default)
- Enable only for clear 1:many relationships
- See [Master-Detail Pattern](#master-detail-pattern) section


Query Configuration


  1. {
      "query": {
        "api": "Application",
        "model": "YourDataModel",
        "dataPath": "edges",
        "autoLoad": false,
        "fields": ["id"],
        "dataSubscription": {
          "enabled": false
        }
      }
    }


autoLoad: false - Users must explicitly search

dataSubscription.enabled: false - Master data doesn't need real-time updates


Default Sort Configuration


Always configure a default sort:

  1. {
      "defaultSort": [
        {
          "field": "TableColumn1",
          "direction": "asc"
        }
      ]
    }
Best Practice:
- Sort by the first data column (primary identifier)
- Use ascending order for text/names
- Users can override via column headers

Why: Predictable initial order reduces confusion and support requests



Column Standards


Column Layout Order

Master data tables follow a strict left-to-right column order:


1. Selection Column (if selectable enabled)
2. Actions Menu Column (if row actions needed)
3. Primary Identifier Column (with linkTarget if applicable)
4. Additional Data Columns (context and details)
5. Audit Columns (CreatedAt, CreatedBy, UpdatedAt, UpdatedBy)

Column 1: Selection Column


When to Include: Table has `selectable: "single"` or `selectable: "multiple"`

Configuration:
  1. {
      "label": " ",
      "format": "text",
      "sortable": false,
      "dataPath": "na",
      "width": "40px",
      "showColumnSuppressMenu": false,
      "editable": false,
      "style": {
        "alignItems": "center"
      }
    }

Key Properties:
- label: Empty space (checkboxes appear automatically)
- dataPath: "na" or empty (no data binding)
- width: "40px" (just enough for checkbox)
- sortable: false (no point sorting checkboxes)
- showColumnSuppressMenu: false (no menu needed)

Why: Dedicated column prevents checkbox overlap with data and provides consistent click target


Column 2: Actions Menu Column


When to Include: Rows require multiple actions (Edit, Delete, Inactivate, etc.)

Configuration:

  1. {
      "label": " ",
      "format": "menu",
      "sortable": false,
      "dataPath": "actions",
      "width": "40px",
      "menuIcon": "ellipsis-v",
      "iconSize": "small",
      "showColumnSuppressMenu": false,
      "actions": [
        {
          "text": "Edit",
          "icon": {
            "icon": "pencil",
            "color": "warning",
            "size": "small"
          }
        },
        {
          "text": "Delete",
          "icon": {
            "icon": "trash",
            "color": "error",
            "size": "small"
          }
        }
      ]
    }

Action Types:

1. Information/View: Read-only details
   - Icon: "circle-info", Color: "info"
   - Opens modal with full record details

2. Edit: Modify record
   - Icon: "pencil", Color: "warning"
   - Opens form or navigates to edit screen

3. Delete: Remove record
   - Icon: "trash", Color: "error"
   - Requires confirmation dialog

4. Inactivate/Deactivate: Soft delete
   - Icon: "ban", Color: "warning"
   - Changes status without deleting

5. Custom Actions: Business-specific
   - Choose appropriate icon and color
   - Follow consistent patterns

Why: Consolidates row-level actions in one menu, saving horizontal space


Column 3: Primary Identifier Column


Purpose: The main field users search for and identify records by

Configuration with LinkTarget:
  1. {
      "label": "Name",
      "format": "text",
      "sortable": true,
      "dataPath": "name",
      "width": "200px",
      "showColumnSuppressMenu": true,
      "linkTarget": {
        "screenId": "screen_id_here",
        "query": {
          "__transform": "{ \"id\": rowData.id }"
        }
      }
    }

Configuration without LinkTarget:

  1. {
      "label": "Name",
      "format": "text",
      "sortable": true,
      "dataPath": "name",
      "width": "200px",
      "showColumnSuppressMenu": true
    }


When to Use LinkTarget:
- A detail form/screen exists for this entity
- Users frequently need to view/edit full record details
- Clicking the identifier is the primary navigation pattern

When NOT to Use LinkTarget:
- All editing happens inline or via menu actions
- No detail screen exists
- Navigation would be confusing

Why: Primary identifier should always be first data column for quick scanning and consistent UX


Additional Data Columns


Standard Column Configuration:

  1. {
      "label": "Field Label",
      "format": "text",
      "sortable": true,
      "dataPath": "fieldName",
      "width": "150px",
      "showColumnSuppressMenu": true
    }

Column Format Types:

| Format | Use Case | Example |
|--------|----------|---------|
| text | Plain text data | Names, descriptions, IDs |
| number | Numeric values | Quantities, counts |
| currency | Money values | Prices, costs |
| date | Date values | Birth dates, due dates |
| datetime | Date with time | Timestamps, appointments |
| boolean | True/false | Active status, flags |
| select | Dropdown options | Status, type, category |
| lookup | Related entity | Customer, location |
| menu | Row actions | Edit, delete, etc. |

Width Guidelines:
- Short IDs/codes: 80-100px
- Names: 150-200px
- Descriptions: 200-300px
- Dates: 100-120px
- Numbers: 80-120px
- Let remaining columns auto-size

Sortable Property:
- Enable for most data columns
- Disable for: selection column, actions column, calculated fields without sort support

showColumnSuppressMenu:
- Enable for data columns users might want to filter/sort/customize
- Disable for: selection column, actions column


Audit Columns


Always place audit fields at the far right (end of all data columns)

Standard Audit Column Set:

1. Created At

  1. {
      "label": "Created",
      "format": "datetime",
      "sortable": true,
      "dataPath": "createdAt",
      "width": "140px",
      "timezone": "tenant",
      "dateFormat": "MM/DD/YYYY HH:mm"
    }


2. Created By

  1. {
      "label": "Created By",
      "format": "lookup",
      "sortable": true,
      "dataPath": "createdBy.fullName",
      "width": "150px",
      "query": {
        "fields": ["createdBy.fullName"]
      }
    }


3. Updated At
  1. {
      "label": "Updated",
      "format": "datetime",
      "sortable": true,
      "dataPath": "updatedAt",
      "width": "140px",
      "timezone": "tenant",
      "dateFormat": "MM/DD/YYYY HH:mm"
    }


4. Updated By

  1. {
      "label": "Updated By",
      "format": "lookup",
      "sortable": true,
      "dataPath": "updatedBy.fullName",
      "width": "150px",
      "query": {
        "fields": ["updatedBy.fullName"]
      }
    }


Critical Requirements:

Timezone: Always use "Fuuz Setting"
- Displays dates in user's configured timezone
- Prevents confusion from UTC timestamps

Date Format: Use consistent format
- Recommended: "MM/DD/YYYY HH:mm" for US audiences
- Adjust for regional requirements
- Be consistent across all tables

User Fields: Use "fullName"
- More user-friendly than "email" or "username"
- Requires query.fields: ["createdBy.fullName"] or Concat firstName & " " & lastName

Why Last: Audit information is important but not primary. Users scan left-to-right for business data, check audit info when needed.


Action Patterns


Icon vs Text Guidelines


Use ICONS ONLY when the function is universally recognized:

✅ Use Icons (with tooltip):
- CREATE (layer-plus, plus, file-plus)
- DELETE (trash, trash-can)
- SEARCH (magnifying-glass, search)
- REFRESH (arrows-rotate, sync)
- FILTER (filter, filter-list)
- EXPORT (download, file-export)
- IMPORT (upload, file-import)

❌ Use Text Labels for:
- Business-specific actions ("Approve", "Reject")
- Complex operations ("Generate Report", "Sync with ERP")
- Ambiguous operations ("Process", "Submit")
- Custom workflows

Best Practice: When in doubt, use text. Clarity beats brevity.


Table Header Actions


Actions that operate on the table as a whole go in ContainerTableHeader:

Standard Pattern:

[Create] [Bulk Edit] [Export] [Menu Actions ▼]


Create Action:

  1. {
      "icon": { "icon": "layer-plus", "color": "success" },
      "useIconButton": true,
      "action": [
        {
          "type": "form",
          "fields": [...]
        },
        {
          "type": "mutation",
          "api": "Application"
        },
        {
          "type": "transformation",
          "transformation": "$components.Table1.fn.search()"
        }
      ]
    }


Why Icon: "Create" is universal, icon is recognized, saves space

Bulk Edit Action:

  1. {
      "text": "Bulk Edit",
      "disabled": {
        "__transform": "$count($components.Table1.state.selectedRows) = 0"
      },
      "action": [
        {
          "type": "form",
          "fields": [...]
        },
        {
          "type": "mutation",
          "api": "Application"
        }
      ]
    }


Why Text: "Bulk Edit" is specific business logic, text is clearer


Use for multiple custom actions to reduce toolbar clutter:
  1. {
      "type": "menuButton",
      "text": "Actions",
      "icon": { "icon": "ellipsis-v" },
      "items": [
        {
          "text": "Generate Report",
          "icon": { "icon": "file-chart-column" }
        },
        {
          "text": "Export to Excel",
          "icon": { "icon": "file-excel" }
        },
        {
          "text": "Sync with ERP",
          "icon": { "icon": "arrows-rotate" }
        }
      ]
    }


When to Use:
- More than 3 custom actions
- Actions used less frequently
- Need to reduce visual clutter

When NOT to Use:
- Primary actions (Create, Search)
- Actions used constantly
- Only 1-2 actions available

Master-Detail Pattern


When to Use Master-Detail

Master-detail view shows child records within the parent row, expandable inline.

Use Master-Detail For:
- Clear 1:many relationships
- Child data is simple and few columns
- Users frequently need to see children in context
- Children don't require complex editing

Examples:
- Customer → Orders (simple order list)
- Equipment → Maintenance Records
- Location → Sub-Locations
- Product → SKU Variants (if simple)

Avoid Master-Detail For:
- Many:many relationships (use separate screen)
- Many:1 relationships (doesn't make sense)
- Complex child data with many fields
- Children require complex forms
- Performance concerns (thousands of children)

Master-Detail Configuration


Enable in Table:

  1. {
      "masterDetail": true
    }


Configure Detail View:
  1. {
      "masterDetail": true,
      "detailCellRendererParams": {
        "detailGridOptions": {
          "columnDefs": [
            {
              "field": "childField1",
              "headerName": "Field 1"
            },
            {
              "field": "childField2",
              "headerName": "Field 2"
            }
          ]
        },
        "getDetailRowData": {
          "__transform": "function($params) { $params.successCallback(rowData.children) }"
        }
      }
    }

Best Practices:
- Keep child columns to 3-5 maximum
- Don't nest master-detail (no grandchildren)
- Consider pagination for large child sets
- Provide way to navigate to full child management screen

Developer Checklist


Before Deployment


Use this checklist for every master data table screen:

Layout Structure
- [ ] ContainerOuter set with `flexDirection: row`, `height: 0px`, `flexGrow: true`
- [ ] ResizableFilterPanel configured with `maxSize: 300`, `minSize: 0`
- [ ] ContainerFilterOuter properly nested with header and body
- [ ] ContainerBody set with `width: 0px`, `flexGrow: true`
- [ ] ContainerTableHeader configured for action buttons
- [ ] All containers properly nested

Filter Panel
- [ ] Filters ordered: Select inputs first (max 4), then switches (max 3), then GraphQL advanced
- [ ] Side-by-side containers used if more than 3 switches needed
- [ ] Select inputs have `isClearable: true`, `dialogMode: "never"`
- [ ] Predicate filters reviewed (avoid hiding accessible data)
- [ ] Search button configured to call `$components.Table1.fn.search()`
- [ ] Clear button configured to call `$components.Form1.fn.reset()`
- [ ] All filter inputs bound to Form1 with proper dataPaths

Table Configuration
- [ ] Table `autoLoad: false` (users must explicitly search)
- [ ] Table `showToolPanels: true` (user customization)
- [ ] Table `showStatusBar: true` (row count, aggregations)
- [ ] Table `enableCharts: false` (not for master data)
- [ ] Table `showColumnMenu: false` (globally disabled)
- [ ] Table `enableRowDragging: false` (no user reordering)
- [ ] Table `disableColumnDragging: true` (consistent layout)
- [ ] Table `disableDragLeaveHidesColumns: true` (prevent accidents)
- [ ] Table `masterDetail` set appropriately (only for 1:many)
- [ ] Default sort configured on first data column

Column Configuration
- [ ] Selection column added if `selectable` enabled (40px, first position)
- [ ] Actions menu column added if needed (40px, second position)
- [ ] Primary identifier column configured (third position, linkTarget if applicable)
- [ ] Additional data columns use appropriate formats
- [ ] Audit columns placed at far right (CreatedAt, CreatedBy, UpdatedAt, UpdatedBy)
- [ ] Date columns have `timezone: "tenant"` and proper format
- [ ] User fields use `fullName` with proper query.fields
- [ ] Column widths set appropriately (selection/actions: 40px, names: 150-200px)
- [ ] Selection and actions columns have `sortable: false`, `showColumnSuppressMenu: false`
- [ ] Data columns have `sortable: true`, `showColumnSuppressMenu: true` as appropriate
- [ ] LinkTarget removed from columns where not used (avoid confusion)

Actions
- [ ] Icons used only for universal actions (CREATE, DELETE, SEARCH)
- [ ] Text labels used for business-specific actions
- [ ] Create action configured with form → mutation → table refresh
- [ ] Menu button used for 3+ custom actions
- [ ] Row action menu configured with appropriate actions (Edit, Delete, etc.)
- [ ] Bulk actions disabled when no rows selected
- [ ] All actions provide user feedback (success messages, confirmations)

Testing
- [ ] Tested with no filters applied (should show "no data" or prompt to search)
- [ ] Tested Search button with various filter combinations
- [ ] Tested Clear button resets all filters
- [ ] Verified filter panel collapses to 0px
- [ ] Verified filter panel expands to 300px max
- [ ] Tested table sorting on each sortable column
- [ ] Verified selection column checkboxes work properly
- [ ] Tested actions menu on multiple rows
- [ ] Verified linkTarget navigation (if used)
- [ ] Tested master-detail expansion (if used)
- [ ] Verified audit fields display correct timezone and format
- [ ] Tested tool panel for column visibility and customization
- [ ] Verified status bar shows correct row counts
- [ ] Tested Create action form and mutation
- [ ] Tested Edit action (if configured)
- [ ] Tested Delete action with confirmation

Data Quality
- [ ] Verified query.fields includes all displayed columns
- [ ] Verified lookup fields include proper relationship paths
- [ ] Tested with large data sets (performance)
- [ ] Verified no predicate filters hide needed data
- [ ] Confirmed data model supports configured columns



Best Practices


Filter Strategy

Start Minimal, Expand Based on Usage

Initial Deployment:
- Add 2-3 most obvious filters (status, type, location)
- Include GraphQL advanced filters for power users
- Monitor user feedback and usage patterns

After 30-60 Days:
- Review filter usage analytics
- Add filters users repeatedly request
- Optimize filter order based on usage frequency
- Remove filters no one uses

Why: Overloading with filters reduces usability. Let real usage patterns guide optimization.

Progressive Disclosure

For complex filtering needs:

1. Basic Filters: Always visible (status, type)
2. Advanced Filters: Collapsible section or GraphQL builder
3. Saved Filter Sets: Allow users to save combinations


Table Performance


Optimize for Large Datasets

When Tables Contain >10,000 Records:

1. Require Initial Filter:
   - Don't allow unfiltered searches
   - Prompt user to select department, location, date range, etc.

2. Implement Pagination:
   - Server-side pagination for large result sets
   - Show page size options (25, 50, 100)

3. Limit Initial Columns:
   - Load essential columns only
   - Use lazy loading for detail columns
   - Let users add columns via tool panel

4. Use Virtualization:
   - Tables automatically virtualize rows
   - Ensure columns aren't overly complex (avoid heavy rendering)

Column Width Strategy

Auto-Sizing:
- Let most columns auto-size
- Fix width only for: selection (40px), actions (40px), icons, short codes

Resizable:
- All data columns should be resizable
- Users can adjust via drag or tool panel

Best Practice:

  1. {
      "width": "150px",  // Initial suggestion
      "resizable": true,  // User can adjust
      "flex": 1          // Or use flex for proportional sizing
    }


Relationship Management


When to Use Separate Screens

Create a separate detail/form screen when:
- Entity has >10 fields
- Complex relationships (many:many)
- Requires multi-step process
- Needs different user permissions
- Has its own child entities

Navigation Pattern:

Master Table → LinkTarget → Detail Form
                           → Related Entity Tabs
                           → Back to List Button


When to Edit Inline

Use inline editing (table cell editing) when:
- Quick status changes
- Single field updates
- Bulk editing scenarios
- Simple lookup changes

Configuration:
  1. {
      "editable": true,
      "cellEditor": "select",
      "cellEditorParams": {
        "values": ["Active", "Inactive", "Pending"]
      }
    }


Audit Trail Requirements


Essential for Master Data

All master data tables should include audit fields because:

1. Compliance: Who changed what and when
2. Troubleshooting: Track down data quality issues
3. Security: Detect unauthorized changes
4. Support: Answer "when did this change?" questions

Display Best Practices

- Always include all four: CreatedAt, CreatedBy, UpdatedAt, UpdatedBy
- Use fullName for "By" fields (more readable than email)
- Use tenant timezone (respects user location)
- Consistent date format across all tables
- Place at far right (important but not primary)


Action Organization


Table Header vs Row Actions

Table Header Actions (ContainerTableHeader):
- Create new record
- Bulk operations (edit, delete, export)
- Table-wide operations (refresh, settings)
- Report generation

Row Actions (Actions menu column):
- Edit single record
- Delete single record
- View details
- Record-specific operations (activate, approve)

Why Separate: Clear separation between table-level and record-level operations reduces user errors


Common Patterns


Pattern 1: Simple Master Data (CRUD)


Use Case: Basic reference data management (departments, locations, categories)

Structure:

Filter Panel:
  ├── Search by Name (SelectInput)
  ├── Active Only (Switch)
  └── Search Button

Table:
  ├── Selection Column (40px)
  ├── Actions Menu Column (40px)
  │   ├── Edit
  │   └── Delete
  ├── Name (primary, linkTarget)
  ├── Description
  ├── Status
  ├── CreatedAt
  └── UpdatedAt


Key Points:
- Minimal filters (name, status)
- LinkTarget to detail form
- Standard actions (edit, delete)
- Audit fields for tracking


Pattern 2: Hierarchical Master Data


Use Case: Data with parent-child relationships (locations with sub-locations, org structure)

Structure:

Filter Panel:
  ├── Parent Entity (SelectInput)
  ├── Level (SelectInput)
  ├── Active Only (Switch)
  └── Search Button

Table:
  ├── Master-Detail Enabled
  ├── Selection Column (40px)
  ├── Actions Menu Column (40px)
  ├── Name (primary)
  ├── Parent
  ├── Level
  ├── ChildCount
  └── Audit Columns

Master-Detail View:
  └── Child Records (inline table)


Key Points:
- Use master-detail for 1:many
- Show parent context
- Display child count
- Allow navigation to child management


Pattern 3: Complex Master Data with Relationships

Use Case: Entities with multiple relationships (products with suppliers, categories, SKUs)

Structure:

Filter Panel:
  ├── Category (SelectInput)
  ├── Supplier (SelectInput)
  ├── Status (SelectInput)
  ├── Active Only (Switch)
  ├── In Stock Only (Switch)
  └── Search Button

Table:
  ├── Selection Column (40px)
  ├── Actions Menu Column (40px)
  │   ├── Edit
  │   ├── View SKUs
  │   ├── Manage Suppliers
  │   └── Delete
  ├── Product Code (primary, linkTarget)
  ├── Description
  ├── Category
  ├── Primary Supplier
  ├── Status
  ├── Quantity on Hand
  └── Audit Columns


Key Points:
- Multiple relationship filters
- Actions navigate to related entity screens
- Don't use master-detail (too complex)
- LinkTarget to full detail form with tabs


Pattern 4: User/Contact Management

Use Case: Managing users, contacts, employees

Structure:

Filter Panel:
  ├── Department (SelectInput)
  ├── Role (SelectInput)
  ├── Status (SelectInput)
  ├── Active Only (Switch)
  └── Search Button

Table:
  ├── Selection Column (40px)
  ├── Actions Menu Column (40px)
  │   ├── Edit Profile
  │   ├── Reset Password
  │   ├── Manage Permissions
  │   ├── Inactivate
  │   └── Delete
  ├── Full Name (primary, linkTarget)
  ├── Email
  ├── Department
  ├── Role
  ├── Last Login
  ├── Status
  └── Audit Columns


Key Points:
- Security-sensitive actions (password reset, permissions)
- Status column shows active/inactive
- Last login for activity tracking
- Inactivate instead of delete (preserve data)


Pattern 5: Equipment/Asset Management


Use Case: Tracking physical assets, equipment, tools

Structure:

Filter Panel:
  ├── Location (SelectInput)
  ├── Type (SelectInput)
  ├── Status (SelectInput)
  ├── Calibration Due (DateRange)
  └── Search Button

Table:
  ├── Master-Detail Enabled (for maintenance history)
  ├── Selection Column (40px)
  ├── Actions Menu Column (40px)
  │   ├── Edit
  │   ├── View History
  │   ├── Schedule Maintenance
  │   └── Retire
  ├── Asset Number (primary, linkTarget)
  ├── Description
  ├── Type
  ├── Location
  ├── Status
  ├── Last Maintenance
  ├── Next Calibration
  └── Audit Columns

Master-Detail View:
  └── Maintenance History (inline table)


Key Points:
- Date-based filters (calibration, maintenance)
- Master-detail for maintenance history
- Status tracking (active, maintenance, retired)
- Action for scheduling



Troubleshooting


Common Layout Issues


Issue: Filter panel doesn't collapse fully

Symptoms:
- Panel stays at minimum width instead of 0px
- Cannot maximize table viewing area

Causes:
- ResizableFilterPanel `minSize` not set to 0
- Child containers have fixed minimum width

Solutions:
1. Set ResizableFilterPanel `minSize: 0`
2. Ensure ContainerFilterOuter has no minimum width constraints
3. Set filter inputs `width: 100%` not fixed pixels

Issue: Table doesn't fill vertical space

Symptoms:
- White space below table
- Table doesn't scroll
- Vertical space wasted

Causes:
- Table `height` not set to "0px" with `flexGrow: true`
- ContainerOuter not set to fill viewport
- ContainerBody missing flexGrow

Solutions:
1. Set Table `height: "0px"`, `flexGrow: true`
2. Set ContainerOuter `height: "0px"`, `flexGrow: true` 
3. Set ContainerBody `width: "0px"`, `flexGrow: true`
4. Verify ROOT screen has `height: "100%"`

Issue: Horizontal scrolling in table when not needed

Symptoms:
- Table shows horizontal scrollbar with plenty of space
- Columns too wide for viewport

Cause*:
- Too many fixed-width columns
- Column widths exceed available space
- Browser window too narrow

Solutions:
1. Reduce number of visible columns (use tool panel for others)
2. Use flexible widths instead of fixed pixels
3. Review column width totals vs viewport
4. Let non-critical columns auto-size


Common Functional Issues


Issue: Search doesn't work

Symptoms:
- Clicking Search shows no data
- Filters not applied to query

Causes:
- Search action not calling `$components.Table1.fn.search()` (Or replace Table1 with actual table name)
- Filter form not bound to table query
- Wrong form element name referenced

Solutions:
1. Verify Search button action: `$components.Table1.fn.search()`
2. Check table element name matches (Table1)
3. Verify filter dataPath matches query parameter structure
4. Test with browser console for errors

Issue: Clear button doesn't reset filters

Symptoms:
- Filters remain populated after clicking Clear
- Must manually delete each filter value

Causes:
- Clear action not calling `$components.Form1.fn.reset()`
- Wrong form element name referenced
- Custom default values not configured

Solutions:
1. Verify Clear button action: `$components.Form1.fn.reset()`
2. Check form element name matches (Form1)
3. Set filter default values if needed
4. Use transformation to set custom reset state

Issue: Selection checkboxes don't appear

Symptoms:
- No checkboxes in first column
- Cannot select rows

Causes:
- Table `selectable` not set to "single" or "multiple"
- Selection column missing
- Selection column has dataPath set (should be empty/na)

Solutions:
1. Set Table `selectable: "single"` or `"multiple"`
2. Add selection column as first column
3. Set selection column `dataPath: "na"` or leave empty
4. Set selection column `width: "40px"`

Issue: Master-detail rows won't expand

Symptoms:
- Expand icon missing from rows
- Clicking row does nothing

Causes:
- Table `masterDetail: false`
- Missing `detailCellRendererParams` configuration
- Wrong data path for child records

Solutions:
1. Set Table `masterDetail: true`
2. Configure `detailCellRendererParams` with child grid options
3. Verify `getDetailRowData` function returns child array
4. Test data structure includes child records

Issue: Date columns show UTC time instead of local

Symptoms:
- Dates appear in wrong timezone
- Hours off by timezone offset

Causes:
- Column `timezone` not set to "tenant"
- Date stored incorrectly in database
- Format doesn't include timezone

Solutions:
1. Set date column `timezone: "tenant"`
2. Verify date format includes time if needed
3. Check database date storage (should be UTC)
4. Use proper date types in GraphQL schema

Issue: Created/Updated By shows email instead of name

Symptoms:
- Audit columns show "user@example.com" instead of "John Smith"

Causes:
- Column `dataPath` is "createdBy.email" instead of "createdBy.fullName"
- Query doesn't include fullName field

Solutions:
1. Change column `dataPath: "createdBy.fullName"`
2. Add to query.fields: `["createdBy.fullName"]`
3. Verify User model has fullName field
4. Same for updatedBy


Common Performance Issues


Issue: Table loads slowly with many records

Symptoms:
- Long wait after clicking Search
- Browser becomes unresponsive
- Timeout errors

Causes:
- Too many records returned (no pagination)
- Complex query with many joins
- Too many columns loaded

Solutions:
1. Implement server-side pagination
2. Require initial filter (don't allow unfiltered search)
3. Reduce number of columns in initial query
4. Add indexes to filtered fields in database
5. Use dataPath to limit returned fields

Issue: Filter panel is slow to open/close

Symptoms:
- Lag when dragging resize handle
- Panel stutters when collapsing

Causes:
- Too many filter inputs (>10)
- Complex SelectInputs with large option sets
- Heavy rendering in filter body

Solutions:
1. Reduce number of filters (use GraphQL advanced instead)
2. Limit SelectInput options (use optionLimit)
3. Remove unnecessary filter complexity
4. Consider tabs for filter organization
    • Related Articles

    • Fuuz Setup Data Management Table Screen Standard

      Specification for Creating a Setup Data Management (SDM) Table Screen in Fuuz Introduction This specification provides guidance for designing and implementing a "Table Screen" in Fuuz for managing setup data. Setup Data Management (SDM) focuses on ...
    • Table

      In the context of Fuuz screen design or a web page within the Fuuz platform, a "table" refers to a structured and organized grid-like layout component used to present and display data in a tabular format. Tables are a fundamental part of user ...
    • Table Feature: Master/Detail View

      Master/Detail View is a feature available for the table screen element. This functionality allows the user to drag in screen elements inside of a table to design the table’s detail view. Once the screen is rendered, each row in that table will have ...
    • Screen Designer (UID)

      Executive Summary The Fuuz Screen Designer is a versatile and intuitive drag-and-drop tool that empowers users to design custom screens according to their specific requirements. With the Screen Designer, you can effortlessly create various types of ...
    • Screen Designer Terminology

      This is where we can provide a “dictionary” of common terminology a user might encounter while navigating the interface, reading our documentation, or discussing the designer. The goal is to provide a place they can go if they see or hear a phrase ...