diff --git a/packages/fiori-docs-embeddings/data_local/SKILLS_TEMPLATE.md b/packages/fiori-docs-embeddings/data_local/SKILLS_TEMPLATE.md new file mode 100644 index 00000000000..da5fc1c7c77 --- /dev/null +++ b/packages/fiori-docs-embeddings/data_local/SKILLS_TEMPLATE.md @@ -0,0 +1,185 @@ +--- +name: [kebab-case-skill-identifier] +description: '[One clear sentence describing what this skill accomplishes and when to use it. Use for: specific use case 1, specific use case 2, specific use case 3.]' +argument-hint: '[expected parameters, inputs, or field names needed for this skill]' +--- + +# [Skill Title] + +## Goal +[One clear sentence describing what this skill accomplishes] + +## Context +[Brief explanation of when/why you would use this skill - 1-2 sentences] + +## Prerequisites +- [Required tool/framework/setup #1] +- [Required tool/framework/setup #2] +- [Required knowledge/file #3] +- [Required condition #4] + +## Steps + +### 1. [Step Name - Gather Information/Requirements] + +[Brief description of what needs to be determined or gathered] + +Ask the user to clarify: +- [Question/requirement #1] +- [Question/requirement #2] +- [Question/requirement #3] + +### 2. [Step Name - First Technical Action] + +[Brief description of what this step accomplishes] + +**File:** `path/to/file` + +```language +// Code example showing the implementation +// Keep it focused on this specific step +// Use placeholders like EntityName, FieldName, etc. +``` + +[Optional bullet points for additional context] +- [Important detail #1] +- [Important detail #2] + +### 3. [Step Name - Second Technical Action] + +[Brief description] + +**File:** `path/to/another/file` + +```language +// Another code example +// Show the pattern clearly +``` + +### 4. [Step Name - Continue Pattern] + +[Keep adding steps as needed, typically 5-8 steps total] + +**File:** `path/to/file` + +```language +// Code example +``` + +### [N]. [Step Name - Final Step - Usually Testing] + +[Description of how to test/verify the implementation] + +```bash +# Command to run +``` + +Verify: +- [Expected result #1] +- [Expected result #2] +- [Expected result #3] + +## [Reference Section Title - e.g., "Configuration Options"] + +| Option | Description | +|--------|-------------| +| `Value1` | What it does | +| `Value2` | What it does | +| `Value3` | What it does | + +## [Another Reference Section - e.g., "Common Patterns"] + +**[Pattern Name]:** +```language +// Code showing this pattern +``` + +**[Another Pattern Name]:** +```language +// Code showing another pattern +``` + +## Common Issues + +**[Problem description]:** +- [Solution point #1] +- [Solution point #2] +- [Solution point #3] + +**[Another problem description]:** +- [Solution point #1] +- [Solution point #2] + +**[Third problem description]:** +- [Solution point #1] +- [Solution point #2] + +## Example Use Cases + +- [Real-world scenario #1] +- [Real-world scenario #2] +- [Real-world scenario #3] +- [Real-world scenario #4] +- [Real-world scenario #5] + +## Notes + +- [Best practice or important consideration #1] +- [Best practice or important consideration #2] +- [Best practice or important consideration #3] +- [Performance tip or caveat] +- [Recommendation for complex scenarios] + +--- + +## Template Usage Instructions + +### Sections to Always Include: +1. **Skill ID** - Unique kebab-case identifier for the skill +2. **Goal** - Single sentence, action-oriented +3. **Context** - Brief "when to use" explanation +4. **Prerequisites** - Bulleted list of requirements +5. **Steps** - Numbered, clear action steps with code examples +6. **Common Issues** - Troubleshooting guide +7. **Example Use Cases** - Real-world scenarios +8. **Notes** - Best practices and tips + +### Optional Sections (use as needed): +- Reference tables (configuration options, types, etc.) +- Common patterns section +- Advanced configurations +- Related skills + +### Writing Guidelines: +- **Be concise** - Short paragraphs, clear actions +- **Use code examples** - Show, don't just tell +- **Use placeholders** - Generic names like `EntityName`, `FieldName` +- **Number steps clearly** - Each step should be actionable +- **Include verification** - Last step should verify success +- **Think troubleshooting** - Address common issues proactively + +### Code Example Format: +```language +// Use comments to explain key parts +// Keep examples focused and minimal +// Use consistent placeholder naming +``` + +### File Reference Format: +**File:** `path/to/file` (always before code blocks) + +### Step Title Format: +"### N. [Action Verb] [What]" - e.g., "### 3. Configure Service Layer" + +### Common Issues Format: +**[Problem in user terms]:** +- [Bullet-point solutions] +- [Keep solutions actionable] + +### Best Practices: +- Start with information gathering +- End with testing/verification +- Keep each step focused on ONE thing +- Use tables for reference information +- Consider the user's perspective +- Make it scannable - use formatting \ No newline at end of file diff --git a/packages/fiori-docs-embeddings/data_local/add-analytical-chart-to-list-report.skills.md b/packages/fiori-docs-embeddings/data_local/add-analytical-chart-to-list-report.skills.md new file mode 100644 index 00000000000..9c657434efd --- /dev/null +++ b/packages/fiori-docs-embeddings/data_local/add-analytical-chart-to-list-report.skills.md @@ -0,0 +1,270 @@ +--- +name: add-analytical-chart-to-list-report +description: 'Add an analytical chart view to a SAP Fiori Elements List Report page to visualize aggregated data (average, sum, min, max) grouped by dimensions. Use for: displaying data trends and patterns through visual charts, adding chart views to List Reports, enabling aggregation support in OData V4 applications.' +argument-hint: 'entity name, dimension field (grouping), measure field (aggregation), aggregation method (average/sum/min/max), and chart type' +--- + +# Add Analytical Chart to SAP Fiori List Report + +## Goal +Add an analytical chart view to a SAP Fiori Elements List Report page to visualize aggregated data (average, sum, min, max) grouped by dimensions. + +## Context +Analytical charts in List Reports help users understand patterns and trends through visual data representation. This skill enables chart capabilities with proper aggregation support for SAP Fiori Elements OData V4 applications. + +## Prerequisites +- Existing SAP Fiori Elements List Report application (OData V4) +- CAP-based backend service with entity model +- Entity with numeric fields for aggregation +- Dimension field for grouping data + +## Steps + +### 1. Gather Requirements + +Ask the user to clarify: +- Target entity name +- Dimension field for grouping (e.g., Destination, Category, Status) +- Measure field to aggregate (e.g., TotalPrice, Revenue, Quantity) +- Desired aggregation method (average, sum, min, max) +- Preferred chart type (Column, Bar, Line, Donut, etc.) + +### 2. Configure Aggregation Support + +Enable analytical capabilities on the service entity. This is REQUIRED for analytical charts. + +**File:** `srv/service-name.cds` + +```cds +service ServiceName @(path: '/service-path') { + @Aggregation.ApplySupported: { + Transformations: ['aggregate', 'groupby'], + AggregatableProperties: [ + { Property: MeasureField } + ], + GroupableProperties: [ + DimensionField, + OtherField1, + OtherField2 + ] + } + entity EntityName as projection on db.EntityName; +} + +annotate ServiceName.EntityName with @odata.draft.enabled; +``` + +**Important:** +- `Transformations` must include both 'aggregate' and 'groupby' +- List all numeric fields in `AggregatableProperties` +- List all fields that can be used for grouping in `GroupableProperties` + +### 3. Define Aggregated Property + +Create aggregated property for the measure using the desired aggregation method. + +**File:** `app/app-name/annotations.cds` or `srv/service-name.cds` + +```cds +annotate ServiceName.EntityName with @( + Analytics.AggregatedProperty #MeasureField_average: { + $Type: 'Analytics.AggregatedPropertyType', + Name: 'MeasureField_average', + AggregatableProperty: MeasureField, + AggregationMethod: 'average', + @Common.Label: 'Average Measure' + } +); +``` + +**Aggregation Methods:** +- `'average'` - Calculate mean value +- `'sum'` - Calculate total +- `'min'` - Find minimum value +- `'max'` - Find maximum value +- `'countdistinct'` - Count unique values + +### 4. Add Chart Annotation + +Define the chart visualization with proper qualifier. + +**File:** `app/app-name/annotations.cds` or `srv/service-name.cds` + +```cds +annotate ServiceName.EntityName with @( + UI.Chart #ChartByDimension: { + $Type: 'UI.ChartDefinitionType', + Title: 'Average Measure by Dimension', + ChartType: #Column, + Dimensions: [ + DimensionField + ], + DynamicMeasures: [ + '@Analytics.AggregatedProperty#MeasureField_average' + ] + } +); +``` + +**Chart Types:** +- `#Column` - Vertical bars (best for comparing categories) +- `#Bar` - Horizontal bars (good for long category names) +- `#Line` - Connected points (ideal for trends over time) +- `#Donut` - Ring chart (part-to-whole relationships) + +### 5. Configure Manifest for Chart View + +Add the chart view configuration to enable the analytical chart on the List Report. + +**File:** `app/app-name/webapp/manifest.json` + +```json +{ + "targets": { + "EntityList": { + "type": "Component", + "id": "EntityList", + "name": "sap.fe.templates.ListReport", + "options": { + "settings": { + "contextPath": "/EntityName", + "variantManagement": "Page", + "views": { + "paths": [ + { + "primary": [ + { + "annotationPath": "com.sap.vocabularies.UI.v1.Chart#ChartByDimension" + } + ], + "secondary": [ + { + "annotationPath": "com.sap.vocabularies.UI.v1.LineItem" + } + ], + "defaultPath": "both" + } + ] + } + } + } + } + } +} +``` + +**Configuration:** +- `primary` - Chart view (uses Chart annotation) +- `secondary` - Table view (uses LineItem annotation) +- `defaultPath` - Initial view: "both" (hybrid), "primary" (chart only), "secondary" (table only) + +### 6. Test the Chart + +Start the application and verify chart functionality. + +```bash +cd project-folder +npm run watch-app-name +``` + +**Verify:** +- Chart displays in List Report with segmented buttons (Chart/Table/Both) +- Chart shows aggregated data grouped by dimension +- Table displays detail records +- Users can switch between Chart, Table, and Hybrid views +- Aggregations calculate correctly based on the data + +## Chart Type Selection Guide + +| Chart Type | Best For | Data Requirements | +|------------|----------|-------------------| +| `#Column` | Comparing categories, trends | 1 dimension, 1+ measures | +| `#Bar` | Long category names, rankings | 1 dimension, 1+ measures | +| `#Line` | Time series, continuous trends | 1 dimension (ideally time), 1+ measures | +| `#Donut` | Part-to-whole relationships | 1 dimension, 1 measure | +| `#Area` | Volume trends over time | 1 dimension (time), 1+ measures | +| `#Bubble` | Multi-dimensional comparison | 1 dimension, 2-3 measures | + +## Multiple Measures Pattern + +To add multiple aggregation options (average, sum, min, max): + +```cds +annotate ServiceName.EntityName with @( + Analytics.AggregatedProperty #MeasureField_average: { + $Type: 'Analytics.AggregatedPropertyType', + Name: 'MeasureField_average', + AggregatableProperty: MeasureField, + AggregationMethod: 'average', + @Common.Label: 'Average Price' + }, + Analytics.AggregatedProperty #MeasureField_sum: { + $Type: 'Analytics.AggregatedPropertyType', + Name: 'MeasureField_sum', + AggregatableProperty: MeasureField, + AggregationMethod: 'sum', + @Common.Label: 'Total Price' + } +); + +annotate ServiceName.EntityName with @( + UI.Chart #ChartByDimension: { + $Type: 'UI.ChartDefinitionType', + Title: 'Price Analysis by Dimension', + ChartType: #Column, + Dimensions: [ + DimensionField + ], + DynamicMeasures: [ + '@Analytics.AggregatedProperty#MeasureField_average', + '@Analytics.AggregatedProperty#MeasureField_sum' + ] + } +); +``` + +Users can then switch between measures using a dropdown in the chart toolbar. + +## Common Issues + +**Chart not appearing:** +- Check `@Aggregation.ApplySupported` is properly configured on the service entity +- Verify dimension field has data values in CSV +- Ensure measure field is numeric (Decimal, Integer) +- Confirm manifest.json has the correct `views` configuration + +**Measures not switching:** +- Verify DynamicMeasures array syntax is correct +- Check AggregatedProperty names match references exactly +- Use correct format: `@Analytics.AggregatedProperty#PropertyName_method` +- Ensure qualifier matches between definition and chart reference + +**Aggregation errors:** +- Confirm GroupableProperties includes all dimension fields +- Verify AggregatableProperties includes all measure fields +- Check CSV data has proper values for grouping +- Ensure Transformations includes both 'aggregate' and 'groupby' + +**Chart qualifier not found:** +- Verify annotationPath in manifest matches the chart qualifier exactly +- Format: `com.sap.vocabularies.UI.v1.Chart#QualifierName` +- Check annotation is defined in the service or app annotations file + +## Example Use Cases + +- **Sales Analysis**: Average revenue by region, total orders by product category +- **Inventory**: Min/max stock levels by warehouse, item counts by status +- **Travel**: Average trip cost by destination, total bookings by season +- **Finance**: Sum of expenses by department, average budget by quarter +- **Operations**: Max processing time by workflow, count of tasks by priority + +## Notes + +- Analytical charts require SAPUI5 version 1.106+ for full feature support +- Charts automatically handle currency and unit formatting +- Use `defaultPath: "both"` for best user experience (shows chart and table) +- Chart data is aggregated on the backend for better performance +- Users can personalize chart type and measures using variant management +- For time-based dimensions, consider using Date or DateTime types +- Multiple dimensions are supported but keep chart readable (max 2 dimensions recommended) +- Annotations can be defined in either `srv/service-name.cds` or `app/app-name/annotations.cds` \ No newline at end of file diff --git a/packages/fiori-docs-embeddings/data_local/configure-externalid.skills.md b/packages/fiori-docs-embeddings/data_local/configure-externalid.skills.md new file mode 100644 index 00000000000..b0fb84ff9f4 --- /dev/null +++ b/packages/fiori-docs-embeddings/data_local/configure-externalid.skills.md @@ -0,0 +1,288 @@ +--- +name: configure-externalid +description: 'Hide technical GUID keys and display readable business IDs instead when using associations in SAP Fiori Elements applications using the @Common.ExternalID annotation. Use for: showing business keys instead of UUIDs in UI, configuring associations to display readable IDs, improving user experience with meaningful identifiers.' +argument-hint: 'association field name, target entity external ID field name' +--- + +# Configure External ID for Associations + +## Goal +Hide technical GUID keys and display readable business IDs instead when using associations in SAP Fiori Elements applications using the @Common.ExternalID annotation. + +## Context +Use this skill when your entities use both technical keys (UUIDs/GUIDs) and business keys (external IDs like customer numbers, product codes), and you want users to see and work with the readable business IDs instead of technical GUIDs in the UI. + +## Prerequisites +- Existing SAP Fiori Elements application (OData V4) +- CAP-based backend service with entity model +- Entities using UUIDs as technical keys (e.g., from cuid aspect) +- Business/External ID fields defined in entities (e.g., customerID, partnerID) +- Understanding of associations and CDS annotations + +## Steps + +### 1. Gather Requirements + +Ask the user to clarify: +- Which association field needs External ID configuration +- What is the readable business ID field name in the target entity +- Whether they want text arrangement on the external ID (e.g., show name with ID) + +### 2. Verify Entity Structure + +Ensure your entities have both technical (GUID) and business (External) IDs defined. + +**File:** `db/schema.cds` + +```cds +using { managed, cuid } from '@sap/cds/common'; + +entity Partner : cuid, managed { + // ID is the technical GUID (from cuid) + partnerID : String(10) @title: 'Partner ID'; // Business/External ID + name : String(100) @title: 'Partner Name'; + type : String(20) @title: 'Partner Type'; + country : String(50) @title: 'Country'; +} + +entity SalesOrder : cuid, managed { + orderID : String(10) @title: 'Order ID'; + description : String(255) @title: 'Description'; + partner : Association to Partner; // Association uses technical GUID + totalAmount : Decimal(16,2) @title: 'Total Amount'; + status : String(1) @title: 'Status'; +} +``` + +Key points: +- Technical key `ID` comes from `cuid` aspect (UUID type) +- Business key `partnerID` is a readable string field +- Association uses the technical GUID internally + +### 3. Configure Text on External ID (Optional but Recommended) + +If you want the external ID to display with descriptive text, configure it on the target entity. + +**File:** `app/app-name/annotations.cds` or `srv/service-name.cds` + +```cds +using MyService as service from '../../srv/service'; + +// Configure Text and TextArrangement on the readable ID in Partner entity +annotate service.Partner with { + partnerID @( + Common.Text : name, + Common.TextArrangement : #TextFirst + ); +}; +``` + +This makes the partnerID display as "ABC Corporation (P-10001)" instead of just "P-10001". + +### 4. Apply Common.ExternalID on Association + +Configure the association field to use the external ID instead of the GUID. + +**File:** `app/app-name/annotations.cds` or `srv/service-name.cds` + +```cds +// Apply Common.ExternalID on the association field in SalesOrder entity +annotate service.SalesOrder with { + partner @( + Common.ExternalID : partner.partnerID, + Common.Label: 'Partner' + ); +}; +``` + +**Important:** The `@Common.ExternalID` annotation is applied on the **association field**, pointing to the path of the readable ID through the association. + +### 5. Configure ValueList for the Association + +Add a ValueList to enable search help functionality with the external ID. + +**File:** `app/app-name/annotations.cds` or `srv/service-name.cds` + +```cds +annotate service.SalesOrder with { + partner @( + Common.ExternalID : partner.partnerID, + Common.Label: 'Partner', + Common.ValueList: { + $Type: 'Common.ValueListType', + CollectionPath: 'Partner', + Parameters: [ + { + $Type: 'Common.ValueListParameterInOut', + LocalDataProperty: partner_ID, + ValueListProperty: 'ID' + }, + { + $Type: 'Common.ValueListParameterDisplayOnly', + ValueListProperty: 'partnerID' + }, + { + $Type: 'Common.ValueListParameterDisplayOnly', + ValueListProperty: 'name' + }, + { + $Type: 'Common.ValueListParameterDisplayOnly', + ValueListProperty: 'type' + } + ] + }, + Common.ValueListWithFixedValues: false + ); +}; +``` + +**Key Points:** +- `ValueListParameterInOut` uses the technical `ID` for data binding +- `ValueListParameterDisplayOnly` shows external ID and other fields to users +- This ensures the GUID is used internally while showing readable fields in UI + +### 6. Hide Technical GUID Fields (Optional) + +If the technical GUID fields appear in forms or tables, hide them. + +**File:** `app/app-name/annotations.cds` or `srv/service-name.cds` + +```cds +annotate service.SalesOrder with { + partner_ID @UI.Hidden; +}; + +annotate service.Partner with { + ID @UI.Hidden; +}; +``` + +### 7. Test the Configuration + +Start the application and verify the external ID display. + +```bash +cd project-folder +npm run watch-app-name +``` + +**Verify:** +- Filter fields display the external ID (e.g., "P-10001") instead of GUID +- Value help shows external ID and descriptive fields +- Forms display the external ID with text arrangement if configured +- Tables show the readable external ID +- Technical GUIDs are completely hidden from users +- Data saving works correctly (uses GUID internally) + +## Complete Example with XML Format + +### Annotations - XML Format + +**File:** `app/app-name/webapp/annotations/annotation.xml` + +```xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +``` + +## How External ID Works + +1. **Technical Layer (Internal):** + - The association uses the technical GUID (`partner_ID`) for data storage and relationships + - Database joins and references use the UUID + +2. **UI Layer (User-Facing):** + - `@Common.ExternalID` tells SAP Fiori Elements to display the external ID (`partnerID`) + - Users see and search by the readable business ID + - Technical GUIDs are completely hidden + +3. **Data Flow:** + - User selects "ABC Corporation (P-10001)" from value help + - UI displays "P-10001" or "ABC Corporation (P-10001)" based on text arrangement + - Backend stores the corresponding technical GUID + - On read, GUID is translated back to external ID for display + +## Important Rules + +- The `@Common.ExternalID` annotation must be applied on the **association field** (e.g., `partner`), pointing to the path of the readable ID (e.g., `partner.partnerID`) +- `@Common.Text` and `@Common.TextArrangement` should be applied on the **readable ID property in the target entity** (e.g., `partnerID` in Partner entity), NOT on the association itself +- Do NOT add Text/TextArrangement annotations on the association field - they belong only on the external ID property +- ValueList must use the technical `ID` for the InOut parameter to ensure correct data binding +- External ID field must be unique or have appropriate constraints + +## Common Issues + +**GUID still showing in the UI:** +- Verify `@Common.ExternalID` is applied on the association field, not the _ID field +- Check the path points correctly to the external ID through the association (e.g., `partner.partnerID`) +- Add `@UI.Hidden` annotation to the technical ID field if it still appears + +**ValueList not working after configuring External ID:** +- Ensure the ValueList uses the technical `ID` for `ValueListProperty` in the InOut parameter +- Verify `LocalDataProperty` points to the foreign key field (e.g., `partner_ID`) +- Check that external ID is included as a DisplayOnly parameter + +**External ID not displaying with text:** +- Ensure `@Common.Text` and `@Common.TextArrangement` are configured on the external ID property in the target entity +- Do not apply these annotations on the association field itself +- Verify the text field (e.g., `name`) exists and is populated in data + +**Filtering not working by external ID:** +- Check that the external ID field is included in the service projection +- Ensure the external ID field is properly populated in your data +- Verify no typos in the ExternalID path + +**Data not saving correctly:** +- Confirm the ValueList InOut parameter uses the technical `ID` field +- Verify the association is properly defined in the data model +- Check that the external ID values in CSV match existing partner records + +## Example Use Cases + +- Display customer numbers instead of GUIDs in sales orders +- Show product codes instead of technical IDs in order items +- Present employee IDs instead of UUIDs in HR forms +- Display partner numbers instead of GUIDs in business documents +- Show material numbers instead of technical keys in inventory + +## Notes + +- External ID configuration improves user experience by hiding technical complexity +- Users work with familiar business IDs they already know +- Technical GUIDs remain in use for database integrity and performance +- Always test with real data to ensure external IDs are properly populated +- Consider adding validation to ensure external IDs are unique +- External ID should be immutable or rarely changed for consistency +- Combine with @Common.Text for even better user experience +- This pattern is essential for user-friendly SAP Fiori applications \ No newline at end of file diff --git a/packages/fiori-docs-embeddings/data_local/configure-text-textarrangement.skills.md b/packages/fiori-docs-embeddings/data_local/configure-text-textarrangement.skills.md new file mode 100644 index 00000000000..76b1d033373 --- /dev/null +++ b/packages/fiori-docs-embeddings/data_local/configure-text-textarrangement.skills.md @@ -0,0 +1,239 @@ +--- +name: configure-text-textarrangement +description: 'Configure how ID and description fields are displayed together in SAP Fiori Elements applications using @Common.Text and @UI.TextArrangement annotations. Use for: displaying IDs with descriptions, configuring dropdown display formats, showing code-description pairs in tables and forms, enhancing user experience with meaningful text.' +argument-hint: 'entity name, ID field name, text/description field name, and display arrangement preference (TextFirst, TextLast, TextOnly, TextSeparate)' +--- + +# Configure Text and TextArrangement + +## Goal +Configure how ID and description fields are displayed together in SAP Fiori Elements applications using @Common.Text and @UI.TextArrangement annotations. + +## Context +Use this skill when you need to display both an ID (e.g., code, key) and its description in dropdowns, tables, or forms. This enhances user experience by showing meaningful text alongside technical IDs. + +## Prerequisites +- Existing SAP Fiori Elements application (OData V4) +- CAP-based backend service with entity model +- Entities with ID fields and corresponding description/text fields +- Understanding of CDS annotations + +## Steps + +### 1. Gather Requirements + +Ask the user to clarify: +- Which entity and field needs text configuration +- Which field contains the descriptive text +- Preferred display format (Description first, ID first, text only, or separate columns) + +### 2. Define the Text Annotation + +Link the ID field to its descriptive text field using `@Common.Text` in your data model. + +**File:** `db/schema.cds` + +```cds +entity SalesOrder { + key ID : UUID; + OrderID : String; + ProductID : String; + Status : String @Common.Text: StatusText; + StatusText : String; +} +``` + +The `@Common.Text` annotation creates a relationship between the ID field and its readable description. + +### 3. Configure TextArrangement + +Add the `@UI.TextArrangement` annotation to control how the ID and text are displayed together. + +**File:** `app/app-name/annotations.cds` or `srv/service-name.cds` + +**Option A: Direct TextArrangement annotation (standard)** +```cds +using MyService from '../srv/service'; + +// Show Description (ID) - Most Common +annotate MyService.SalesOrder with { + ProductID @UI.TextArrangement: #TextFirst; +} + +// Show ID (Description) +annotate MyService.SalesOrder with { + ProductID @UI.TextArrangement: #TextLast; +} + +// Show only Description (ID is hidden) +annotate MyService.SalesOrder with { + Status @UI.TextArrangement: #TextOnly; +} + +// Show ID and Description in separate columns +annotate MyService.SalesOrder with { + ProductID @UI.TextArrangement: #TextSeparate; +} +``` + +**Option B: TextArrangement applied to Common.Text (alternative syntax)** +```cds +// This syntax applies TextArrangement directly to the Text annotation +annotate MyService.Partner with { + partnerID @( + Common.Text : name, + Common.Text.@UI.TextArrangement : #TextFirst + ) +}; +``` + +Both syntaxes achieve the same result. + +### 4. Test the Configuration + +Start the application and verify the text display. + +```bash +cd project-folder +npm run watch-app-name +``` + +**Verify:** +- ID and description display according to chosen arrangement +- Dropdowns show the correct format +- Tables display the configured text arrangement +- Form fields show the expected text format + +## TextArrangement Options + +| Option | Display Format | Example | Best For | +|--------|----------------|---------|----------| +| `#TextFirst` | Description (ID) | "Premium Widget (PROD-001)" | When description is more important (customer names, product names) | +| `#TextLast` | ID (Description) | "PROD-001 (Premium Widget)" | When ID is more important (product codes, account numbers) | +| `#TextOnly` | Description only | "Confirmed" | When ID is purely technical and users don't need to see it | +| `#TextSeparate` | Separate columns | ID: PROD-001
Name: Premium Widget | When both values need equal visibility in tables | + +## Complete Example + +### Data Model +**File:** `db/schema.cds` + +```cds +namespace my.app; + +entity SalesOrder { + key ID : UUID; + OrderID : String; + CustomerID : String; + ProductID : String @Common.Text: ProductName; + ProductName : String; + Status : String @Common.Text: StatusText; + StatusText : String; +} +``` + +### Service Definition +**File:** `srv/service.cds` + +```cds +using { my.app as db } from '../db/schema'; + +service OrderService { + entity SalesOrder as projection on db.SalesOrder; +} +``` + +### Annotations +**File:** `app/app-name/annotations.cds` + +```cds +using OrderService from '../srv/service'; + +// Show Product Name first, then ID in parentheses +annotate OrderService.SalesOrder with { + ProductID @UI.TextArrangement: #TextFirst; + // Result: "Premium Widget (PROD-001)" +} + +// Show Product ID first, then Name in parentheses +annotate OrderService.SalesOrder with { + ProductID @UI.TextArrangement: #TextLast; + // Result: "PROD-001 (Premium Widget)" +} + +// Show only Status text, hide the code +annotate OrderService.SalesOrder with { + Status @UI.TextArrangement: #TextOnly; + // Result: "Confirmed" (instead of "C (Confirmed)") +} +``` + +## Common Patterns + +### Customer/Partner Fields +```cds +CustomerID @Common.Text: CustomerName + @UI.TextArrangement: #TextFirst; +// Shows: "Jane Smith (C12345)" +``` + +### Product/Material Fields +```cds +ProductID @Common.Text: ProductDescription + @UI.TextArrangement: #TextLast; +// Shows: "PROD-001 (Premium Widget)" +``` + +### Status/Code Fields +```cds +StatusCode @Common.Text: StatusDescription + @UI.TextArrangement: #TextOnly; +// Shows: "Active" (hides the code) +``` + +### Category Fields +```cds +CategoryID @Common.Text: CategoryName + @UI.TextArrangement: #TextSeparate; +// Shows ID and Name in separate table columns +``` + +## Common Issues + +**Both ID and description show the same value:** +- Check that `@Common.Text` points to the correct description field +- Verify the text field name matches exactly in your data model + +**Only ID shows, no description:** +- Ensure the description field is populated in your data (CSV files) +- Verify the text field is included in the service projection +- Check that the field path in `@Common.Text` is correct + +**TextArrangement not working:** +- Verify that both `@Common.Text` and `@UI.TextArrangement` are on the same field +- Ensure you're testing with data that has both ID and description populated +- Clear browser cache and reload the application + +**Different format appears than expected:** +- Double-check the TextArrangement enum value (#TextFirst, #TextLast, etc.) +- Verify no conflicting annotations exist in other files +- Check if manifest.json has any overriding configurations + +## Example Use Cases + +- Display customer names with IDs in sales orders +- Show product descriptions alongside product codes in inventory +- Present status descriptions instead of cryptic status codes +- Display partner names with partner IDs in business documents +- Show material descriptions with material numbers in manufacturing + +## Notes + +- Always define `@Common.Text` before using `@UI.TextArrangement` +- TextArrangement can be applied at the entity level or in annotations +- Both syntaxes (Option A and B) are valid - choose based on team preference +- For consistency, use the same TextArrangement pattern across similar fields +- Test with real data to ensure both ID and text fields are properly populated +- Consider user workflows when choosing between TextFirst and TextLast +- Use TextOnly for truly technical fields that users don't need to see +- TextSeparate is useful in tables but may not work well in dropdowns \ No newline at end of file diff --git a/packages/fiori-docs-embeddings/data_local/create-hierarchy-tree-table.skills.md b/packages/fiori-docs-embeddings/data_local/create-hierarchy-tree-table.skills.md new file mode 100644 index 00000000000..ccf140a54bd --- /dev/null +++ b/packages/fiori-docs-embeddings/data_local/create-hierarchy-tree-table.skills.md @@ -0,0 +1,248 @@ +--- +name: create-hierarchy-tree-table +description: 'Automatically create a recursive hierarchy data model in a CAP project and configure it to display as a tree table in a SAP Fiori Elements List Report application. Use for: displaying parent-child relationships, building organizational hierarchies, creating category trees, showing nested structures, implementing recursive hierarchies.' +argument-hint: 'entity name, namespace, service name, and app path' +--- + +# Skill: Create Hierarchical Tree Table in SAP Fiori Elements + +## When to Use This Skill +- When you need to display parent-child relationships in a tree structure +- When building organizational hierarchies, category trees, or nested structures +- When the user requests "recursive hierarchy", "tree table", "parent-child data", or "hierarchical display" + +## Prerequisites +- Existing CAP project with CDS entity +- SAP Fiori Elements List Report application +- Entity must use `cuid` or have a UUID primary key + +## Parameters Required +- `entityName`: The name of the entity to make hierarchical (e.g., "Travel", "Category", "Task") +- `namespace`: The CDS namespace (e.g., "sap.fe.cap.travel") +- `serviceName`: The service name (e.g., "TravelService") +- `appPath`: Path to the Fiori app folder (e.g., "app/travelmanagement") + +## Implementation Steps + +### Step 1: Check Current Entity Structure +**Action:** Use `cds-mcp` server to search for the entity definition +``` +Tool: use_mcp_tool +Server: cds-mcp +Tool: search_model +Arguments: { + "projectPath": "", + "name": "", + "kind": "entity" +} +``` + +### Step 2: Update Entity with Hierarchy Association +**Action:** Add self-referencing managed association to the entity + +**Pattern to add:** +```cds +entity : cuid, managed { + // ... existing fields ... + + // Add hierarchy support + parent : Association to ; + + // ... rest of entity ... +} +``` + +**Implementation:** +``` +Tool: replace_in_file +Path: db/schema.cds +``` + +**Rules:** +- Use managed association (no `on` condition) +- Name it `parent` (convention creates `parent_ID` foreign key) +- Add before compositions or at end of entity definition + +### Step 3: Add Hierarchy Annotation to Service +**Action:** Add `@hierarchy` annotation to entity projection in service + +**Pattern to add:** +```cds +service @(path: '/') { + @hierarchy + entity as projection on db. { + *, + // ... redirected associations ... + }; +} +``` + +**Implementation:** +``` +Tool: replace_in_file +Path: srv/.cds +``` + +**Rules:** +- Add `@hierarchy` annotation before the entity definition +- Keep all existing projections and redirections +- Verify the annotation is on the service entity, not the database entity + +### Step 4: Configure TreeTable in Manifest +**Action:** Update Fiori app manifest.json to use TreeTable + +**Pattern to modify in List Report target:** +```json +"controlConfiguration": { + "@com.sap.vocabularies.UI.v1.LineItem": { + "tableSettings": { + "type": "TreeTable", + "hierarchyQualifier": "Hierarchy" + } + } +} +``` + +**Implementation:** +``` +Tool: replace_in_file +Path: /webapp/manifest.json +``` + +**Rules:** +- Locate the List Report target (not Object Page) +- Change existing `tableSettings.type` from "ResponsiveTable" to "TreeTable" +- Add `hierarchyQualifier` with descriptive name +- Keep all other settings intact + +### Step 5: Create or Update Sample Data +**Action:** Create hierarchical sample data with parent-child relationships + +**CSV Format:** +```csv +ID;Field1;Field2;...;parent_ID +;Root Item 1;...; +;Child 1-1;...; +;Child 1-2;...; +;Root Item 2;...; +;Child 2-1;...; +``` + +**Implementation:** +``` +Tool: write_to_file +Path: db/data/-.csv +``` + +**Rules:** +- Use `parent_ID` as column name (with underscore) +- Use valid UUID format for IDs +- Leave `parent_ID` empty for root items (top level) +- Ensure parent IDs reference existing records +- Create at least 2-3 hierarchy levels for demo + +**Sample Structure:** +- 3-4 root items (no parent) +- 2-3 children per root +- 1-2 grandchildren to show depth + +### Step 6: Test the Implementation +**Action:** Start the application and verify + +**Implementation:** +``` +Tool: execute_command +Command: cd && npm run watch- +``` + +**Verification Checklist:** +- [ ] Application starts without errors +- [ ] No CDS compilation warnings about @hierarchy +- [ ] Data loads successfully +- [ ] List Report displays +- [ ] Tree expand/collapse controls visible +- [ ] Hierarchy structure matches data model + +## Common Errors and Solutions + +### Error: "@hierarchy is not supported for unmanaged association" +**Cause:** Using unmanaged association with `on` condition +**Solution:** Remove the `on` clause, use managed association: +```cds +// ❌ Wrong +parent : Association to Travel on parent.ID = parentID; + +// ✅ Correct +parent : Association to Travel; +``` + +### Error: "table has no column named parentID" +**Cause:** CSV file uses wrong column name +**Solution:** Use `parent_ID` with underscore in CSV header + +### Error: "No artifact has been found with name 'cuid'" +**Cause:** Missing import statement +**Solution:** Add at top of schema.cds: +```cds +using { Currency, managed, cuid } from '@sap/cds/common'; +``` + +### Warning: "@hierarchy is ignored as no managed association to self exists" +**Cause:** Association is not properly configured as managed +**Solution:** Verify association has no `on` condition and references same entity type + +## Output Deliverables + +After successful execution, the following changes will be made: + +1. **Updated Entity Schema** (`db/schema.cds`) + - Self-referencing `parent` association added + +2. **Updated Service Definition** (`srv/.cds`) + - `@hierarchy` annotation added to entity + +3. **Updated Manifest** (`app//webapp/manifest.json`) + - TreeTable configuration in List Report + +4. **Sample Hierarchical Data** (`db/data/-.csv`) + - Multi-level parent-child records + +5. **Running Application** + - Tree table visible in List Report + - Expand/collapse controls functional + +## Usage Example + +**User Request:** +"Create a recursive hierarchy for the Category entity and show it in a tree table" + +**Skill Execution:** +1. Search for Category entity using cds-mcp +2. Add `parent: Association to Category;` to entity +3. Add `@hierarchy` to service entity +4. Update manifest.json with TreeTable config +5. Create sample data with category hierarchy +6. Start application with npm run watch + +**Expected Result:** +- Categories displayed in tree structure +- Parent categories expandable to show children +- Multiple levels of nesting visible + +## Tips for Customization + +1. **Deeper Hierarchies:** Add more levels in sample data +2. **Different Field Names:** Use meaningful association names, but keep CSV as `_ID` +3. **UI Annotations:** Add @UI.LineItem annotations for better column display +4. **Validation Logic:** Add business logic to prevent circular references +5. **Performance:** Consider pagination for large datasets + +## References + +- CAP Associations: https://cap.cloud.sap/docs/cds/cdl#associations +- Fiori TreeTable: https://sapui5.hana.ondemand.com/#/topic/c337707a119c4e6ca7b8800858bb5f1c +- OData Hierarchy: https://docs.oasis-open.org/odata/odata-data-aggregation-ext/v4.0/ + +## Version History + +- v1.0 (2026-04-01): Initial skill creation for CAP + Fiori Elements hierarchies \ No newline at end of file diff --git a/packages/fiori-docs-embeddings/data_local/rich-text-editor-building-block.skills.md b/packages/fiori-docs-embeddings/data_local/rich-text-editor-building-block.skills.md new file mode 100644 index 00000000000..6cd9c030fd6 --- /dev/null +++ b/packages/fiori-docs-embeddings/data_local/rich-text-editor-building-block.skills.md @@ -0,0 +1,295 @@ +--- +name: fiori-building-blocks +description: 'Add SAP Fiori Elements building blocks (RichTextEditor, Table, Chart, Form) to custom sections in Object Pages. Use for: adding rich text editor to display/edit formatted fields, creating custom sections with building blocks, extending Fiori Elements OData V4 apps with fragment-based custom content.' +argument-hint: 'building block type (e.g., RichTextEditor) and field name' +--- + +# Fiori Elements Building Blocks in Custom Sections + +Add SAP Fiori Elements building blocks to custom sections on Object Pages using fragments and manifest configuration. + +## When to Use + +- Add a **RichTextEditor** to display/edit formatted text fields (memo, description, notes) +- Add a **Table**, **Chart**, or **Form** building block to a custom section +- Extend a Fiori Elements Object Page with custom fragment-based content +- Use building blocks with proper OData bindings in custom sections + +## Prerequisites + +- Fiori Elements OData V4 application with Object Page +- MCP Fiori server available for documentation search +- Knowledge of the entity property to bind to + +## Workflow + +### 1. Identify Requirements + +**Gather:** +- Building block type (RichTextEditor, Table, Chart, Form, etc.) +- Target entity property/field name +- Section title and positioning preference + +**Example:** "Add rich text editor for the Memo field in a new section called Trip Description" + +### 2. Search MCP Documentation + +Search for building block syntax and configuration: + +``` +Search queries: +- "rich text editor building block" +- "RichTextEditor fragment syntax" +- "custom section object page OData V4" +- " building block" +``` + +**Key findings to extract:** +- Required XML namespaces +- Building block element name and attributes +- Binding syntax (value, metaPath, etc.) +- Optional configuration (buttonGroups, plugins, etc.) + +### 3. Examine Data Model + +Read the metadata or service definition to verify: +- Entity type name +- Property name and data type +- Property annotations (if any) + +**Files to check:** +- `webapp/localService/mainService/metadata.xml` (OData metadata) +- Service CDS definitions (if available) + +### 4. Create Fragment File + +**Location:** `webapp/ext/fragment/.fragment.xml` + +**Template for RichTextEditor:** +```xml + + + +``` + +**Common Building Blocks:** + +| Building Block | Element | Key Attributes | +|---|---|---| +| RichTextEditor | `macros:RichTextEditor` | `value="{Property}"` or `metaPath="Property"` | +| Table | `macros:Table` | `metaPath="@com.sap.vocabularies.UI.v1.LineItem"` | +| Chart | `macros:Chart` | `metaPath="@com.sap.vocabularies.UI.v1.Chart"` | +| Field | `macros:Field` | `metaPath="Property"` | + +**Note:** +- Use `value="{Property}"` for direct data binding +- Use `metaPath="Property"` when binding requires metadata/annotation resolution +- `RichTextEditorWithMetadata` requires annotation term path, not just property name + +### 5. Update Manifest Configuration + +**Location:** `webapp/manifest.json` + +**Find:** `sap.ui5.routing.targets..options.settings` + +**Add:** Custom section configuration under `content.body.sections` + +```json +{ + "content": { + "body": { + "sections": { + "": { + "name": ".ext.fragment.", + "type": "XMLFragment", + "title": "Section Title", + "position": { + "placement": "After", + "anchor": "" + } + } + } + } + } +} +``` + +**Key Configuration:** +- `name`: Full fragment namespace path (e.g., `travelapp.ext.fragment.TripDescription`) +- `type`: Always `"XMLFragment"` +- `title`: Display label for the section +- `position`: Optional; controls placement relative to other sections + - `placement`: "Before", "After", or omit for last position + - `anchor`: ID of existing section to place relative to + +**To add as last section (simplest):** +```json +{ + "content": { + "body": { + "sections": { + "": { + "name": ".ext.fragment.", + "type": "XMLFragment", + "title": "Section Title" + } + } + } + } +} +``` + +### 6. Validate and Fix Errors + +**Check for errors** in both files: +- Fragment XML: Verify namespaces, binding syntax, property names +- Manifest JSON: Verify fragment path matches namespace and file location + +**Common Issues:** + +| Error | Cause | Fix | +|---|---|---| +| "Path value must end with annotation term" | Using `metaPath` with RichTextEditor without annotation | Use `value="{Property}"` instead | +| Fragment not found | Namespace mismatch | Ensure `name` in manifest matches: `.ext.fragment.` | +| Property not found | Wrong property name | Verify property exists in entity metadata | +| Section not appearing | Missing from manifest | Check section registered in correct target settings | + +**Validation checklist:** +- [ ] Fragment file exists at `webapp/ext/fragment/.fragment.xml` +- [ ] Fragment namespace matches app component namespace +- [ ] Property name matches entity metadata +- [ ] Manifest section `name` matches fragment namespace path +- [ ] No compilation errors in fragment or manifest +- [ ] Section appears in Object Page (test in preview) + +## Building Block Reference + +### RichTextEditor + +**Use for:** Formatted text fields (HTML content, memo, description) + +**Basic syntax:** +```xml + +``` + +**With toolbar customization:** +```xml + + + + + +``` + +**Required namespace:** `xmlns:macros="sap.fe.macros"` + +### Table + +**Use for:** Display line items, collections, navigation properties + +**Basic syntax:** +```xml + +``` + +### Chart + +**Use for:** Data visualization from Chart annotations + +**Basic syntax:** +```xml + +``` + +### Field + +**Use for:** Single editable field with label + +**Basic syntax:** +```xml + +``` + +## Tips + +- **Start simple:** Use basic building block syntax first, add configuration later +- **Check examples:** Search MCP docs for complete working examples +- **Use existing sections:** Check annotation.xml for existing UI.Facets to understand section patterns +- **Fragment reuse:** Fragments can be referenced from multiple pages/sections +- **Namespace consistency:** App namespace comes from manifest `sap.app.id` + +## Related Documentation + +When MCP Fiori server is available, search for: +- "building blocks fiori elements" +- "custom section fragment" +- "object page extensions" +- Specific building block name (e.g., "RichTextEditor", "Table macro") + +## Example: Add RichTextEditor for Memo Field + +**Goal:** Add Trip Description section with rich text editor for Memo field + +**Step 1:** Search MCP +``` +Query: "rich text editor building block" +Found: RichTextEditor uses value="{Property}" for data binding +``` + +**Step 2:** Check metadata +```xml + + +``` + +**Step 3:** Create fragment +```xml + + + + +``` + +**Step 4:** Update manifest +```json +"TravelObjectPage": { + "options": { + "settings": { + "contextPath": "/Travel", + "content": { + "body": { + "sections": { + "tripDescriptionSection": { + "name": "travelapp.ext.fragment.TripDescription", + "type": "XMLFragment", + "title": "Trip Description" + } + } + } + } + } + } +} +``` + +**Step 5:** Validate - no errors, section appears as last section on Object Page ✓