diff --git a/e2e/share.spec.ts b/e2e/share.spec.ts index 55fe344c..ae0f0cf4 100644 --- a/e2e/share.spec.ts +++ b/e2e/share.spec.ts @@ -18,12 +18,19 @@ test.describe('Share Functionality', () => { const shareButton = page.getByRole('button', { name: 'Share' }); await shareButton.click(); + // Click the Copy button inside the Share Modal + const copyButton = page.getByRole('dialog').getByRole('button', { name: /Copy/i }); + await expect(copyButton).toBeVisible(); + await copyButton.click(); + // Should show success message await expect(page.getByText('Link copied to clipboard')).toBeVisible({ timeout: 5000 }); - // Verify clipboard contains the link with data parameter - const clipboardText = await page.evaluate(() => navigator.clipboard.readText()); - expect(clipboardText).toContain('data='); + // Verify input contains the link with data parameter + const inputLocator = page.getByRole('dialog').locator('input[type="text"]'); + await expect(inputLocator).toBeVisible(); + const inputValue = await inputLocator.inputValue(); + expect(inputValue).toContain('data='); }); test('should load template from shared URL', async ({ page }) => { @@ -33,12 +40,19 @@ test.describe('Share Functionality', () => { const shareButton = page.getByRole('button', { name: 'Share' }); await shareButton.click(); + // Click the Copy button inside the Share Modal + const copyButton = page.getByRole('dialog').getByRole('button', { name: /Copy/i }); + await expect(copyButton).toBeVisible(); + await copyButton.click(); + // Wait for clipboard to be populated await expect(page.getByText('Link copied to clipboard')).toBeVisible({ timeout: 5000 }); - // Get the shareable link from clipboard - const shareableLink = await page.evaluate(() => navigator.clipboard.readText()); - + // Get the shareable link from the modal input directly to avoid clipboard flakiness + const inputLocator = page.getByRole('dialog').locator('input[type="text"]'); + await expect(inputLocator).toBeVisible(); + const shareableLink = await inputLocator.inputValue(); + // Validate that we got a non-empty string expect(shareableLink, 'Shareable link should be a non-empty string').toBeTruthy(); expect(typeof shareableLink, 'Shareable link should be a string').toBe('string'); diff --git a/e2e_test_log.txt b/e2e_test_log.txt new file mode 100644 index 00000000..84f6dba6 --- /dev/null +++ b/e2e_test_log.txt @@ -0,0 +1,51 @@ + +> template_playground@0.0.0 test:e2e +> playwright test + +[WebServer] The CJS build of Vite's Node API is deprecated. See https://vite.dev/guide/troubleshooting.html#vite-cjs-node-api-deprecated for more details. + + +Running 17 tests using 8 workers + +[1/17] [chromium] › e2e/navigation.spec.ts:4:7 › Navigation › should navigate to Learn page +[2/17] [chromium] › e2e/app.spec.ts:4:7 › App Loading › should load the app and display main components +[3/17] [chromium] › e2e/app.spec.ts:46:7 › Dark Mode › should toggle dark mode via Settings modal +[4/17] [chromium] › e2e/app.spec.ts:29:7 › App Loading › should display Preview panel with content +[5/17] [chromium] › e2e/app.spec.ts:19:7 › App Loading › should display editor panels +[6/17] [chromium] › e2e/navigation.spec.ts:53:7 › Navigation › should have external links in navbar +[7/17] [chromium] › e2e/navigation.spec.ts:20:7 › Navigation › should navigate back to playground from Learn page +[8/17] [chromium] › e2e/navigation.spec.ts:35:7 › Navigation › should have Help dropdown menu +[9/17] [chromium] › e2e/share.spec.ts:9:7 › Share Functionality › should have Share button in sidebar +[10/17] [chromium] › e2e/share.spec.ts:14:7 › Share Functionality › should copy shareable link to clipboard on Share click +[11/17] [chromium] › e2e/share.spec.ts:34:7 › Share Functionality › should load template from shared URL +[12/17] [chromium] › e2e/share.spec.ts:83:7 › Share Functionality › should have Start Tour button +[13/17] [chromium] › e2e/share.spec.ts:88:7 › Share Functionality › should have Settings button +[14/17] [chromium] › e2e/template-workflow.spec.ts:9:7 › Template Workflow › should have sample dropdown and change templates +[15/17] [chromium] › e2e/template-workflow.spec.ts:30:7 › Template Workflow › should collapse and expand editor panels +[16/17] [chromium] › e2e/template-workflow.spec.ts:42:7 › Template Workflow › should toggle Editor panel visibility +[17/17] [chromium] › e2e/template-workflow.spec.ts:63:7 › Template Workflow › should toggle Preview panel visibility + 1) [chromium] › e2e/share.spec.ts:34:7 › Share Functionality › should load template from shared URL + + Error: Shareable link should be a non-empty string + + expect(received).toBeTruthy() + + Received: "" + + 51 | + 52 | // Validate that we got a non-empty string + > 53 | expect(shareableLink, 'Shareable link should be a non-empty string').toBeTruthy(); + | ^ + 54 | expect(typeof shareableLink, 'Shareable link should be a string').toBe('string'); + 55 | + 56 | // Parse URL with validation + at /home/beerus1206/Documents/code/githubrepo/template-playground/e2e/share.spec.ts:53:74 + + Error Context: test-results/share-Share-Functionality--d6b00-ad-template-from-shared-URL-chromium/error-context.md + + + 1 failed + [chromium] › e2e/share.spec.ts:34:7 › Share Functionality › should load template from shared URL + 16 passed (37.0s) + + Serving HTML report at http://localhost:9323. Press Ctrl+C to quit. diff --git a/lint_log.txt b/lint_log.txt new file mode 100644 index 00000000..b9e4cc27 --- /dev/null +++ b/lint_log.txt @@ -0,0 +1,192 @@ + +> template_playground@0.0.0 lint +> eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0 + + +/home/beerus1206/Documents/code/githubrepo/template-playground/src/components/AIConfigPopup.tsx + 143:2 error Mixed spaces and tabs no-mixed-spaces-and-tabs + 146:4 error Unexpected lexical declaration in case block no-case-declarations + 149:4 error Unexpected lexical declaration in case block no-case-declarations + 151:4 error Unexpected lexical declaration in case block no-case-declarations + 152:3 error Mixed spaces and tabs no-mixed-spaces-and-tabs + 153:2 error Mixed spaces and tabs no-mixed-spaces-and-tabs + 157:3 error Mixed spaces and tabs no-mixed-spaces-and-tabs + 158:3 error Mixed spaces and tabs no-mixed-spaces-and-tabs + 161:4 error Unexpected lexical declaration in case block no-case-declarations + 161:10 error Unsafe assignment of an `any` value @typescript-eslint/no-unsafe-assignment + 162:44 error Unsafe argument of type `any` assigned to a parameter of type `SetStateAction` @typescript-eslint/no-unsafe-argument + 162:44 error Unsafe member access .data on an `any` value @typescript-eslint/no-unsafe-member-access + 162:44 error Unsafe call of an `any` typed value @typescript-eslint/no-unsafe-call + 162:63 warning Unexpected any. Specify a different type @typescript-eslint/no-explicit-any + 162:71 error Unsafe member access .id on an `any` value @typescript-eslint/no-unsafe-member-access + 162:71 error Unsafe return of an `any` typed value @typescript-eslint/no-unsafe-return + 176:3 error Mixed spaces and tabs no-mixed-spaces-and-tabs + 179:3 error Mixed spaces and tabs no-mixed-spaces-and-tabs + 180:21 error Unsafe assignment of an `any` value @typescript-eslint/no-unsafe-assignment + 181:55 error Unsafe argument of type `any` assigned to a parameter of type `SetStateAction` @typescript-eslint/no-unsafe-argument + 181:55 error Unsafe member access .models on an `any` value @typescript-eslint/no-unsafe-member-access + 181:55 error Unsafe call of an `any` typed value @typescript-eslint/no-unsafe-call + 181:76 warning Unexpected any. Specify a different type @typescript-eslint/no-explicit-any + 181:84 error Unsafe member access .name on an `any` value @typescript-eslint/no-unsafe-member-access + 181:84 error Unsafe return of an `any` typed value @typescript-eslint/no-unsafe-return + 192:3 error Mixed spaces and tabs no-mixed-spaces-and-tabs + 195:3 error Mixed spaces and tabs no-mixed-spaces-and-tabs + 196:21 error Unsafe assignment of an `any` value @typescript-eslint/no-unsafe-assignment + 197:55 error Unsafe argument of type `any` assigned to a parameter of type `SetStateAction` @typescript-eslint/no-unsafe-argument + 197:55 error Unsafe member access .models on an `any` value @typescript-eslint/no-unsafe-member-access + 197:55 error Unsafe call of an `any` typed value @typescript-eslint/no-unsafe-call + 197:76 warning Unexpected any. Specify a different type @typescript-eslint/no-explicit-any + 197:84 error Unsafe member access .name on an `any` value @typescript-eslint/no-unsafe-member-access + 197:84 error Unsafe return of an `any` typed value @typescript-eslint/no-unsafe-return + 208:3 error Mixed spaces and tabs no-mixed-spaces-and-tabs + 211:3 error Mixed spaces and tabs no-mixed-spaces-and-tabs + 212:21 error Unsafe assignment of an `any` value @typescript-eslint/no-unsafe-assignment + 213:55 error Unsafe argument of type `any` assigned to a parameter of type `SetStateAction` @typescript-eslint/no-unsafe-argument + 213:55 error Unsafe member access .models on an `any` value @typescript-eslint/no-unsafe-member-access + 213:55 error Unsafe call of an `any` typed value @typescript-eslint/no-unsafe-call + 213:76 warning Unexpected any. Specify a different type @typescript-eslint/no-explicit-any + 213:84 error Unsafe member access .name on an `any` value @typescript-eslint/no-unsafe-member-access + 213:84 error Unsafe return of an `any` typed value @typescript-eslint/no-unsafe-return + 219:3 error Mixed spaces and tabs no-mixed-spaces-and-tabs + 220:3 error Mixed spaces and tabs no-mixed-spaces-and-tabs + 223:3 error Mixed spaces and tabs no-mixed-spaces-and-tabs + 224:3 error Mixed spaces and tabs no-mixed-spaces-and-tabs + 224:12 error Unsafe assignment of an `any` value @typescript-eslint/no-unsafe-assignment + 225:3 error Mixed spaces and tabs no-mixed-spaces-and-tabs + 225:46 error Unsafe argument of type `any` assigned to a parameter of type `SetStateAction` @typescript-eslint/no-unsafe-argument + 225:46 error Unsafe member access .models on an `any` value @typescript-eslint/no-unsafe-member-access + 225:46 error Unsafe call of an `any` typed value @typescript-eslint/no-unsafe-call + 225:67 warning Unexpected any. Specify a different type @typescript-eslint/no-explicit-any + 225:75 error Unsafe return of an `any` typed value @typescript-eslint/no-unsafe-return + 225:75 error Unsafe member access .name on an `any` value @typescript-eslint/no-unsafe-member-access + 225:85 error Unsafe member access .model on an `any` value @typescript-eslint/no-unsafe-member-access + 236:3 error Mixed spaces and tabs no-mixed-spaces-and-tabs + 239:3 error Mixed spaces and tabs no-mixed-spaces-and-tabs + 240:21 error Unsafe assignment of an `any` value @typescript-eslint/no-unsafe-assignment + 241:55 error Unsafe argument of type `any` assigned to a parameter of type `SetStateAction` @typescript-eslint/no-unsafe-argument + 241:55 error Unsafe member access .models on an `any` value @typescript-eslint/no-unsafe-member-access + 241:55 error Unsafe call of an `any` typed value @typescript-eslint/no-unsafe-call + 241:76 warning Unexpected any. Specify a different type @typescript-eslint/no-explicit-any + 241:84 error Unsafe member access .name on an `any` value @typescript-eslint/no-unsafe-member-access + 241:84 error Unsafe return of an `any` typed value @typescript-eslint/no-unsafe-return + 248:21 warning Unexpected any. Specify a different type @typescript-eslint/no-explicit-any + 249:13 error Unsafe member access .name on an `any` value @typescript-eslint/no-unsafe-member-access + 261:6 warning React Hook useEffect has a missing dependency: 'apiKey'. Either include it or remove the dependency array react-hooks/exhaustive-deps + 435:2 error Mixed spaces and tabs no-mixed-spaces-and-tabs + 436:2 error Mixed spaces and tabs no-mixed-spaces-and-tabs + 440:3 error Mixed spaces and tabs no-mixed-spaces-and-tabs + 446:3 error Mixed spaces and tabs no-mixed-spaces-and-tabs + 447:3 error Mixed spaces and tabs no-mixed-spaces-and-tabs + 451:3 error Mixed spaces and tabs no-mixed-spaces-and-tabs + 453:3 error Mixed spaces and tabs no-mixed-spaces-and-tabs + 459:4 error Mixed spaces and tabs no-mixed-spaces-and-tabs + 460:4 error Mixed spaces and tabs no-mixed-spaces-and-tabs + 461:4 error Mixed spaces and tabs no-mixed-spaces-and-tabs + 462:4 error Mixed spaces and tabs no-mixed-spaces-and-tabs + 467:4 error Mixed spaces and tabs no-mixed-spaces-and-tabs + 468:4 error Mixed spaces and tabs no-mixed-spaces-and-tabs + 469:4 error Mixed spaces and tabs no-mixed-spaces-and-tabs + 470:4 error Mixed spaces and tabs no-mixed-spaces-and-tabs + 474:3 error Mixed spaces and tabs no-mixed-spaces-and-tabs + 476:3 error Mixed spaces and tabs no-mixed-spaces-and-tabs + 479:3 error Mixed spaces and tabs no-mixed-spaces-and-tabs + 481:3 error Mixed spaces and tabs no-mixed-spaces-and-tabs + 483:2 error Mixed spaces and tabs no-mixed-spaces-and-tabs + 490:3 error Mixed spaces and tabs no-mixed-spaces-and-tabs + 491:3 error Mixed spaces and tabs no-mixed-spaces-and-tabs + 492:3 error Mixed spaces and tabs no-mixed-spaces-and-tabs + +/home/beerus1206/Documents/code/githubrepo/template-playground/src/contexts/MarkdownEditorContext.tsx + 36:14 warning Fast refresh only works when a file only exports components. Use a new file to share constants or functions between components react-refresh/only-export-components + +/home/beerus1206/Documents/code/githubrepo/template-playground/src/tests/components/SettingsModal.test.tsx + 8:34 error Unsafe return of an `any` typed value @typescript-eslint/no-unsafe-return + 8:34 error Unsafe call of an `any` typed value @typescript-eslint/no-unsafe-call + +/home/beerus1206/Documents/code/githubrepo/template-playground/src/tests/components/ShareModal.test.tsx + 11:9 error Unsafe assignment of an `any` value @typescript-eslint/no-unsafe-assignment + 78:16 error Avoid referencing unbound methods which may cause unintentional scoping of `this`. +If your function does not access `this`, you can annotate it with `this: void`, or consider using an arrow function instead @typescript-eslint/unbound-method + +/home/beerus1206/Documents/code/githubrepo/template-playground/src/utils/helpers/errorUtils.ts + 5:7 error 'errorMessage' is never reassigned. Use 'const' instead prefer-const + 8:7 error 'jsonMatch' is never reassigned. Use 'const' instead prefer-const + 11:13 error Unsafe assignment of an `any` value @typescript-eslint/no-unsafe-assignment + 14:11 error Unsafe member access .error on an `any` value @typescript-eslint/no-unsafe-member-access + 15:20 error Unsafe member access .error on an `any` value @typescript-eslint/no-unsafe-member-access + 17:15 error Unsafe member access .error on an `any` value @typescript-eslint/no-unsafe-member-access + 18:24 error Unsafe member access .error on an `any` value @typescript-eslint/no-unsafe-member-access + 20:23 error Unsafe assignment of an `any` value @typescript-eslint/no-unsafe-assignment + 20:42 error Unsafe argument of type `any` assigned to a parameter of type `string` @typescript-eslint/no-unsafe-argument + 20:42 error Unsafe member access .error on an `any` value @typescript-eslint/no-unsafe-member-access + 21:21 error Unsafe member access .error on an `any` value @typescript-eslint/no-unsafe-member-access + 22:19 error Unsafe return of an `any` typed value @typescript-eslint/no-unsafe-return + 22:26 error Unsafe member access .error on an `any` value @typescript-eslint/no-unsafe-member-access + 25:17 error Unsafe return of an `any` typed value @typescript-eslint/no-unsafe-return + 25:24 error Unsafe member access .error on an `any` value @typescript-eslint/no-unsafe-member-access + 31:20 error Unsafe member access .error on an `any` value @typescript-eslint/no-unsafe-member-access + 32:11 error Unsafe return of an `any` typed value @typescript-eslint/no-unsafe-return + 32:18 error Unsafe member access .error on an `any` value @typescript-eslint/no-unsafe-member-access + 37:11 error Unsafe member access .detail on an `any` value @typescript-eslint/no-unsafe-member-access + 38:9 error Unsafe return of an `any` typed value @typescript-eslint/no-unsafe-return + 38:16 error Unsafe member access .detail on an `any` value @typescript-eslint/no-unsafe-member-access + 42:11 error Unsafe member access .message on an `any` value @typescript-eslint/no-unsafe-member-access + 43:9 error Unsafe return of an `any` typed value @typescript-eslint/no-unsafe-return + 43:16 error Unsafe member access .message on an `any` value @typescript-eslint/no-unsafe-member-access + 52:11 error Unsafe assignment of an `any` value @typescript-eslint/no-unsafe-assignment + 55:9 error Unsafe member access .error on an `any` value @typescript-eslint/no-unsafe-member-access + 56:18 error Unsafe member access .error on an `any` value @typescript-eslint/no-unsafe-member-access + 58:13 error Unsafe member access .error on an `any` value @typescript-eslint/no-unsafe-member-access + 61:19 error Unsafe assignment of an `any` value @typescript-eslint/no-unsafe-assignment + 61:44 error Unsafe argument of type `any` assigned to a parameter of type `string` @typescript-eslint/no-unsafe-argument + 61:44 error Unsafe member access .error on an `any` value @typescript-eslint/no-unsafe-member-access + 62:17 error Unsafe member access .error on an `any` value @typescript-eslint/no-unsafe-member-access + 62:38 error Unsafe member access .error on an `any` value @typescript-eslint/no-unsafe-member-access + 63:15 error Unsafe return of an `any` typed value @typescript-eslint/no-unsafe-return + 63:22 error Unsafe member access .error on an `any` value @typescript-eslint/no-unsafe-member-access + 66:13 error Unsafe return of an `any` typed value @typescript-eslint/no-unsafe-return + 66:20 error Unsafe member access .error on an `any` value @typescript-eslint/no-unsafe-member-access + 70:18 error Unsafe member access .error on an `any` value @typescript-eslint/no-unsafe-member-access + 71:9 error Unsafe return of an `any` typed value @typescript-eslint/no-unsafe-return + 71:16 error Unsafe member access .error on an `any` value @typescript-eslint/no-unsafe-member-access + 76:9 error Unsafe member access .detail on an `any` value @typescript-eslint/no-unsafe-member-access + 77:7 error Unsafe return of an `any` typed value @typescript-eslint/no-unsafe-return + 77:14 error Unsafe member access .detail on an `any` value @typescript-eslint/no-unsafe-member-access + 81:9 error Unsafe member access .message on an `any` value @typescript-eslint/no-unsafe-member-access + 82:7 error Unsafe return of an `any` typed value @typescript-eslint/no-unsafe-return + 82:14 error Unsafe member access .message on an `any` value @typescript-eslint/no-unsafe-member-access + +/home/beerus1206/Documents/code/githubrepo/template-playground/src/utils/secureKeyStorage.ts + 171:17 error This assertion is unnecessary since it does not change the type of the expression @typescript-eslint/no-unnecessary-type-assertion + 213:32 error This assertion is unnecessary since it does not change the type of the expression @typescript-eslint/no-unnecessary-type-assertion + 220:36 error This assertion is unnecessary since it does not change the type of the expression @typescript-eslint/no-unnecessary-type-assertion + 314:42 error This assertion is unnecessary since it does not change the type of the expression @typescript-eslint/no-unnecessary-type-assertion + +/home/beerus1206/Documents/code/githubrepo/template-playground/src/utils/testing/setup.ts + 63:25 error Unexpected empty method 'fillRect' @typescript-eslint/no-empty-function + 64:26 error Unexpected empty method 'clearRect' @typescript-eslint/no-empty-function + 66:29 error Unexpected empty method 'putImageData' @typescript-eslint/no-empty-function + 68:29 error Unexpected empty method 'setTransform' @typescript-eslint/no-empty-function + 69:26 error Unexpected empty method 'drawImage' @typescript-eslint/no-empty-function + 70:21 error Unexpected empty method 'save' @typescript-eslint/no-empty-function + 71:24 error Unexpected empty method 'restore' @typescript-eslint/no-empty-function + 72:26 error Unexpected empty method 'beginPath' @typescript-eslint/no-empty-function + 73:23 error Unexpected empty method 'moveTo' @typescript-eslint/no-empty-function + 74:23 error Unexpected empty method 'lineTo' @typescript-eslint/no-empty-function + 75:26 error Unexpected empty method 'closePath' @typescript-eslint/no-empty-function + 76:23 error Unexpected empty method 'stroke' @typescript-eslint/no-empty-function + 77:21 error Unexpected empty method 'fill' @typescript-eslint/no-empty-function + 78:26 error Unexpected empty method 'translate' @typescript-eslint/no-empty-function + 79:22 error Unexpected empty method 'scale' @typescript-eslint/no-empty-function + 80:23 error Unexpected empty method 'rotate' @typescript-eslint/no-empty-function + 81:20 error Unexpected empty method 'arc' @typescript-eslint/no-empty-function + 83:26 error Unexpected empty method 'transform' @typescript-eslint/no-empty-function + 84:21 error Unexpected empty method 'rect' @typescript-eslint/no-empty-function + 85:21 error Unexpected empty method 'clip' @typescript-eslint/no-empty-function + 89:55 warning Unexpected any. Specify a different type @typescript-eslint/no-explicit-any + 91:4 error Avoid referencing unbound methods which may cause unintentional scoping of `this`. +If your function does not access `this`, you can annotate it with `this: void`, or consider using an arrow function instead @typescript-eslint/unbound-method + +✖ 168 problems (158 errors, 10 warnings) + 6 errors and 0 warnings potentially fixable with the `--fix` option. + diff --git a/package-lock.json b/package-lock.json index 26ce2507..d95faaee 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2707,9 +2707,10 @@ } }, "node_modules/@babel/core": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.7.tgz", - "integrity": "sha512-nykK+LEK86ahTkX/3TgauT0ikKoNCfKHEaZYTUVupJdTLzGNvrblu4u6fa7DhZONAltdf8e662t/abY8idrd/g==", + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", + "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", + "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.24.7", @@ -4826,6 +4827,7 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT", "engines": { "node": ">=18" }, @@ -4847,6 +4849,7 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT", "engines": { "node": ">=18" } @@ -9925,6 +9928,7 @@ "version": "8.17.1", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -10842,6 +10846,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", "peer": true, "engines": { "node": ">= 0.8" @@ -11493,6 +11498,7 @@ "version": "1.8.1", "resolved": "https://registry.npmjs.org/compression/-/compression-1.8.1.tgz", "integrity": "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==", + "license": "MIT", "peer": true, "dependencies": { "bytes": "3.1.2", @@ -11526,6 +11532,7 @@ "version": "0.6.4", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", + "license": "MIT", "peer": true, "engines": { "node": ">= 0.6" @@ -13565,6 +13572,7 @@ "url": "https://github.com/sponsors/NaturalIntelligence" } ], + "license": "MIT", "peer": true, "dependencies": { "strnum": "^1.0.5" @@ -18248,6 +18256,7 @@ "version": "3.14.2", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", + "license": "MIT", "peer": true, "dependencies": { "argparse": "^1.0.7", @@ -19906,6 +19915,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz", "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==", + "license": "MIT", "peer": true, "engines": { "node": ">= 0.8" @@ -23017,6 +23027,7 @@ "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.30.0.tgz", "integrity": "sha512-kQvGasUgN+AlWGliFn2POSajRQEsULVYFGTvOZmK06d7vCD+YhZztt70kGk3qaeAXeWYL5eO7zx+rAubBc55eA==", "dev": true, + "license": "MIT", "bin": { "rollup": "dist/bin/rollup" }, @@ -25334,6 +25345,7 @@ "version": "5.9.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -25900,6 +25912,7 @@ "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.14.tgz", "integrity": "sha512-+v57oAaoYNnO3hIu5Z/tJRZjq5aHM2zDve9YZ8HngVHbhk66RStobhb1sqPMIPEleV6cNKYK4eGrAbE9Ulbl2g==", "dev": true, + "license": "MIT", "dependencies": { "esbuild": "^0.18.10", "postcss": "^8.4.27", @@ -26580,6 +26593,7 @@ "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.4.tgz", "integrity": "sha512-7tP1PdV4vF+lYPnkMR0jMY5/la2ub5Fc/8VQrrU+lXkiM6C4TjVfGw7iKfyhnTQOsD+6Q/iKw0eFciziRgD58Q==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": ">=10.13.0" diff --git a/src/components/AIChatPanel.tsx b/src/components/AIChatPanel.tsx index f422f27b..a2fc4491 100644 --- a/src/components/AIChatPanel.tsx +++ b/src/components/AIChatPanel.tsx @@ -8,13 +8,13 @@ export const AIChatPanel = () => { const [isDropdownOpen, setIsDropdownOpen] = useState(false); const [userInput, setUserInput] = useState(""); const textareaRef = useRef(null); - + const editorsContent = useAppStore((state) => ({ editorTemplateMark: state.editorValue, editorModelCto: state.editorModelCto, editorAgreementData: state.editorAgreementData, })); - + const { chatState, resetChat, aiConfig, setAIConfig, setAIConfigOpen, setAIChatOpen, textColor, backgroundColor } = useAppStore((state) => ({ chatState: state.chatState, resetChat: state.resetChat, @@ -25,15 +25,15 @@ export const AIChatPanel = () => { textColor: state.textColor, backgroundColor: state.backgroundColor })); - + const latestMessageRef = useRef(null); const theme = useMemo(() => { const isDarkMode = backgroundColor !== '#ffffff'; return { - header: `h-10 -ml-4 -mr-4 -mt-1 p-2 border-gray-200 text-sm font-medium flex justify-between items-center ${ - isDarkMode ? 'bg-gray-700 text-white' : 'bg-slate-100 text-gray-700' - }`, + header: `h-10 -ml-4 -mr-4 -mt-1 p-2 border-gray-200 text-sm font-medium flex justify-between items-center ${isDarkMode ? 'bg-gray-700 text-white' : 'bg-slate-100 text-gray-700' + }`, + iconButton: isDarkMode ? 'text-gray-300 hover:text-white' : 'text-gray-500 hover:text-gray-800', welcomeMessage: isDarkMode ? 'bg-blue-900' : 'bg-blue-100', welcomeText: isDarkMode ? 'text-gray-300' : 'text-gray-600', @@ -71,7 +71,7 @@ export const AIChatPanel = () => { inlineCode: isDarkMode ? 'bg-gray-700 text-gray-200' : 'bg-gray-200 text-gray-800' }; }, [backgroundColor]); - + const [includeTemplateMarkContent, setIncludeTemplateMarkContent] = useState( localStorage.getItem('aiIncludeTemplateMark') === 'true' ); @@ -81,69 +81,69 @@ export const AIChatPanel = () => { const [includeDataContent, setIncludeDataContent] = useState( localStorage.getItem('aiIncludeData') === 'true' ); - + const handleSendMessage = async () => { if (!userInput.trim()) return; - + if (!aiConfig) { setAIConfigOpen(true); return; } - + const prompt = userInput; - + setUserInput(""); setIsDropdownOpen(false); - + if (textareaRef.current) { textareaRef.current.scrollTop = 0; } - + await sendMessage(prompt, promptPreset, editorsContent); }; - + const handleTemplateMarkToggle = (checked: boolean) => { setIncludeTemplateMarkContent(checked); localStorage.setItem('aiIncludeTemplateMark', checked.toString()); - + if (aiConfig) { const updatedConfig = { ...aiConfig, includeTemplateMarkContent: checked }; - + setAIConfig(updatedConfig); } }; - + const handleConcertoModelToggle = (checked: boolean) => { setIncludeConcertoModelContent(checked); localStorage.setItem('aiIncludeConcertoModel', checked.toString()); - + if (aiConfig) { const updatedConfig = { ...aiConfig, includeConcertoModelContent: checked }; - + setAIConfig(updatedConfig); } }; - + const handleDataToggle = (checked: boolean) => { setIncludeDataContent(checked); localStorage.setItem('aiIncludeData', checked.toString()); - + if (aiConfig) { const updatedConfig = { ...aiConfig, includeDataContent: checked }; - + setAIConfig(updatedConfig); } }; - + const handleStopMessage = () => { stopMessage(); }; @@ -162,14 +162,14 @@ export const AIChatPanel = () => { // Detect error marker const isError = content.startsWith('[ERROR]'); const displayContent = isError ? content.replace(/^\[ERROR\]\s*/, '') : content; - + if (!displayContent || !displayContent.includes('```')) { return (
{children}, - }}> + }}> {displayContent}
@@ -178,9 +178,9 @@ export const AIChatPanel = () => { const parts = []; let key = 0; - + const segments = displayContent.split('```'); - + if (segments[0]) { parts.push(
@@ -190,16 +190,16 @@ export const AIChatPanel = () => {
); } - + for (let i = 1; i < segments.length; i++) { if (i % 2 === 1 && segments[i]) { const firstLineBreak = segments[i].indexOf('\n'); let code = segments[i]; - + if (firstLineBreak > -1) { code = segments[i].substring(firstLineBreak + 1); } - + parts.push(
@@ -217,18 +217,18 @@ export const AIChatPanel = () => {
         );
       }
     }
-    
+
     return parts;
   };
 
   useEffect(() => {
     if (chatState.messages.length > 0 && latestMessageRef.current) {
       const messageContainer = latestMessageRef.current.closest('.overflow-y-auto');
-      
+
       if (messageContainer) {
         setTimeout(() => {
           const messageTop = latestMessageRef.current!.offsetTop;
-          
+
           messageContainer.scrollTop = messageTop - 50;
         }, 100);
       }
@@ -242,7 +242,7 @@ export const AIChatPanel = () => {
         
- )}) - )} + ) + }) + )}
- {promptPreset && ( + {promptPreset && (
- - { - promptPreset === "textToTemplate" ? "Text to TemplateMark" : "Create Concerto Model" - } - - +
- )} - - {/* Context selection row */} -
- Context: - {/* TemplateMark Button */} -
handleTemplateMarkToggle(!includeTemplateMarkContent)} - className={ - `px-1 py-0.5 text-xs rounded-full flex items-center cursor-pointer border transition-colors + )} + + {/* Context selection row */} +
+ Context: + {/* TemplateMark Button */} +
handleTemplateMarkToggle(!includeTemplateMarkContent)} + className={ + `px-1 py-0.5 text-xs rounded-full flex items-center cursor-pointer border transition-colors ${includeTemplateMarkContent - ? theme.contextButtons.templateMark.active - : theme.contextButtons.templateMark.inactive}` - } - > - TemplateMark - {includeTemplateMarkContent && ( - - )} -
- {/* Concerto Button */} -
handleConcertoModelToggle(!includeConcertoModelContent)} - className={ - `px-1 py-0.5 text-xs rounded-full flex items-center cursor-pointer border transition-colors + + + + )} +
+ {/* Concerto Button */} +
handleConcertoModelToggle(!includeConcertoModelContent)} + className={ + `px-1 py-0.5 text-xs rounded-full flex items-center cursor-pointer border transition-colors ${includeConcertoModelContent - ? theme.contextButtons.concerto.active - : theme.contextButtons.concerto.inactive}` - } + ? theme.contextButtons.concerto.active + : theme.contextButtons.concerto.inactive}` + } + > + Concerto + {includeConcertoModelContent && ( + + )} +
+ {/* Data Button */} +
handleDataToggle(!includeDataContent)} + className={ + `px-1 py-0.5 text-xs rounded-full flex items-center cursor-pointer border transition-colors + ${includeDataContent + ? theme.contextButtons.data.active + : theme.contextButtons.data.inactive}` + } + > + Data + {includeDataContent && ( + + )} +
+
+ +
+