Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Jan 29, 2026

Extends existing AgGrid plugin with metadata-driven variant that auto-fetches object schemas and data from ObjectStack backend, eliminating manual column configuration.

Core Implementation

  • ObjectAgGridImpl.tsx: Fetches metadata via @objectstack/client, generates AG Grid column definitions from field metadata, handles data loading with pagination/filtering/sorting
  • object-aggrid.types.ts: Type definitions for ObjectAgGridSchema and field-to-filter mappings
  • index.tsx: Lazy-loads implementation, registers object-aggrid component type

Field Type Support

Implements renderers and formatters for all 30+ ObjectUI field types:

  • Numeric: currency ($1,234.56), percent (45.5%), number with precision
  • Temporal: date/datetime with locale formatting and validation
  • Interactive: email/phone/url as clickable links (XSS-safe)
  • Visual: color swatches, rating stars, image thumbnails, circular avatars
  • Complex: select (shows labels), lookup (displays referenced names), boolean (✓/✗)

Usage

import { ObjectStackAdapter } from '@object-ui/data-objectstack';
import '@object-ui/plugin-aggrid';

const dataSource = new ObjectStackAdapter({
  baseUrl: 'https://api.example.com',
  token: 'auth-token'
});

const schema = {
  type: 'object-aggrid',
  objectName: 'contacts',
  dataSource,
  editable: true,  // Auto-saves to backend
  fieldNames: ['name', 'email', 'phone']  // Optional field selection
};

Security

  • Escapes HTML in cell renderers to prevent XSS
  • Validates dates to prevent "Invalid Date" display
  • Sanitizes all user-controlled values before rendering

Testing

  • Unit tests for component instantiation and schema validation
  • Storybook examples demonstrating field selection, editing, export
  • CodeQL scan: 0 vulnerabilities
Original prompt

继续现有的aggrid控件,进一步开发元数据驱动的object-aggrid,使用@objectstack/client获取元数据和数据,要求支持所有的字段类型


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

@vercel
Copy link

vercel bot commented Jan 29, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
objectui Ready Ready Preview, Comment Jan 29, 2026 4:56pm
objectui-components Ready Ready Preview, Comment Jan 29, 2026 4:56pm
objectui-crm-app Error Error Jan 29, 2026 4:56pm

Request Review

Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
Copilot AI and others added 3 commits January 29, 2026 16:45
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
Copilot AI changed the title [WIP] Add object-aggrid support for metadata-driven fields Add metadata-driven ObjectAgGrid with @objectstack/client integration Jan 29, 2026
Copilot AI requested a review from hotlong January 29, 2026 16:52
@hotlong hotlong marked this pull request as ready for review January 29, 2026 17:09
Copilot AI review requested due to automatic review settings January 29, 2026 17:09
@hotlong hotlong merged commit 85b272a into main Jan 29, 2026
7 of 8 checks passed
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a metadata‑driven object-aggrid plugin that uses the shared DataSource abstraction (and @object-ui/data-objectstack) to auto-generate AG Grid columns from ObjectStack object schemas and load data without manual column configuration.

Changes:

  • Introduces ObjectAgGridImpl and associated schema/prop types to fetch object metadata and data via DataSource.getObjectSchema/find, generate AG Grid columnDefs from FieldMetadata, and wire up formatting and editing for many field types.
  • Extends the existing plugin registration in index.tsx to lazily load the new implementation, expose an ObjectAgGridRenderer, and register the object-aggrid component with the ComponentRegistry and design‑time inputs.
  • Adds docs (English and Chinese), Storybook stories, and an example demo to document and showcase the new metadata‑driven grid, along with wiring up the @object-ui/data-objectstack workspace dependency.

Reviewed changes

