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,

  1. In your running Liferay instance, sign in as the Clarity Admin user.

    • Username: admin@clarityvisionsolutions.com
    • Password: learn
  2. Open the Site Menu (Site Menu) and go to the Page Tree.

  3. Click Distributors Tickets Report and examine the current default visualization for Clarity’s tickets.Click Distributors Tickets Report and examine the current default visualization for Clarity’s tickets.

  4. Next, open a file explorer and go to the client-extensions/ directory in your course workspace.

  5. Create a new folder named clarity-renderer-ticket-highlight.

  6. 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
  7. 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
  8. Add this text to client-extension.dev.yaml and save the file:

    clarity-renderer-ticket-highlight:
        baseURL: http://localhost:3000
        url: index.js
  9. 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"
    }
  10. 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/**/*"
    	]
    }
  11. 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,
    		}),
    	],
    };
  12. In the clarity-renderer-ticket-highlight/ folder, create a new folder named src.

  13. In the src/ folder, create a new file named index.ts.

  14. 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.

  15. Open a terminal and navigate to the client-extensions/clarity-renderer-ticket-highlight/ project folder in your course workspace.

  16. Run this command to build and deploy the client extension:

    blade gw clean deploy
  17. 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]
  18. Return to the Clarity website in your running Liferay instance.

  19. Open the Global Menu (Global Menu), go to the Control Panel tab, and click Data Sets.

  20. Click Clarity Distributors Tickets Report and then go to the Visualization Modes tab.

  21. Click Actions (Actions) for the dateCreated field and select Edit.Click Actions for the dateCreated field and select Edit.  ​

  22. For Renderer, select Clarity Renderer Ticket Highlight and click Save.

  23. Return to the Distributors Tickets Report page and confirm that all tickets older than 30 days are now highlighted in red.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,

  1. Open a file explorer and go to the client-extensions/ directory in your course workspace.

  2. Create a new folder named clarity-renderer-notification-button.

  3. 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
  4. 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
  5. Add this text to client-extension.dev.yaml and save the file:

    clarity-renderer-notification-button:
        baseURL: http://localhost:3000
        url: index.js
  6. 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"
    }
  7. 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/**/*"
    	]
    }
  8. 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,
    		}),
    	],
    };
  9. In the clarity-renderer-notification-button/ folder, create a new folder named src.

  10. In the src/ folder, create a new file named index.ts.

  11. 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.

  12. Open a terminal and navigate to the client-extensions/clarity-renderer-notification-button/ project folder in your course workspace.

  13. Run this command to build and deploy the client extension:

    blade gw clean deploy
  14. 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]
  15. Return to the Clarity website in your running Liferay instance.

  16. Open the Global Menu (Global Menu), go to the Control Panel tab, and click Data Sets

  17. Click Clarity Distributors Tickets Report and go to the Visualization Modes tab.

  18. Click Actions (Actions) for the ID field and select Edit.

  19. Enter Notifications for Label, select Clarity Renderer Notification Button for Renderer, and click Save.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 (Global Menu) -> Control Panel -> Notification -> Templates -> Ticket Needs Attention.

  20. Open the Site Menu (Site Menu) and go to the Page Tree.

  21. Click the Distributors Tickets Report page.

  22. Click the notification button for one of the support tickets. Confirm that the success message displays on the screen.Confirm that the success message displays on the screen after clicking the button.

  23. To verify that the notification has reached the desired user, log in as Ian Miller:

    • Username: ian.miller@clarityvisionsolutions.com
    • Password: learn
  24. 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.

Loading Knowledge

Capabilities

Product

Education

Contact Us

Connect

Powered by Liferay
© 2024 Liferay Inc. All Rights Reserved • Privacy Policy