Improving Visibility for Clarity's Support Tickets
Frontend data sets (FDS) are a powerful tool for rendering data in your websites and applications. With the FDS cell renderer client extension, you can go beyond default presentation options by injecting custom UI components and logic directly into data cells. Clarity’s development team wants to enhance the user experience of their ticketing dashboard with dynamic styling and custom interactions.
In these exercises, you’ll implement two FDS cell renderer client extensions to empower Clarity administrators with actionable, visually engaging ticket reports.
Exercise: Changing a Data Set’s Cell Presentation
Here, you’ll create an FDS cell renderer client extension to highlight tickets in red if they are more than thirty days old. This color change will provide Clarity administrators with an immediate visual cue to identify and prioritize older unresolved tickets.
To do this,
-
In your running Liferay instance, sign in as the Clarity Admin user.
- Username:
admin@clarityvisionsolutions.com
- Password:
learn
- Username:
-
Open the Site Menu (
) and go to the Page Tree. -
Click Distributors Tickets Report and examine the current default visualization for Clarity’s tickets.
-
Next, open a file explorer and go to the
client-extensions/
directory in your course workspace. -
Create a new folder named
clarity-renderer-ticket-highlight
. -
In the
clarity-renderer-ticket-highlight/
folder, create the following files:client-extension.yaml
client-extension.dev.yaml
package.json
tsconfig.json
webpack.config.js
-
Add this text to
client-extension.yaml
and save the file:assemble: - from: build/static into: static clarity-renderer-ticket-highlight: name: Clarity Renderer Ticket Highlight type: fdsCellRenderer url: index.*.js
-
Add this text to
client-extension.dev.yaml
and save the file:clarity-renderer-ticket-highlight: baseURL: http://localhost:3000 url: index.js
-
Add this text to
package.json
and save the file:{ "dependencies": { "@liferay/js-api": "0.6.0" }, "description": "Clarity Renderer Ticket Highlight", "devDependencies": { "ts-loader": "9.5.1", "typescript": "^5.0.4", "webpack": "5.90.1", "webpack-cli": "5.1.4", "webpack-dev-server": "4.15.1" }, "name": "@liferay/clarity-renderer-ticket-highlight", "scripts": { "build": "webpack", "start": "webpack serve", "watch": "tsc --watch" }, "version": "0.0.0" }
-
Add this text to
tsconfig.json
and save the file:{ "compilerOptions": { "esModuleInterop": true, "jsx": "react", "lib": [ "DOM", "ES2020" ], "module": "ES2020", "moduleResolution": "node", "outDir": "./build", "resolveJsonModule": true, "sourceMap": false, "target": "ES2020", "types": [ ] }, "include": [ "./src/**/*" ] }
-
Add this code to
webpack.config.js
and save the file:/** * SPDX-FileCopyrightText: (c) 2000 Liferay, Inc. https://liferay.com * SPDX-License-Identifier: LGPL-2.1-or-later OR LicenseRef-Liferay-DXP-EULA-2.0.0-2023-06 */ const path = require('path'); const webpack = require('webpack'); const DEVELOPMENT = process.env.NODE_ENV === 'development'; const WEBPACK_SERVE = !!process.env.WEBPACK_SERVE; module.exports = { devServer: { headers: { 'Access-Control-Allow-Origin': '*', }, port: 3000, }, devtool: DEVELOPMENT ? 'source-map' : false, entry: { index: './src/index.ts', }, experiments: { outputModule: true, }, mode: DEVELOPMENT ? 'development' : 'production', module: { rules: [ { test: /\.ts$/i, use: ['ts-loader'], }, ], }, optimization: { minimize: !DEVELOPMENT, }, output: { clean: true, environment: { dynamicImport: true, module: true, }, filename: WEBPACK_SERVE ? '[name].js' : '[name].[contenthash].js', library: { type: 'module', }, path: path.resolve('build', 'static'), }, plugins: [ new webpack.optimize.LimitChunkCountPlugin({ maxChunks: 1, }), ], };
-
In the
clarity-renderer-ticket-highlight/
folder, create a new folder namedsrc
. -
In the
src/
folder, create a new file namedindex.ts
. -
Add this code to
index.ts
and save the file:import type {FDSTableCellHTMLElementBuilder} from '@liferay/js-api/data-set'; const fdsCellRenderer: FDSTableCellHTMLElementBuilder = ({value}) => { const element = document.createElement('div'); const rawDate = String(value); const cellDate = new Date(rawDate); if (!isNaN(cellDate.getTime())) { const now = new Date(); const thirtyDaysAgo = new Date(); thirtyDaysAgo.setDate(now.getDate() - 30); if (cellDate < thirtyDaysAgo) { element.style.backgroundColor = 'rgba(255, 0, 0, 0.2)'; element.`${cellDate.toLocaleDateString()} - OLD`; } else { element.cellDate.toLocaleDateString(); } } else { element.'Invalid Date'; } return element; }; export default fdsCellRenderer;
Note that lines 9-22 set the condition for the red highlight.
-
Open a terminal and navigate to the
client-extensions/clarity-renderer-ticket-highlight/
project folder in your course workspace. -
Run this command to build and deploy the client extension:
blade gw clean deploy
-
Verify it deploys successfully.
2025-06-03 14:08:34.676 INFO [fileinstall-directory-watcher][BundleStartStopLogger:68] STARTED clarity-renderer-ticket-highlight_7.4.13 [1463]
-
Return to the Clarity website in your running Liferay instance.
-
Open the Global Menu (
), go to the Control Panel tab, and click Data Sets. -
Click Clarity Distributors Tickets Report and then go to the Visualization Modes tab.
-
Click Actions (
) for the dateCreated field and select Edit. -
For Renderer, select Clarity Renderer Ticket Highlight and click Save.
-
Return to the Distributors Tickets Report page and confirm that all tickets older than 30 days are now highlighted in red.
Now Clarity administrators can more easily identify old tickets.
Exercise: Rendering ID Cells as Buttons
In this exercise, you’ll implement an FDS cell renderer client extension to change the ID field of a ticket into a button that will notify users when clicked. This can help Clarity improve visibility and response time for support tickets.
To do this,
-
Open a file explorer and go to the
client-extensions/
directory in your course workspace. -
Create a new folder named
clarity-renderer-notification-button
. -
In the
clarity-renderer-notification-button/
folder, create the following files:client-extension.yaml
client-extension.dev.yaml
package.json
tsconfig.json
webpack.config.js
-
Add this text to
client-extension.yaml
and save the file:assemble: - from: build/static into: static clarity-renderer-notification-button: name: Clarity Renderer Notification Button type: fdsCellRenderer url: index.*.js
-
Add this text to
client-extension.dev.yaml
and save the file:clarity-renderer-notification-button: baseURL: http://localhost:3000 url: index.js
-
Add this text to
package.json
and save the file:{ "dependencies": { "@liferay/js-api": "0.6.0" }, "description": "Clarity Renderer Notification Button", "devDependencies": { "ts-loader": "9.5.1", "typescript": "^5.0.4", "webpack": "5.90.1", "webpack-cli": "5.1.4", "webpack-dev-server": "4.15.1" }, "name": "@liferay/clarity-renderer-notification-button", "scripts": { "build": "webpack", "start": "webpack serve", "watch": "tsc --watch" }, "version": "0.0.0" }
-
Add this text to
tsconfig.json
and save the file:{ "compilerOptions": { "esModuleInterop": true, "jsx": "react", "lib": [ "DOM", "ES2020" ], "module": "ES2020", "moduleResolution": "node", "outDir": "./build", "resolveJsonModule": true, "sourceMap": false, "target": "ES2020", "types": [ ] }, "include": [ "./src/**/*" ] }
-
Add this code to
webpack.config.js
and save the file:/** * SPDX-FileCopyrightText: (c) 2000 Liferay, Inc. https://liferay.com * SPDX-License-Identifier: LGPL-2.1-or-later OR LicenseRef-Liferay-DXP-EULA-2.0.0-2023-06 */ const path = require('path'); const webpack = require('webpack'); const DEVELOPMENT = process.env.NODE_ENV === 'development'; const WEBPACK_SERVE = !!process.env.WEBPACK_SERVE; module.exports = { devServer: { headers: { 'Access-Control-Allow-Origin': '*', }, port: 3000, }, devtool: DEVELOPMENT ? 'source-map' : false, entry: { index: './src/index.ts', }, experiments: { outputModule: true, }, mode: DEVELOPMENT ? 'development' : 'production', module: { rules: [ { test: /\.ts$/i, use: ['ts-loader'], }, ], }, optimization: { minimize: !DEVELOPMENT, }, output: { clean: true, environment: { dynamicImport: true, module: true, }, filename: WEBPACK_SERVE ? '[name].js' : '[name].[contenthash].js', library: { type: 'module', }, path: path.resolve('build', 'static'), }, plugins: [ new webpack.optimize.LimitChunkCountPlugin({ maxChunks: 1, }), ], };
-
In the
clarity-renderer-notification-button/
folder, create a new folder namedsrc
. -
In the
src/
folder, create a new file namedindex.ts
. -
Add this code to
index.ts
and save the file:import type {FDSTableCellHTMLElementBuilder} from '@liferay/js-api/data-set'; declare const Liferay: any; const fdsCellRenderer: FDSTableCellHTMLElementBuilder = ({value}) => { const element = document.createElement('div'); if (typeof value !== 'number') { element.'Invalid ID'; return element; } const ticketId = value; const button = document.createElement('button'); button.textContent = 'Notify'; button.className = 'btn btn-sm btn-primary'; button.addEventListener('click', async () => { try { const response = await Liferay.Util.fetch( `/o/c/tickets/${ticketId}/object-actions/ticketRequiresAttention`, { method: 'PUT', headers: { 'Content-Type': 'application/json', Accept: 'application/json', }, } ); if (response.ok) { Liferay.Util.openToast({ message: 'Notification successfully sent!', title: 'Success', type: 'success', }); } else { const errorText = await response.text(); Liferay.Util.openToast({ message: `Error when sending notification: ${errorText}`, title: 'Error', type: 'danger', }); } } catch (error) { Liferay.Util.openToast({ message: `Unexpected error: ${error}`, title: 'Error', type: 'danger', }); } }); element.appendChild(button); return element; }; export default fdsCellRenderer;
This code replaces the ID field with a notification button.
-
Open a terminal and navigate to the
client-extensions/clarity-renderer-notification-button/
project folder in your course workspace. -
Run this command to build and deploy the client extension:
blade gw clean deploy
-
Verify it deploys successfully.
2025-06-03 14:08:34.676 INFO [fileinstall-directory-watcher][BundleStartStopLogger:68] STARTED clarity-renderer-notification-button_7.4.13 [1463]
-
Return to the Clarity website in your running Liferay instance.
-
Open the Global Menu (
), go to the Control Panel tab, and click Data Sets -
Click Clarity Distributors Tickets Report and go to the Visualization Modes tab.
-
Click Actions (
) for the ID field and select Edit. -
Enter
Notifications
for Label, select Clarity Renderer Notification Button for Renderer, and click Save.
Note that the notification template used for the button’s action is already configured for your data set. You can see it by navigating to Global Menu ( ) -> Control Panel -> Notification -> Templates -> Ticket Needs Attention. -
Open the Site Menu (
) and go to the Page Tree. -
Click the Distributors Tickets Report page.
-
Click the notification button for one of the support tickets. Confirm that the success message displays on the screen.
-
To verify that the notification has reached the desired user, log in as Ian Miller:
- Username:
ian.miller@clarityvisionsolutions.com
- Password:
learn
- Username:
-
Click on your profile picture and then click Notifications. Confirm that the latest notification says “This ticket requires attention.”
Now Clarity’s administrators have an efficient method for notifying the appropriate employees about a ticket that requires attention.
Conclusion
Great! You’ve implemented frontend data set cell renderer client extensions to enrich the user experience in Clarity’s ticketing system for administrators, developers, and partners. With these client extensions, you can tailor your data-driven applications to specific user needs with fine-grain control over individual data cells.
Next, you’ll learn more about caching as it relates to frontend client extensions.
Capabilities
Product
Education
Contact Us