|
1 | | -# Copilot Instructions |
2 | | - |
3 | | -## Internationalization (i18n) |
4 | | - |
5 | | -- Do NOT hardcode user-facing strings. |
6 | | -- ALWAYS use the component i18n keysets. |
7 | | -- For key naming, see `i18n-naming-ruleset.md` in the repo root. |
8 | | - |
9 | 1 | # GitHub Copilot Instructions for YDB Embedded UI |
10 | 2 |
|
11 | | -> **Note**: This file contains project-specific instructions for GitHub Copilot code review and assistance. |
12 | | -> These instructions are derived from AGENTS.md but formatted specifically for Copilot's consumption. |
13 | | -> When updating project conventions, update both AGENTS.md (for human developers) and this file (for Copilot). |
14 | | -
|
15 | | -## Project Overview |
16 | | - |
17 | | -This is a React-based monitoring and management interface for YDB clusters. The codebase follows specific patterns and conventions that must be maintained. |
18 | | - |
19 | | -## Tech Stack Requirements |
20 | | - |
21 | | -- Use React 18.3 with TypeScript 5.x |
22 | | -- Use Redux Toolkit 2.x with RTK Query for state management |
23 | | -- Use Gravity UI (@gravity-ui/uikit) 7.x for UI components |
24 | | -- Use React Router v5 (NOT v6) for routing |
25 | | -- Use Monaco Editor 0.52 for code editing features |
26 | | - |
27 | | -## Critical Bug Prevention Patterns |
28 | | - |
29 | | -### React Performance (MANDATORY) |
30 | | - |
31 | | -- **ALWAYS** use `useMemo` for expensive computations, object/array creation |
32 | | -- **ALWAYS** use `useCallback` for functions in effect dependencies |
33 | | -- **ALWAYS** memoize table columns, filtered data, computed values |
34 | | -- **AVOID** `useEffect` when possible - prefer direct approaches with `useCallback` |
35 | | -- **PREFER** direct event handlers and callbacks over useEffect for user interactions |
36 | | - |
37 | | -```typescript |
38 | | -// ✅ REQUIRED patterns |
39 | | -const displaySegments = useMemo(() => segments.filter((segment) => segment.visible), [segments]); |
40 | | -const handleClick = useCallback(() => { |
41 | | - // logic |
42 | | -}, [dependency]); |
43 | | - |
44 | | -// ✅ PREFER direct callbacks over useEffect |
45 | | -const handleInputChange = useCallback( |
46 | | - (value: string) => { |
47 | | - setSearchTerm(value); |
48 | | - onSearchChange?.(value); |
49 | | - }, |
50 | | - [onSearchChange], |
51 | | -); |
52 | | - |
53 | | -// ❌ AVOID unnecessary useEffect |
54 | | -// useEffect(() => { |
55 | | -// onSearchChange?.(searchTerm); |
56 | | -// }, [searchTerm, onSearchChange]); |
57 | | -``` |
58 | | - |
59 | | -### Memory & Display Safety |
60 | | - |
61 | | -- **ALWAYS** provide fallback values: `Number(value) || 0` |
62 | | -- **NEVER** allow division by zero: `capacity > 0 ? value/capacity : 0` |
63 | | -- **ALWAYS** dispose Monaco Editor: `return () => editor.dispose();` in useEffect |
64 | | - |
65 | | -### Security & Input Validation |
66 | | - |
67 | | -- **NEVER** expose authentication tokens in logs or console |
68 | | -- **ALWAYS** validate user input before processing |
69 | | -- **NEVER** skip error handling for async operations |
70 | | - |
71 | | -## Critical Coding Rules |
72 | | - |
73 | | -### API Architecture |
74 | | - |
75 | | -- NEVER call APIs directly - always use `window.api.module.method()` pattern |
76 | | -- Use RTK Query's `injectEndpoints` pattern for API endpoints |
77 | | -- Wrap `window.api` calls in RTK Query for proper state management |
78 | | - |
79 | | -### Component Patterns |
80 | | - |
81 | | -- Use BEM naming with `cn()` utility: `const b = cn('component-name')` |
82 | | -- Prefix new SCSS root blocks and new `cn()` block names with `ydb-` unless the surrounding feature already has an established local naming convention that must be preserved for compatibility |
83 | | -- Use `PaginatedTable` component for all data tables |
84 | | -- Tables require: columns, fetchData function, and unique tableName |
85 | | -- Use virtual scrolling for large datasets |
86 | | - |
87 | | -### Internationalization (MANDATORY) |
88 | | - |
89 | | -- NEVER hardcode user-facing strings |
90 | | -- ALWAYS create i18n entries in component's `i18n/` folder |
91 | | -- Follow key format: `<context>_<content>` (e.g., `action_save`, `field_name`) |
92 | | -- Register keysets with `registerKeysets()` using unique component name |
93 | | - |
94 | | -### Display Placeholders (MANDATORY) |
95 | | - |
96 | | -- ALWAYS use `EMPTY_DATA_PLACEHOLDER` for empty UI values. Do not hardcode em or en dashes (`—`, `–`) as placeholders. Hyphen `-`/dashes may be used as separators in titles/ranges. Before submitting a PR, grep for `—` and `–` and ensure placeholder usages use `EMPTY_DATA_PLACEHOLDER` from `src/utils/constants.ts`. |
97 | | - |
98 | | -### State Management |
99 | | - |
100 | | -- Use Redux Toolkit with domain-based organization |
101 | | -- NEVER mutate state in RTK Query - return new objects/arrays |
102 | | -- Clear errors on user input in forms |
103 | | -- Always handle loading states in UI |
104 | | - |
105 | | -### UI Components |
106 | | - |
107 | | -- Prefer Gravity UI components over custom implementations |
108 | | -- Use `createToast` for notifications |
109 | | -- Use `ResponseError` component for API errors |
110 | | -- Use `Loader` and `TableSkeleton` for loading states |
111 | | - |
112 | | -### Form Handling |
113 | | - |
114 | | -- Always use controlled components with validation |
115 | | -- Clear errors on user input |
116 | | -- Validate before submission |
117 | | -- Use Gravity UI form components with error states |
118 | | - |
119 | | -### Dialog/Modal Patterns |
120 | | - |
121 | | -- Use `@ebay/nice-modal-react` for complex modals |
122 | | -- Use Gravity UI `Dialog` for simple dialogs |
123 | | -- Always include loading states |
124 | | - |
125 | | -### Type Conventions |
126 | | - |
127 | | -- API types prefixed with 'T' (e.g., `TTenantInfo`, `TClusterInfo`) |
128 | | -- Types located in `src/types/api/` directory |
129 | | - |
130 | | -### Performance Requirements |
131 | | - |
132 | | -- Use React.memo for expensive renders |
133 | | -- Lazy load Monaco Editor |
134 | | -- Batch API requests when possible |
135 | | -- Use virtual scrolling for tables |
| 3 | +Use existing repository patterns and prefer minimal, behavior-preserving changes. |
136 | 4 |
|
137 | | -### Testing Patterns |
| 5 | +## Core Rules |
138 | 6 |
|
139 | | -- Unit tests colocated in `__test__` directories |
140 | | -- E2E tests use Playwright with page objects pattern |
141 | | -- Use CSS class selectors for E2E element selection |
| 7 | +- Do not invent new abstractions when an established local pattern already exists. |
| 8 | +- When changing user-visible behavior, update all connected surfaces, not only the primary component. |
| 9 | +- Keep suggestions consistent with `AGENTS.md`; this file is the short Copilot-specific subset. |
142 | 10 |
|
143 | | -### Navigation (React Router v5) |
| 11 | +## React and TypeScript |
144 | 12 |
|
145 | | -- Use React Router v5 hooks (`useHistory`, `useParams`) |
146 | | -- Always validate route params exist before use |
| 13 | +- Use `import React from 'react'` in TSX and component files; use `import type React from 'react'` when only React types are needed. |
| 14 | +- Use `React.Fragment` instead of fragment shorthand. |
| 15 | +- Use separate top-level `import type`. |
| 16 | +- Do not use `React.FC` for component typing. |
| 17 | +- This repo uses React Router v5, not v6; prefer v5 hooks such as `useHistory` and `useParams`. |
| 18 | +- Avoid unnecessary `useEffect`; prefer direct handlers and derived state when possible. |
| 19 | +- Keep BEM names semantic. Prefix new SCSS root blocks and new `cn()` block names with `ydb-` unless the surrounding feature already uses an established local convention. |
147 | 20 |
|
148 | | -### URL Parameter Management (MANDATORY) |
| 21 | +## API and State |
149 | 22 |
|
150 | | -- **PREFER** `use-query-params` over `redux-location-state` for new development |
151 | | -- **ALWAYS** use Zod schemas for URL parameter validation with fallbacks |
152 | | -- **ALWAYS** use `z.enum([...]).catch(defaultValue)` pattern for safe parsing |
153 | | -- Use custom `QueryParamConfig` objects for encoding/decoding complex parameters |
| 23 | +- Never call APIs directly; use `window.api.module.method()`. |
| 24 | +- RTK Query endpoints must use `injectEndpoints()` and `queryFn`. |
| 25 | +- Clear form errors on user input and always handle loading states. |
154 | 26 |
|
155 | | -```typescript |
156 | | -// ✅ REQUIRED pattern for URL parameters |
157 | | -const sortColumnSchema = z.enum(['column1', 'column2', 'column3']).catch('column1'); |
| 27 | +## Tables and URL Params |
158 | 28 |
|
159 | | -const SortOrderParam: QueryParamConfig<SortOrder[]> = { |
160 | | - encode: (value) => (value ? encodeURIComponent(JSON.stringify(value)) : undefined), |
161 | | - decode: (value) => { |
162 | | - try { |
163 | | - return value ? JSON.parse(decodeURIComponent(value)) : []; |
164 | | - } catch { |
165 | | - return []; |
166 | | - } |
167 | | - }, |
168 | | -}; |
169 | | -``` |
| 29 | +- Prefer `PaginatedTable` for standard virtualized data grids; use specialized table stacks only when the use case requires them. |
| 30 | +- When changing columns, filters, or sorting, also update URL/query-param schema, sort whitelist, persisted or shareable state, drawer or details rendering, i18n keys, and tests. |
| 31 | +- Prefer `use-query-params` over `redux-location-state` for new work. |
| 32 | +- Validate URL params with Zod fallbacks. |
170 | 33 |
|
171 | | -## Common Utilities |
| 34 | +## i18n and Display |
172 | 35 |
|
173 | | -- Formatters: `formatBytes()`, `formatDateTime()` from `src/utils/dataFormatters/` |
174 | | -- Time parsing: utilities in `src/utils/timeParsers/` |
175 | | -- Query utilities: `src/utils/query.ts` for SQL/YQL helpers |
| 36 | +- Never hardcode user-facing strings. |
| 37 | +- Use component keysets and follow `i18n-naming-ruleset.md`. |
| 38 | +- Use `EMPTY_DATA_PLACEHOLDER` for empty UI values. |
| 39 | +- Treat empty strings `''` as missing unless the feature explicitly requires otherwise. |
| 40 | +- Do not format dates or times from unchecked values; guard against `''`, invalid dates, and `NaN`. |
176 | 41 |
|
177 | | -## Development Commands |
| 42 | +## Query Safety and Compatibility |
178 | 43 |
|
179 | | -```bash |
180 | | -npm run lint # Run all linters before committing |
181 | | -npm run typecheck # TypeScript type checking |
182 | | -npm run unused # Find unused code |
183 | | -``` |
| 44 | +- Do not interpolate raw user input into SQL or YQL without escaping. |
| 45 | +- Parenthesize mixed `OR` expressions before combining them with `AND`. |
| 46 | +- When backend field availability differs by YDB version, prefer compatibility-safe query shapes and normalize the response in code. |
184 | 47 |
|
185 | | -## Before Making Changes |
| 48 | +## UI and Styling |
186 | 49 |
|
187 | | -- Run `npm run lint` and `npm run typecheck` before committing |
188 | | -- Follow conventional commit message format |
189 | | -- Use conventional commit format for PR titles with lowercase subjects (e.g., "fix: update api endpoints", "feat: add new component", "chore: update dependencies") |
190 | | -- PR title subjects must be lowercase (no proper nouns, sentence-case, start-case, pascal-case, or upper-case) |
191 | | -- PR title must not exceed 72 characters (keep them concise and descriptive) |
192 | | -- Ensure all user-facing text is internationalized |
193 | | -- Test with a local YDB instance when possible |
| 50 | +- Prefer Gravity UI components over custom implementations. |
| 51 | +- Keep BEM element names semantic; do not reuse narrow names for unrelated content only to share styles. |
| 52 | +- When behavior depends on UI kit defaults and visual hierarchy matters, set the critical prop explicitly. |
194 | 53 |
|
195 | | -## Debugging Helpers |
| 54 | +## CI and Workflow Changes |
196 | 55 |
|
197 | | -- `window.api` - Access API methods in browser console |
198 | | -- `window.ydbEditor` - Monaco editor instance |
199 | | -- Enable request tracing with `DEV_ENABLE_TRACING_FOR_ALL_REQUESTS` |
| 56 | +- Do not introduce unpinned runtime installs of latest tool versions in workflows when compatibility depends on a specific version. |
| 57 | +- Prefer versions derived from `package-lock.json` or `package.json`. |
200 | 58 |
|
201 | | -## Environment Variables |
| 59 | +## Verification Reminders |
202 | 60 |
|
203 | | -- `REACT_APP_BACKEND` - Backend URL for single-cluster mode |
204 | | -- `REACT_APP_META_BACKEND` - Meta backend URL for multi-cluster mode |
205 | | -- `GENERATE_SOURCEMAP` - Set to `false` for production builds |
| 61 | +- For layout bugs, check actual DOM ownership, selector specificity, computed styles, and overflow behavior before explaining the cause. |
| 62 | +- For review suggestions, prefer the latest head and diff and avoid stale PR state assumptions. |
0 commit comments