Skip to content

Commit 1dceb78

Browse files
msmygitMadhavan
andauthored
feat: Introduce CDM Config Builder UI (#422)
* Document original architecture of CDM * Initial version of Config Builder * Add unit tests * Add theme switcher --------- Co-authored-by: Madhavan <cxo@ibm.com>
1 parent b398e98 commit 1dceb78

31 files changed

+8612
-1
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ spark-submit --properties-file cdm.properties \
175175
# Things to know
176176

177177
> [!TIP]
178-
> If you want to pass in additional [Cassandra Java Driver configs](https://github.com/apache/cassandra-java-driver/blob/4.x/core/src/main/resources/reference.conf), you can leverage it as below
178+
> If you want to pass in additional [Cassandra Java Driver configs](https://github.com/apache/cassandra-java-driver/blob/4.x/core/src/main/resources/reference.conf), you can pass in
179179
> `--conf spark.driver.extraJavaOptions="-Ddatastax-java-driver.advanced.connection.pool.remote.size=5`
180180
181181
> [!TIP]

cdm-config-builder/.gitignore

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
node_modules/
2+
dist/
3+
coverage/
4+
.DS_Store
5+
*.local
6+
7+
# ESLint cache
8+
.eslintcache

cdm-config-builder/.prettierignore

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Dependencies
2+
node_modules/
3+
4+
# Build output
5+
dist/
6+
build/
7+
8+
# Coverage reports
9+
coverage/
10+
11+
# Package files
12+
package-lock.json
13+
14+
# Config files
15+
.eslintrc.cjs
16+
vite.config.js
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"semi": true,
3+
"trailingComma": "es5",
4+
"singleQuote": true,
5+
"printWidth": 100,
6+
"tabWidth": 2,
7+
"useTabs": false,
8+
"arrowParens": "always",
9+
"endOfLine": "lf"
10+
}

cdm-config-builder/README.md

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
# CDM Config Builder
2+
3+
A React application using the [IBM Carbon Design System](https://carbondesignsystem.com/) that provides a user-friendly interface for generating [`cdm.properties`](../src/resources/cdm.properties) configuration files for the [Cassandra Data Migrator (CDM)](https://github.com/datastax/cassandra-data-migrator).
4+
5+
## Features
6+
7+
- **Schema-aware configuration** — paste CQL `CREATE TABLE` statements and the app parses keyspace/table names, primary keys, clustering keys, and column types automatically
8+
- **Best-practices engine** — applies CDM performance recommendations based on estimated row count, table size, and data types present
9+
- **Advanced features** — configure ExplodeMap, ConstantColumns, and ExtractJson transformations via guided form fields
10+
- **Live preview** — the generated `cdm.properties` file updates in real time as you fill out the form
11+
- **Inline comments** — every generated property includes an explanation of why it was set to that value
12+
- **Download & Copy** — save the file as `cdm.properties` or copy to clipboard with one click
13+
- **Dark / Light theme** — toggle between themes via the header button; preference is persisted in `localStorage` and respects the OS `prefers-color-scheme` setting
14+
15+
## Prerequisites
16+
17+
- **Node.js** 18+ (LTS recommended)
18+
- **npm** 9+
19+
20+
## Getting Started
21+
22+
```bash
23+
# From the repository root
24+
cd cdm-config-builder
25+
26+
# Install dependencies
27+
npm install
28+
29+
# Start the development server
30+
npm run dev
31+
```
32+
33+
The app will be available at **http://localhost:5173** (or the next available port).
34+
35+
## Build for Production
36+
37+
```bash
38+
npm run build
39+
# Output is in cdm-config-builder/dist/
40+
```
41+
42+
To preview the production build locally:
43+
44+
```bash
45+
npm run preview
46+
```
47+
48+
## Project Structure
49+
50+
```
51+
cdm-config-builder/
52+
├── index.html # Anti-FOUC theme script + React mount point
53+
├── package.json
54+
├── vite.config.js
55+
├── README.md
56+
└── src/
57+
├── main.jsx # React entry point
58+
├── App.jsx # Root component, form state, layout
59+
├── App.scss # Carbon + custom styles + CSS theme tokens
60+
├── context/
61+
│ └── ThemeContext.jsx # ThemeProvider + useTheme hook (localStorage, prefers-color-scheme)
62+
├── components/
63+
│ ├── FormSection.jsx # Reusable Carbon Tile section wrapper
64+
│ ├── SchemaSection.jsx # CQL CREATE TABLE inputs
65+
│ ├── ConnectionSection.jsx # Origin/target host, port, SCB, credentials
66+
│ ├── PerformanceHintsSection.jsx # Row count, table size, data types, toggles
67+
│ ├── AdvancedFeaturesSection.jsx # ExplodeMap, ConstantColumns, ExtractJson
68+
│ ├── PropertiesPreview.jsx # Live preview panel + Download/Copy buttons
69+
│ └── ThemeToggleButton.jsx # Sun/Moon SVG icons for the header theme toggle
70+
└── utils/
71+
│ ├── parseCqlSchema.js # CQL DDL parser
72+
│ ├── bestPracticesRules.js # Performance tuning rules engine
73+
│ └── generateProperties.js # cdm.properties file generator
74+
└── test/
75+
│ ├── theme.test.jsx # ThemeContext + icon component tests
76+
│ ├── ConnectionSection.test.jsx
77+
│ ├── bestPracticesRules.test.js
78+
│ ├── generateProperties.test.js
79+
│ ├── parseCqlSchema.test.js
80+
│ └── setup.js
81+
```
82+
83+
## How It Works
84+
85+
### 1. Schema Parsing
86+
Paste a full `CREATE TABLE` statement (including keyspace name and `CLUSTERING ORDER BY`) into the **Origin** or **Target** schema fields. The parser extracts:
87+
- Keyspace and table name → sets `spark.cdm.schema.origin.keyspaceTable`
88+
- Partition and clustering key columns → informs `batchSize` recommendations
89+
- Column types → detects BLOBs, counters, collections, UDTs, timestamps
90+
91+
### 2. Best Practices Engine
92+
The rules engine (`bestPracticesRules.js`) evaluates your inputs and applies CDM best practices:
93+
94+
| Input | Effect |
95+
|-------|--------|
96+
| Table size (GB) | Calculates `numParts` = size × 1024 ÷ 10MB per part |
97+
| Row count > 100M | Increases `numParts` to ≥ 50,000 |
98+
| LOBs present | Sets `batchSize=1`, reduces `fetchSizeInRows` to 100 |
99+
| PK = partition key | Sets `batchSize=1` (no clustering, each row is its own partition) |
100+
| Collections-only non-PK | Enables `ttlwritetime.calc.useCollections=true` |
101+
| Counter table | Adds warning comment for `autocorrect.missing.counter` |
102+
| Table > 1TB | Adds Spark cluster recommendation comment |
103+
104+
### 3. Generated Properties
105+
The output includes all standard CDM properties with:
106+
- Inline `#` comments explaining each value
107+
- Commented-out optional properties for easy reference
108+
- Sections matching the structure of `cdm-detailed.properties`
109+
110+
## CDM Reference
111+
112+
- [CDM Properties Reference](../src/resources/cdm-detailed.properties)
113+
- [CDM README](../README.md)
114+
- [CDM GitHub](https://github.com/datastax/cassandra-data-migrator)
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import js from '@eslint/js';
2+
import react from 'eslint-plugin-react';
3+
import reactHooks from 'eslint-plugin-react-hooks';
4+
import reactRefresh from 'eslint-plugin-react-refresh';
5+
import globals from 'globals';
6+
7+
export default [
8+
{
9+
ignores: ['dist/**', 'node_modules/**', '.eslintcache'],
10+
},
11+
js.configs.recommended,
12+
{
13+
files: ['**/*.{js,jsx}'],
14+
languageOptions: {
15+
ecmaVersion: 2021,
16+
sourceType: 'module',
17+
globals: {
18+
...globals.browser,
19+
...globals.es2020,
20+
...globals.node,
21+
},
22+
parserOptions: {
23+
ecmaFeatures: {
24+
jsx: true,
25+
},
26+
},
27+
},
28+
plugins: {
29+
react,
30+
'react-hooks': reactHooks,
31+
'react-refresh': reactRefresh,
32+
},
33+
rules: {
34+
...react.configs.recommended.rules,
35+
...react.configs['jsx-runtime'].rules,
36+
...reactHooks.configs.recommended.rules,
37+
'react-refresh/only-export-components': [
38+
'warn',
39+
{ allowConstantExport: true, allowExportNames: ['useTheme'] },
40+
],
41+
'react/prop-types': 'off',
42+
'no-unused-vars': [
43+
'warn',
44+
{
45+
argsIgnorePattern: '^_',
46+
varsIgnorePattern: '^_',
47+
},
48+
],
49+
'react/jsx-uses-react': 'off',
50+
'react/react-in-jsx-scope': 'off',
51+
},
52+
settings: {
53+
react: {
54+
version: '18.3',
55+
},
56+
},
57+
},
58+
];

cdm-config-builder/index.html

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+
<title>CDM Config Builder</title>
7+
<!-- Anti-FOUC: apply theme before React hydrates to prevent flash -->
8+
<script>
9+
(function () {
10+
var stored = localStorage.getItem('cdm-theme');
11+
var preferred = window.matchMedia('(prefers-color-scheme: dark)').matches
12+
? 'dark'
13+
: 'light';
14+
document.documentElement.dataset.theme = stored || preferred;
15+
})();
16+
</script>
17+
</head>
18+
<body>
19+
<div id="root"></div>
20+
<script type="module" src="/src/main.jsx"></script>
21+
</body>
22+
</html>

0 commit comments

Comments
 (0)