UNPKG

@servicenow/sdk

Version:
386 lines (305 loc) 12.1 kB
--- tags: [workspace, dashboard, list-menu, ux, crud, navigation, workspace-configuration] --- # Creating Workspaces Guide Guide for creating ServiceNow Workspaces -- complete out-of-the-box solutions for managing business entities through standardized CRUD workflows. A workspace automatically generates a dashboard page, list management views, and detailed forms following ServiceNow's standard UX patterns. ## When to Use - When creating new workspaces - When the user asks about workspace configuration or best practices - When building a full business process interface with dashboard, list management, and detail forms ## What is a Workspace? A Workspace automatically generates a complete set of pages for managing a business entity: - **Dashboard Page**: Overview dashboard with key metrics and recent activity - **List Page**: Searchable, filterable table view with bulk operations - **Detail/Form Page**: Full CRUD form with related records and actions ## Instructions ### Step 1: Understand the Requirement - Identify the required tables. - First, check whether they already exist on the platform. - If not, look for them within the project. - Create new tables only if they cannot be found in either location. - Gather details about the tables' columns. ### Step 2: Configure the UX List Menu Create a `UxListMenuConfig` inside `list-menu.now.ts` defining the navigation structure and list views. ### Step 3: Configure the Workspace Create a `Workspace` in `workspace.now.ts`: - Ensure you also create an ACL to secure the workspace route. - Associate the UX List Menu configuration to the workspace. ### Step 4: Configure the Dashboard (Mandatory) Create a `Dashboard` inside `dashboard.now.ts`: - Associate the dashboard to the workspace via visibilities. - The dashboard is mandatory for the workspace to function correctly. ### Step 5: Verify Integration - Ensure the `UxListMenuConfig` is properly referenced in the workspace. - Verify that the workspace is referenced in dashboard visibilities. - Confirm ACL field matches workspace path pattern: `{path}.*` - Check that all roles are properly defined and referenced. ### Step 6: Build, Install, and Provide Summary After building and installing, read `src/fluent/generated/keys.ts` to extract the actual sys_id from `sys_ux_page_registry` for the workspace. Provide the user with: - A clickable URL to access the workspace: `/now/{path}/{landingPath}` - A clickable URL to edit in UI Builder: `/now/builder/ui/experience/{workspace_sys_id}` ## File Organization ``` src/ fluent/ workspaces/ incident-tracker/ workspace.now.ts list-menu.now.ts dashboard.now.ts ``` ## Workspace URL Structure ``` /now/{path}/{landingPath} ``` If `path: 'my-example'`, the URL is `/now/my-example/home` (landingPath defaults to `home`). --- ## Workspace API Reference ### Workspace Properties For the full property reference, see the `workspace-api` topic. ### Workspace Example ```typescript fluent import { Workspace, UxListMenuConfig, Acl, Applicability, Role } from '@servicenow/sdk/core'; // 1. Define roles const userRole = Role({ $id: Now.ID['asset_workspace_user_role'], name: 'x_snc_asset.user', containsRoles: ['canvas_user'], }); // 2. Define applicability const assetApplicability = Applicability({ $id: Now.ID['asset_applicability'], name: 'Asset Management Users', roles: [userRole], }); // 3. Create list configuration (see UxListMenuConfig section) const assetListConfig = UxListMenuConfig({ /* ... */ }); // 4. Create workspace export const assetWorkspace = Workspace({ $id: Now.ID['asset_management_workspace'], title: 'Asset Management', path: 'asset-management', tables: ['alm_asset', 'cmdb_ci', 'user'], listConfig: assetListConfig, }); // 5. Create ACL -- field MUST match workspace path + .* Acl({ $id: Now.ID['asset_management_workspace_ACL'], localOrExisting: 'Existing', type: 'ux_route', operation: 'read', roles: ['x_snc_asset.user'], table: 'now', field: 'asset-management.*', }); ``` --- ## UxListMenuConfig API Reference Defines navigation structure and list views for workspaces -- categories, lists, and role-based visibility. ### UxListMenuConfig Properties | Name | Type | Required | Description | |------|------|----------|-------------| | `$id` | `Now.ID[string]` | Yes | Unique identifier | | `name` | `string` | Yes | Name of the list configuration | | `description` | `string` | No | Description | | `active` | `boolean` | No | Whether active (default: `true`) | | `categories` | `UxListCategory[]` | No | Array of categories | ### UxListCategory Properties | Name | Type | Required | Description | |------|------|----------|-------------| | `$id` | `Now.ID[string]` | Yes | Unique identifier | | `title` | `string` | Yes | Display title in navigation | | `order` | `number` | No | Sort order (lower = first) | | `lists` | `UxList[]` | Yes | Array of lists | ### UxList Properties | Name | Type | Required | Description | |------|------|----------|-------------| | `$id` | `Now.ID[string]` | Yes | Unique identifier | | `title` | `string` | Yes | Display title | | `table` | `string` | Yes | ServiceNow table name | | `columns` | `string` | No | Comma-separated column names | | `condition` | `string` | No | Encoded query filter | | `order` | `number` | No | Sort order within category | | `applicabilities` | `ListApplicability[]` | No | Role-based visibility | ### Encoded Query Patterns ```typescript fluent condition: 'active=true^EQ' // Active records condition: '' // All records condition: 'assigned_toDYNAMIC90d1921e5f510100a9ad2572f2b477fe^EQ' // Assigned to current user condition: 'priority=1^ORpriority=2' // High priority ``` ### UxListMenuConfig Example ```typescript fluent const listConfig = UxListMenuConfig({ $id: Now.ID['itsm_workspace_list_config'], name: 'ITSM Workspace List Configuration', categories: [ { $id: Now.ID['incidents_category'], title: 'Incidents', order: 10, lists: [ { $id: Now.ID['incidents_open'], title: 'Open', order: 10, condition: 'active=true^EQ', table: 'incident', columns: 'number,short_description,priority,state', applicabilities: [{ $id: Now.ID['incidents_open_applicability'], applicability: userApplicability, }], }, { $id: Now.ID['incidents_all'], title: 'All', order: 20, condition: '', table: 'incident', columns: 'number,short_description,priority,state', applicabilities: [{ $id: Now.ID['incidents_all_applicability'], applicability: userApplicability, }], }, ], }, ], }); ``` --- ## Dashboard API Reference The Dashboard fluent plugin defines the landing page for workspaces. Dashboards are organized into tabs containing widgets. ### Dashboard Properties | Name | Type | Required | Description | |------|------|----------|-------------| | `$id` | `Now.ID[string]` | Yes | Unique identifier | | `name` | `string` | Yes | Display name | | `tabs` | `DashboardTab[]` | Yes | Array of tabs | | `visibilities` | `DashboardVisibility[]` | Yes | Links dashboard to workspaces | | `permissions` | `DashboardPermission[]` | Yes | Access control (can be empty) | ### Widget Properties | Name | Type | Required | Description | |------|------|----------|-------------| | `$id` | `Now.ID[string]` | Yes | Unique identifier | | `component` | `string` | Yes | Visualization type | | `componentProps` | `object` | Yes | Component configuration | | `height` | `number` | Yes | Height in grid units | | `width` | `number` | Yes | Width in grid units | | `position` | `{x, y}` | Yes | Grid position | ### Grid Layout System Dashboards use a **48-point grid**. Common layouts: - **Full width**: `{ width: 48, position: { x: 0, y: 0 } }` - **Three columns**: widths 14, 17, 17 at x positions 0, 14, 31 ### Widget Component Types **Visualizations:** | Component | Description | Data Type | |-----------|-------------|-----------| | `single-score` | Single metric display | Simple | | `vertical-bar` | Vertical bar chart | Group | | `horizontal-bar` | Horizontal bar chart | Group | | `line` | Line chart | Trend | | `donut` | Donut chart | Group | | `pie` | Pie chart | Group | | `area` | Area chart | Trend | | `dial` | Dial gauge | Simple | **Supporting widgets:** `heading`, `rich-text`, `image`. ### Data Type Requirements - **Simple** (single-score, dial, gauge): requires `dataSources` and `metrics` only. - **Group** (vertical-bar, donut, pie): requires `dataSources`, `metrics`, and `groupBy`. - **Trend** (line, area, column): requires `dataSources`, `metrics`, and `trendBy`. ### Dashboard Example ```typescript fluent import { Dashboard } from '@servicenow/sdk/core'; Dashboard({ $id: Now.ID['incident_dashboard'], name: 'Incident Dashboard', tabs: [{ $id: Now.ID['overview_tab'], name: 'Overview', widgets: [ { $id: Now.ID['open_incidents_widget'], component: 'single-score', componentProps: { dataSources: [{ label: 'Incident', sourceType: 'table', tableOrViewName: 'incident', filterQuery: '', id: 'data_source_1', }], headerTitle: 'Open Incidents', metrics: [{ dataSource: 'data_source_1', id: 'metric_1', aggregateFunction: 'COUNT', axisId: 'primary', }], }, height: 14, width: 14, position: { x: 0, y: 0 }, }, { $id: Now.ID['incidents_by_priority_widget'], component: 'vertical-bar', componentProps: { dataSources: [{ label: 'Incident', sourceType: 'table', tableOrViewName: 'incident', filterQuery: '', id: 'data_source_1', }], headerTitle: 'Incidents by Priority', metrics: [{ dataSource: 'data_source_1', id: 'metric_1', aggregateFunction: 'COUNT', axisId: 'primary', }], groupBy: [{ groupBy: [{ dataSource: 'data_source_1', groupByField: 'priority' }], maxNumberOfGroups: 10, showOthers: false, }], sortBy: 'value', }, height: 14, width: 17, position: { x: 14, y: 0 }, }, ], }], visibilities: [{ $id: Now.ID['dashboard_visibility'], experience: assetWorkspace, }], permissions: [], }); ``` --- ## List API Reference Configure lists (`sys_ui_list`) and their views. | Name | Type | Description | |------|------|-------------| | `table` | String | Required. Table name for the list. | | `view` | Reference | Required. UI view identifier or `default_view`. | | `columns` | ListElement[] | Required. Array of column definitions. | | `parent` | TableName | Parent table for related lists. | ### List Element | Field | Type | Mandatory | Description | |-------|------|-----------|-------------| | `element` | string | Yes | Field name (supports dot walking) | | `position` | number | No | Display position (defaults to array order) | ```typescript fluent import { List } from '@servicenow/sdk/core'; const myList = List({ table: 'cmdb_ci_server', view: app_task_view, columns: [ { element: 'name', position: 0 }, { element: 'business_unit', position: 1 }, ], }); ``` ## Troubleshooting ### Dashboard Not Appearing - Verify `visibilities` references the correct workspace. - Confirm the workspace URL pattern is correct. ### Lists Not Appearing - Check `active` is true for both category and list. - Verify applicability includes the user's roles. - Ensure `listConfig` is referenced in the workspace. ### Workspace Not Accessible - Check ACL field matches `{workspace.path}.*` exactly. - Verify users have required roles.