-
-
Notifications
You must be signed in to change notification settings - Fork 11
feat: suggestions import #74
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
ba1802a
68ba732
fc7c7ec
782e793
71a9fe2
ddb9635
17bc30b
0e93649
5dcacd9
71320f2
266bb58
da2a8fc
91205ed
405acb2
d3555bf
454ed41
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,90 @@ | ||||||||||||||||||||||||||||||||||||||||||||||
| import { ApiClient, createApiClient, components } from "@tginternal/client"; | ||||||||||||||||||||||||||||||||||||||||||||||
| import { languagesTestData } from "./languageTestData"; | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| const API_URL = "http://localhost:22223"; | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| export async function deleteProject(client: ApiClient | undefined) { | ||||||||||||||||||||||||||||||||||||||||||||||
| await client?.DELETE("/v2/projects/{projectId}", { | ||||||||||||||||||||||||||||||||||||||||||||||
| params: { path: { projectId: client?.getProjectId() } }, | ||||||||||||||||||||||||||||||||||||||||||||||
| parseAs: "stream", | ||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| export type Options = { | ||||||||||||||||||||||||||||||||||||||||||||||
| languages?: components["schemas"]["LanguageRequest"][]; | ||||||||||||||||||||||||||||||||||||||||||||||
| } & Partial<Omit<components["schemas"]["EditProjectRequest"], "name">>; | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| export async function createProjectWithClient( | ||||||||||||||||||||||||||||||||||||||||||||||
| name: string, | ||||||||||||||||||||||||||||||||||||||||||||||
| data: components["schemas"]["SingleStepImportResolvableRequest"], | ||||||||||||||||||||||||||||||||||||||||||||||
| options?: Options | ||||||||||||||||||||||||||||||||||||||||||||||
| ) { | ||||||||||||||||||||||||||||||||||||||||||||||
| const client = createApiClient({ | ||||||||||||||||||||||||||||||||||||||||||||||
| baseUrl: API_URL, | ||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||
| await client.login({ username: "admin", password: "admin" }); | ||||||||||||||||||||||||||||||||||||||||||||||
| const organizations = await client.GET("/v2/organizations"); | ||||||||||||||||||||||||||||||||||||||||||||||
| const { languages, ...editOptions } = options ?? {}; | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| const project = await client.POST("/v2/projects", { | ||||||||||||||||||||||||||||||||||||||||||||||
| body: { | ||||||||||||||||||||||||||||||||||||||||||||||
| name, | ||||||||||||||||||||||||||||||||||||||||||||||
| organizationId: organizations.data!._embedded!.organizations![0].id, | ||||||||||||||||||||||||||||||||||||||||||||||
| languages: languages ?? languagesTestData, | ||||||||||||||||||||||||||||||||||||||||||||||
| icuPlaceholders: editOptions?.icuPlaceholders ?? true, | ||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+29
to
+36
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unsafe chained non-null assertions could cause runtime errors. Line 32 chains multiple non-null assertions ( Apply this diff to add proper error handling: const organizations = await client.GET("/v2/organizations");
+ if (!organizations.data?._embedded?.organizations?.length) {
+ throw new Error("No organizations found for admin user");
+ }
const { languages, ...editOptions } = options ?? {};
const project = await client.POST("/v2/projects", {
body: {
name,
- organizationId: organizations.data!._embedded!.organizations![0].id,
+ organizationId: organizations.data._embedded.organizations[0].id,
languages: languages ?? languagesTestData,
icuPlaceholders: editOptions?.icuPlaceholders ?? true,
},
});📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| client.setProjectId(project.data!.id); | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| await client.PUT("/v2/projects/{projectId}", { | ||||||||||||||||||||||||||||||||||||||||||||||
| params: { | ||||||||||||||||||||||||||||||||||||||||||||||
| path: { | ||||||||||||||||||||||||||||||||||||||||||||||
| projectId: client.getProjectId(), | ||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||
| body: { | ||||||||||||||||||||||||||||||||||||||||||||||
| icuPlaceholders: true, | ||||||||||||||||||||||||||||||||||||||||||||||
| useNamespaces: true, | ||||||||||||||||||||||||||||||||||||||||||||||
| suggestionsMode: "DISABLED", | ||||||||||||||||||||||||||||||||||||||||||||||
| translationProtection: "NONE", | ||||||||||||||||||||||||||||||||||||||||||||||
| ...editOptions, | ||||||||||||||||||||||||||||||||||||||||||||||
| name, | ||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| await client.POST("/v2/projects/{projectId}/single-step-import-resolvable", { | ||||||||||||||||||||||||||||||||||||||||||||||
| params: { path: { projectId: client.getProjectId() } }, | ||||||||||||||||||||||||||||||||||||||||||||||
| body: data, | ||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| return client; | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| export const DEFAULT_SCOPES = [ | ||||||||||||||||||||||||||||||||||||||||||||||
| "keys.view", | ||||||||||||||||||||||||||||||||||||||||||||||
| "translations.view", | ||||||||||||||||||||||||||||||||||||||||||||||
| "translations.edit", | ||||||||||||||||||||||||||||||||||||||||||||||
| "keys.edit", | ||||||||||||||||||||||||||||||||||||||||||||||
| "keys.create", | ||||||||||||||||||||||||||||||||||||||||||||||
| "screenshots.view", | ||||||||||||||||||||||||||||||||||||||||||||||
| "screenshots.upload", | ||||||||||||||||||||||||||||||||||||||||||||||
| "screenshots.delete", | ||||||||||||||||||||||||||||||||||||||||||||||
| "translations.state-edit", | ||||||||||||||||||||||||||||||||||||||||||||||
| ]; | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| export async function createPak(client: ApiClient, scopes = DEFAULT_SCOPES) { | ||||||||||||||||||||||||||||||||||||||||||||||
| const apiKey = await client.POST("/v2/api-keys", { | ||||||||||||||||||||||||||||||||||||||||||||||
| body: { projectId: client.getProjectId(), scopes }, | ||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| return apiKey.data!.key; | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+76
to
+82
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Verify API response data exists before non-null assertions. Lines 81 and 89 use non-null assertions on API response data without verifying the response succeeded. If the API call fails or returns unexpected data, this will cause runtime errors. Apply this diff to add proper error handling: export async function createPak(client: ApiClient, scopes = DEFAULT_SCOPES) {
const apiKey = await client.POST("/v2/api-keys", {
body: { projectId: client.getProjectId(), scopes },
});
-
- return apiKey.data!.key;
+ if (!apiKey.data?.key) {
+ throw new Error("Failed to create API key: no key in response");
+ }
+ return apiKey.data.key;
}
export async function createPat(client: ApiClient) {
const apiKey = await client.POST("/v2/pats", {
body: { description: "e2e test pat" },
});
-
- return apiKey.data!.token;
+ if (!apiKey.data?.token) {
+ throw new Error("Failed to create PAT: no token in response");
+ }
+ return apiKey.data.token;
}Also applies to: 84-90 |
||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| export async function createPat(client: ApiClient) { | ||||||||||||||||||||||||||||||||||||||||||||||
| const apiKey = await client.POST("/v2/pats", { | ||||||||||||||||||||||||||||||||||||||||||||||
| body: { description: "e2e test pat" }, | ||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| return apiKey.data!.token; | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| import { components } from "@tginternal/client"; | ||
| import en from "../import-data/examples/en.json"; | ||
| import fr from "../import-data/examples/fr.json"; | ||
| import cs from "../import-data/examples/cs.json"; | ||
| import de from "../import-data/examples/de.json"; | ||
|
|
||
| const keys = Object.keys(en) as Array<keyof typeof en>; | ||
| export const EXAMPLE_PROJECT: components["schemas"]["SingleStepImportResolvableRequest"] = | ||
| { | ||
| keys: keys.map((name) => ({ | ||
| name, | ||
| translations: { | ||
| en: { text: en[name] }, | ||
| fr: { text: fr[name] }, | ||
| cs: { text: cs[name] }, | ||
| de: { text: de[name] }, | ||
| }, | ||
| })), | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| import { components } from "@tginternal/client"; | ||
|
|
||
| export const languagesTestData: components["schemas"]["LanguageRequest"][] = [ | ||
|
Comment on lines
+1
to
+3
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chainVerify the import source and type safety. The code imports Please confirm:
Run the following script to check the type definitions: 🏁 Script executed: #!/bin/bash
# Check if @tginternal/client exports components with LanguageRequest schema
rg -A 10 'export.*components' node_modules/@tginternal/client --type ts 2>/dev/null || echo "@tginternal/client not found or no TypeScript files"
# Check local apiSchema for components definition
echo "--- Local apiSchema.generated.ts ---"
cat src/client/apiSchema.generated.ts | head -20
# Check if there are other generated API schema files
echo "--- Other API schema files ---"
fd 'apiSchema|api.*schema' --type fLength of output: 577 Ensure proper type definitions for LanguageRequest
🤖 Prompt for AI Agents |
||
| { | ||
| name: "English", | ||
| originalName: "English", | ||
| tag: "en", | ||
| flagEmoji: "🇬🇧", | ||
| }, | ||
| { | ||
| name: "French", | ||
| originalName: "French", | ||
| tag: "fr", | ||
| flagEmoji: "🇫🇷", | ||
| }, | ||
| { | ||
| name: "Czech", | ||
| originalName: "Czech", | ||
| tag: "cs", | ||
| }, | ||
| { | ||
| name: "German", | ||
| originalName: "German", | ||
| tag: "de", | ||
| }, | ||
| ]; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,9 +1,8 @@ | ||
| import { createShortcutUrl, PluginData } from "@/web/urlConfig"; | ||
|
|
||
| const ORIGIN = "http://localhost:3000"; | ||
| const ORIGIN = "http://localhost:22224"; | ||
|
|
||
| export const visitWithState = (data: Partial<PluginData>) => { | ||
| cy.visit(`${ORIGIN}${createShortcutUrl(data)}`); | ||
| cy.wait(100); | ||
| cy.frameLoaded("#plugin_iframe"); | ||
| cy.iframeReady(); | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Potential configuration override: icuPlaceholders is set twice.
Line 34 defaults
icuPlaceholderstotrueif not provided ineditOptions, but line 47 unconditionally sets it totrueagain in the PUT request, potentially overriding a user-providedfalsevalue fromeditOptions.Apply this diff to ensure
editOptionstakes precedence:body: { name, organizationId: organizations.data!._embedded!.organizations![0].id, languages: languages ?? languagesTestData, - icuPlaceholders: editOptions?.icuPlaceholders ?? true, + icuPlaceholders: true, }, }); client.setProjectId(project.data!.id); await client.PUT("/v2/projects/{projectId}", { params: { path: { projectId: client.getProjectId(), }, }, body: { - icuPlaceholders: true, useNamespaces: true, suggestionsMode: "DISABLED", translationProtection: "NONE", ...editOptions, + icuPlaceholders: editOptions?.icuPlaceholders ?? true, name, }, });Also applies to: 47-47
🤖 Prompt for AI Agents