-
Notifications
You must be signed in to change notification settings - Fork 24
Description
Overview
Implement a new content block (ProductListBlock) that renders a configurable list of products with support for both grid and table views. The block should leverage the existing products and cms modules, and strictly follow the documented conventions for structure and customization.
Requirements
1. Block Generation
- Use the block generator to scaffold the initial structure
- Run
npm run generateat the project root and select the "block" generator - Provide the block name:
product-listorProductList - Reference: Using Generators
- Run
The generator will create the following structure in packages/blocks/product-list/:
- API Harmonization layer (module, controller, service, mapper, model, request)
- Frontend layer (server component, client component, renderer, typings, API methods)
- SDK layer
2. Integration with Products Module
-
Reuse existing product data from the
productsmodule- Reference:
packages/framework/src/modules/products/products.model.tsfor the base Product model - Reference:
packages/integrations/mocked/src/modules/products/products.mapper.tsfor mocked data - Reference:
packages/framework/src/modules/products/products.request.tsfor request query types
- Reference:
-
Add the Products module as a dependency to your block:
- Edit
packages/blocks/product-list/src/api-harmonization/product-list.module.ts - Add
Products.Serviceto the providers array - Reference implementation: Creating the harmonizing block - Declaring dependencies
- Edit
-
Add new fields to the base Product model if necessary
- Extend in
packages/framework/src/modules/products/products.model.ts - Consider fields like
stock,rating,availability, etc.
- Extend in
3. CMS Model Extension and Mocked Data
The block generator automatically creates the base CMS model in the framework. You need to:
1. Extend the generated framework CMS model (automatically created by the generator):
- Reference:
packages/framework/src/modules/cms/models/blocks/product-list.model.ts- This file is automatically generated when you use the block generator
- It's already exported in
packages/framework/src/modules/cms/cms.model.ts - Add fields for titles, labels, filter configurations, pagination settings, view toggle labels
- Reference existing models like
ResourceListBlockorTicketListBlockfor guidance
2. Add mocked data in the mocked integration:
- Create a mapper file:
packages/integrations/mocked/src/modules/cms/mappers/blocks/cms.product-list.mapper.ts - Import and add the mapper in
packages/integrations/mocked/src/modules/cms/cms.service.ts - Reference existing mapper:
cms.resource-list.mapper.ts
4. Standard Filters and Pagination
- Implement filters and pagination following existing patterns:
Filter types should include:
- Category
- Price range
- Availability
- Tags
5. Grid and Table View Toggle
- Implement a view toggle component to switch between grid and table layouts
- Use the existing
Togglecomponent:packages/ui/src/elements/toggle.tsx - Create two rendering modes:
- Grid view: Use
ProductCardcomponent frompackages/ui/src/components/Cards/ProductCard/ProductCard.tsx- Reference:
packages/blocks/service-list/src/frontend/ServiceList.client.tsxfor grid layout pattern
- Reference:
- Table view: Use
DataListcomponent frompackages/ui/src/components/DataList/DataList.tsx- Reference:
packages/blocks/ticket-list/src/frontend/TicketList.client.tsxfor table layout pattern
- Reference:
- Grid view: Use
- These components might need to be extended with additional items if necessary
- Check our Storybook for examples of usage of components
6. Design Reference
- Follow examples from shadcn-ui-blocks for inspiration:
- Note: Similar aesthetic but does not need to be an exact match, it's enough that it matches the overall app design and "looks nice"; we will adjust it later if necessary
7. UI Library Integration
- Reuse existing shadcn/ui components from the UI library
- Located in
packages/ui/src/
- Located in
- Install additional shadcn/ui components if needed:
- Use the shadcn/ui CLI to add new components to
packages/ui/src/elements/ - Example:
npx shadcn@latest add [component-name]
- Use the shadcn/ui CLI to add new components to
8. Reusable Components
- Place any new reusable React components in the UI library:
packages/ui/src/components/ - Follow the existing pattern for component exports and structure
9. Accessibility and SEO
- Ensure semantic HTML structure
- Add proper ARIA labels and roles for interactive elements
- Use proper heading hierarchy (h1 β h2 β h3)
- Include
alttext for all images - Use proper link semantics and keyboard navigation
- Ensure color contrast meets WCAG standards
- Add meta descriptions and structured data if applicable
Implementation Steps
- Generate the block structure using the generator (this automatically creates the framework CMS model)
- Extend framework CMS model and add mocked data:
- Extend the generated framework CMS model with required fields
- Create a mapper for mocked data in the mocked integration
- Add the mapper service method
- Implement API harmonization layer:
- Declare dependencies (CMS, Products)
- Define data models
- Fetch and aggregate data
- Map responses to normalized format
- Reference: Creating the harmonizing block
- Implement frontend layer:
- Create server component for data fetching
- Create client component with view toggle
- Implement grid and table rendering
- Add filters and pagination
- Reference: Creating the frontend block
- Register the block:
- Add to
apps/frontend/src/blocks/renderBlocks.tsx - Add to block type definitions in
apps/api-harmonization/src/modules/page/page.model.ts - Reference: Creating the frontend block
- Add to
- Test the implementation:
- API testing:
http://localhost:3001/api/blocks/product-list - Frontend testing: Add block to a page in the CMS
- API testing:
Adding the ProductListBlock to a CMS Page in Mocked Integration
To add the ProductListBlock to a new "Products" page in the mocked integration with support for EN/DE/PL locales, follow these steps:
1. Create a New Page Definition File
Create a new file at packages/integrations/mocked/src/modules/cms/mappers/mocks/pages/product-list.page.ts that defines the page for all three locales (EN, DE, PL).
For an example of how to structure this file, refer to:
Your page definition should:
- Use a unique ID (e.g., '20')
- Define slugs for each locale ('/products', '/produkte', '/produkty')
- Include appropriate SEO information for each language
- Set permissions to [Auth.Constants.Roles.ORG_USER, Auth.Constants.Roles.ORG_ADMIN]
- Use 'OneColumnTemplate' with the ProductListBlock in the main slot
For more information on page structure, see the CMS content model documentation.
Note: When creating mocked content, especially for locales other than English (DE, PL), you can use AI tools to help generate appropriate translations and locale-specific content. This can save time and ensure consistency across different language versions.
2. Update the Page Mapper
Modify the packages/integrations/mocked/src/modules/cms/mappers/cms.page.mapper.ts file to include your new page definitions.
For reference on how to update the page mapper, see:
You'll need to make the following changes:
- Import the new page definitions from your product-list.page.ts file
- Add the new page routes to the
mapPagefunction with cases for each locale's slug ('/products', '/produkte', '/produkty') - Add the new pages to the
getAllPagesfunction for each locale (pl, de, en) - Add the new pages to the
getAlternativePagesfunction
For more information on how the page mapper works, see the Mocked integration documentation.
3. Test the Implementation
After implementing the ProductListBlock and adding the page definitions:
- Start the development server
- Navigate to:
/productsfor English/produktefor German/produktyfor Polish
The page should display the ProductListBlock with the appropriate content for each locale.
Reference Documentation
- Create a new block guide
- Using generators
- Blocks structure
- CMS content model
- Mocked integration
- Block usage
As an additional requirement, please provide a short feedback on your experiences with working with this framework - how easy or difficult it was to get started (including starting the project, getting around the monorepo or readings our docs) and to make the required changes.
This repo is using Opire - what does it mean? π
π΅ Everyone can add rewards for this issue commenting
/reward 100 (replace 100 with the amount).π΅οΈββοΈ If someone starts working on this issue to earn the rewards, they can comment
/try to let everyone know!π And when they open the PR, they can comment
/claim #332 either in the PR description or in a PR's comment.πͺ Also, everyone can tip any user commenting
/tip 20 @marcinkrasowski (replace 20 with the amount, and @marcinkrasowski with the user to tip).π If you want to learn more, check out our documentation.
Metadata
Metadata
Assignees
Labels
Type
Projects
Status