Copilot reviewed 11 out of 12 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
pnpm-lock.yaml Adds the @object-ui/data-objectstack workspace package to the lockfile so the new adapter dependency resolves correctly.
packages/plugin-aggrid/src/object-aggrid.types.ts Defines ObjectAgGridSchema and ObjectAgGridImplProps plus a field-type → AG Grid filter mapping; note that ColDef is imported but unused.
packages/plugin-aggrid/src/object-aggrid.test.ts Adds basic Vitest tests ensuring ObjectAgGridRenderer is defined and can be invoked with required schema props without throwing.
packages/plugin-aggrid/src/index.tsx Lazily loads ObjectAgGridImpl, defines ObjectAgGridRenderer, adds it to the aggridComponents export, and registers the object-aggrid component and its inputs in ComponentRegistry.
packages/plugin-aggrid/src/ObjectAgGridImpl.tsx Core metadata-driven AG Grid implementation: fetches object schema and data via DataSource, generates columnDefs from FieldMetadata, configures filters, status bar, context menu, export, and inline editing with backend updates; contains a URL handling security issue and some unused imports/any casting.
packages/plugin-aggrid/package.json Declares @object-ui/data-objectstack as a dependency so consumers can use ObjectStackAdapter with object-aggrid.
packages/plugin-aggrid/README.md Adds a full “Object AgGrid” section documenting features, schema API, examples, and field-type formatting behavior.
packages/plugin-aggrid/QUICKSTART.md New quick start for ObjectAgGrid including installation, schema examples, and backend requirements; currently shows SchemaRenderer imported from @object-ui/components, which is inconsistent with other docs that use @object-ui/react.
packages/plugin-aggrid/OBJECT_AGGRID_CN.md Adds comprehensive Chinese-language documentation for ObjectAgGrid, matching the English README content and examples.
packages/components/src/stories-json/object-aggrid.stories.tsx Storybook stories for ObjectAgGrid (contacts/products/basic/field selection/editable/export), using a local createMockDataSource; includes an unused ObjectStackAdapter import.
examples/object-aggrid-demo.tsx Example React demo showing several ObjectAgGrid usage patterns with a mocked data source; imports ObjectStackAdapter but does not use it.
IMPLEMENTATION_SUMMARY.md High-level implementation summary describing the new ObjectAgGrid component, field-type support, security considerations, testing status, and potential future enhancements.
Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

### Step 4: Use in Your Component

```typescript
import { SchemaRenderer } from '@object-ui/components';
Copy link

Copilot AI Jan 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This Quick Start example imports SchemaRenderer from @object-ui/components, whereas other documentation (for example, the CLI app generator at packages/cli/src/utils/app-generator.ts:149) shows SchemaRenderer coming from @object-ui/react. For consistency with the rest of the docs and to match the recommended runtime entry point, consider updating this snippet to import SchemaRenderer from @object-ui/react.

Suggested change
import { SchemaRenderer } from '@object-ui/components';
import { SchemaRenderer } from '@object-ui/react';

Copilot uses AI. Check for mistakes.
Comment on lines +515 to +520
case 'url':
colDef.cellRenderer = (params: any) => {
if (!params.value) return '';
const escaped = escapeHtml(params.value);
return `<a href="${escaped}" target="_blank" rel="noopener noreferrer" class="text-blue-600 hover:underline">${escaped}</a>`;
};
Copy link

Copilot AI Jan 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The url cell renderer builds an <a> tag directly from params.value and only applies escapeHtml to it, which does not prevent javascript: or other dangerous URL schemes from being used in href; this means a malicious value like "javascript:alert(1)" would still produce a clickable XSS vector. To avoid this, validate and whitelist allowed protocols (e.g. http/https) before using the value in href, and fall back to rendering plain text or a safe placeholder when the URL scheme is not allowed.

Copilot uses AI. Check for mistakes.
Comment on lines +79 to +81
// Fetch object schema/metadata
const schema = await (dataSource as any).getObjectSchema(objectName);
setObjectSchema(schema);
Copy link

Copilot AI Jan 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getObjectSchema is invoked via (dataSource as any) even though DataSource in @object-ui/types already declares this method, which unnecessarily discards type safety and deviates from how other components (e.g. packages/plugin-grid/src/ObjectGrid.tsx:166) call dataSource.getObjectSchema directly. You can rely on the typed DataSource interface here (or narrow the prop type if needed) instead of casting to any, so that incorrect data sources are caught at compile time rather than at runtime.

Copilot uses AI. Check for mistakes.
Comment on lines +20 to +22
MenuItemDef,
IServerSideDatasource,
IServerSideGetRowsParams
Copy link

Copilot AI Jan 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IServerSideDatasource and IServerSideGetRowsParams are imported from ag-grid-community but never used, which adds noise and can cause linting issues. Please remove these unused imports or wire them into an actual server-side row model implementation if that work is planned.

Suggested change
MenuItemDef,
IServerSideDatasource,
IServerSideGetRowsParams
MenuItemDef

Copilot uses AI. Check for mistakes.
* LICENSE file in the root directory of this source tree.
*/

import type { ColDef } from 'ag-grid-community';
Copy link

Copilot AI Jan 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ColDef is imported from ag-grid-community but not used in this file, which is unnecessary and can trigger lint warnings. Consider removing this unused import to keep the types module clean.

Suggested change
import type { ColDef } from 'ag-grid-community';

Copilot uses AI. Check for mistakes.
import type { Meta, StoryObj } from '@storybook/react';
import { SchemaRenderer } from '../SchemaRenderer';
import type { BaseSchema } from '@object-ui/types';
import { ObjectStackAdapter } from '@object-ui/data-objectstack';
Copy link

Copilot AI Jan 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ObjectStackAdapter is imported but never used in this Storybook file; the stories rely entirely on the local createMockDataSource helper instead. Dropping this unused import will avoid confusion about whether the stories exercise the real ObjectStack adapter and will keep the story code leaner.

Suggested change
import { ObjectStackAdapter } from '@object-ui/data-objectstack';

Copilot uses AI. Check for mistakes.
*/

import React from 'react';
import { ObjectStackAdapter } from '@object-ui/data-objectstack';
Copy link

Copilot AI Jan 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ObjectStackAdapter is imported at the top of this example but never actually used, since createExampleDataSource returns a hand-rolled mock data source. To reduce confusion for readers and keep the example code tidy, either remove this import or update the example to demonstrate constructing a real ObjectStackAdapter.

Suggested change
import { ObjectStackAdapter } from '@object-ui/data-objectstack';

Copilot uses AI. Check for mistakes.
const [error, setError] = useState<Error | null>(null);
const [objectSchema, setObjectSchema] = useState<ObjectSchemaMetadata | null>(null);
const [rowData, setRowData] = useState<any[]>([]);
const [totalCount, setTotalCount] = useState(0);
Copy link

Copilot AI Jan 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused variable totalCount.

Copilot uses AI. Check for mistakes.
Comment on lines +103 to +108
## Security Improvements

1. **XSS Prevention**: All HTML cell renderers escape user input using `escapeHtml()` function
2. **Date Validation**: Date parsing includes validation to prevent "Invalid Date" display
3. **URL Sanitization**: All URL values are escaped before rendering
4. **Error Handling**: Comprehensive error handling prevents crashes from malformed data
Copy link

Copilot AI Jan 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The implementation behind this section uses an escapeHtml() helper with document.createElement('div').textContent and then interpolates the escaped value directly into HTML attributes inside AG Grid cellRenderer strings (e.g., <a href="mailto:${escaped}">, <img src="${escapedUrl}">). This escaping is only safe for text nodes, not for attribute context; an attacker controlling a field value can inject quotes and additional attributes or javascript: URLs so that the constructed HTML becomes syntactically valid and executes arbitrary script in the browser. To address this, avoid building raw HTML strings for email/URL/phone/color/image/avatar cells (use React elements or framework components instead), or introduce attribute-context-safe encoding and strict URL/CSS whitelisting before inserting untrusted data into HTML attributes.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants