Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
77 commits
Select commit Hold shift + click to select a range
be0f3bc
feat(i18n): Adding i18n support.
Raptor399 Nov 5, 2025
8a52bb9
feat(i18n): Fixing "This expression is not callable" error in editor.
Raptor399 Nov 5, 2025
fc929ea
feat(i18n): Fix vue-tsc errors
Raptor399 Nov 6, 2025
10e8d00
feat(i18n): Updated packages
Raptor399 Nov 7, 2025
53aa4ba
feat(i18n): Fix error "Unsafe assignment of an error typed value."
Raptor399 Nov 7, 2025
b68a351
feat(i18n): Fix error "Unsafe assignment of an `error` type typed val…
Raptor399 Nov 7, 2025
0679a8a
feat(i18n): Fix error "defined but never used"
Raptor399 Nov 7, 2025
2ca262b
feat(i18n): Quick code style fixes
Raptor399 Nov 7, 2025
c499cb5
feat(i18n): Fix error "Unsafe call of an `error` type typed value."
Raptor399 Nov 8, 2025
9b84f2e
feat(i18n): Refactor to fix type inference
Raptor399 Nov 8, 2025
cd5f688
feat(i18n): Fix linter errors
Raptor399 Nov 8, 2025
c131658
feat(i18n): Decouple from i18n.global.t to return a safe type, hopefu…
Raptor399 Nov 9, 2025
94c7ddc
feat(i18n): Trying to get rid of "Unsafe call of an `error` type type…
Raptor399 Nov 9, 2025
505744f
feat(i18n): Fix production linter errors
Raptor399 Nov 10, 2025
1175f50
feat(i18n): Fix production linter errors in existing code.
Raptor399 Nov 10, 2025
74396db
feat(i18n): Use type assertions to prevent production linter errors.
Raptor399 Nov 10, 2025
83b3245
feat(i18n): Fix object injection sink errors
Raptor399 Nov 11, 2025
4d1bdb6
feat(i18n): Fix error "The application dynamically constructs file or…
Raptor399 Nov 13, 2025
6ea510a
feat(i18n): Switch to using literals only to satisfy Codacy security …
Raptor399 Nov 13, 2025
375e035
feat(i18n): Explicitly convert to string to prevent "Unsafe assignmen…
Raptor399 Nov 15, 2025
6fb6eb5
feat(i18n): Use explicity typing instead of using unknown.
Raptor399 Nov 15, 2025
8f0b016
feat(i18n): Fix Codacy errors
Raptor399 Nov 15, 2025
549e176
feat(i18n): Narrowly type the translation function
Raptor399 Nov 17, 2025
e1a44b6
feat(i18n): Revert previous commit.
Raptor399 Nov 17, 2025
94c34ff
feat(i18n): Remove try/catch to remove implicit `error` type
Raptor399 Nov 17, 2025
8253c44
feat(i18n): Explicitly cast result
Raptor399 Nov 17, 2025
4b3082f
feat(i18n): Explicitly type the translator function
Raptor399 Nov 17, 2025
4e06018
feat(i18n): Testing the response of Codacy for "Unsafe assignment of …
Raptor399 Nov 17, 2025
000f0b6
feat(i18n): Make i18n type explicit
Raptor399 Nov 17, 2025
0519110
feat(i18n): Hide bare constant behind accessor
Raptor399 Nov 17, 2025
5ebf0c8
feat(i18n): Use types to avoid "unsafe assignment of an `any` value."…
Raptor399 Nov 24, 2025
69e0d6b
feat(i18n): Define `i18n` local instead of on the module level to pre…
Raptor399 Nov 24, 2025
beba8b4
feat(i18n): Stop using custom translator function
Raptor399 Nov 24, 2025
4683d15
feat(i18n): Using local `t()` to avoid "expression is not callable" e…
Raptor399 Nov 24, 2025
2a608ba
feat(i18n): Remove unused import
Raptor399 Nov 24, 2025
bccb20b
feat(i18n): Add missing "errorDialogOk" label
Raptor399 Nov 24, 2025
2e500f5
feat(i18n): Use local `t()` to avoid "expression is not callable" error.
Raptor399 Nov 24, 2025
ec4f6ab
feat(i18n): Define `t()` locally to avoid "not callable" error.
Raptor399 Nov 25, 2025
cde11b8
feat(i18n): Fixed regex being vulnerable to super-linear runtime due …
Raptor399 Nov 25, 2025
7be0de7
feat(i18n): Use `LocalizedString` instead of `unknown`.
Raptor399 Nov 25, 2025
0c513d4
feat(i18n): Check type
Raptor399 Nov 25, 2025
4b65736
feat(i18n): Provide type to fix "Unsafe argument of type `any` assign…
Raptor399 Nov 25, 2025
33cfe53
feat(i18n): Check type
Raptor399 Nov 25, 2025
2486e42
feat(i18n): Try typing to get around "Unsafe member access .global on…
Raptor399 Nov 25, 2025
5026c78
feat(i18n): Use typing to get around "Unsafe member access .global on…
Raptor399 Nov 25, 2025
791c546
feat(i18n): Type to get around "Unsafe argument of type `any` assigne…
Raptor399 Nov 25, 2025
94aed11
feat(i18n): Type to get around "Unsafe argument of type `any` assigne…
Raptor399 Nov 25, 2025
e891c1a
feat(i18n): Fixing error "Array type using 'Array<T>' is forbidden. U…
Raptor399 Nov 25, 2025
89ad340
feat(i18n): Fix "Unsafe assignment of an error typed value." error
Raptor399 Nov 25, 2025
b807f48
feat(i18n): Provide return types to avoid "Unsafe call of an `error` …
Raptor399 Nov 25, 2025
bb610c1
feat(i18n): Try to fix "Unsafe call of an `error` type typed value."…
Raptor399 Nov 25, 2025
c820ef6
feat(i18n): Prevent unsafe call errors by using relative import path.
Raptor399 Nov 25, 2025
332ff3d
feat(i18n): unref LocalizedString to string to fix "not assignable" e…
Raptor399 Nov 25, 2025
4a1b526
feat(i18n): Fix "Unsafe argument of type `EverestConfigList` assigned…
Raptor399 Nov 25, 2025
2d12a95
feat(i18n): Retry fix
Raptor399 Nov 25, 2025
a0e9b6c
feat(i18n): Prevent error "Detected string concatenation with a non-l…
Raptor399 Nov 26, 2025
9cb8d6c
feat(i18n): Fix error "Unsafe argument of type `EverestConfigList` as…
Raptor399 Nov 26, 2025
8192c6d
feat(i18n): Fix Codacy errors
Raptor399 Nov 26, 2025
d0e2a11
feat(i18n): Force type to avoid "unsafe" errors
Raptor399 Nov 26, 2025
dc50d8e
feat(i18n): Safely access `config`
Raptor399 Nov 26, 2025
70ad44e
feat(i18n): Rollback previous commit, as the "Generic Object Injectio…
Raptor399 Nov 26, 2025
7e67652
feat(i18n): Fix linter false positives on valid type annotations
Raptor399 Nov 27, 2025
d4d0816
feat(i18n): Silence false positive linter results
Raptor399 Nov 27, 2025
07c062b
feat(i18n): Address linter error "Depending on the context, user cont…
Raptor399 Nov 27, 2025
ae8df56
feat(i18n): Verify "Generic Object Injection Sink" issues and disable…
Raptor399 Nov 28, 2025
bde6590
feat(i18n): Verify and address unsafe assignments
Raptor399 Nov 28, 2025
38e95cd
feat(i18n): Prevent false positive object injection sink finding
Raptor399 Nov 28, 2025
116d76a
feat(i18n): Fix unsafe call and unsafe member access error
Raptor399 Nov 28, 2025
c75e937
feat(i18n): Rollback last attempt and try importing from relative pat…
Raptor399 Nov 28, 2025
8b76789
feat(i18n): Address "unsafe member access on an `error` typed value/"
Raptor399 Nov 28, 2025
e97a234
feat(i18n): Rollback previous commit.
Raptor399 Nov 28, 2025
bf63898
feat(i18n): Prevent "Unsafe member access .interface on an `error` ty…
Raptor399 Nov 28, 2025
d532585
feat(i18n): Make item type locally explicit.
Raptor399 Nov 28, 2025
2574fcc
feat(i18n): Make `item` type explicit
Raptor399 Nov 28, 2025
1ee2a81
feat(i18n): Use type narrowing function to prevent "Unsafe member acc…
Raptor399 Nov 28, 2025
9aedf17
feat(i18n): Narrow the type of `val`
Raptor399 Nov 28, 2025
23e01f9
feat(i18n): Disable check for verified safe value.
Raptor399 Nov 28, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 21 additions & 19 deletions build-tools/fetch-schemas-plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,27 +19,29 @@ function sha256(data: string): string {
}

export function fetchRemoteSchemas() {
remoteSchemas.forEach(async (schema) => {
if (!fs.existsSync(`./public/schemas/${schema.name}.json`)) {
const fetchedSchemaYAML = await fetch(schema.url).then((res) =>
res.text(),
);
const fetchedSchemaHash = sha256(fetchedSchemaYAML);
if (fetchedSchemaHash !== schema.hash) {
throw new Error(
`Schema hash mismatch for ${schema.url}. Expected: ${schema.hash}, got: ${fetchedSchemaHash}`,
remoteSchemas.forEach((schema) => {
void (async () => {
if (!fs.existsSync(`./public/schemas/${schema.name}.json`)) {
const fetchedSchemaYAML = await fetch(schema.url).then((res) =>
res.text(),
);
}
const schemaJSON = yaml.load(fetchedSchemaYAML);
const fetchedSchemaHash = sha256(fetchedSchemaYAML);
if (fetchedSchemaHash !== schema.hash) {
throw new Error(
`Schema hash mismatch for ${schema.url}. Expected: ${schema.hash}, got: ${fetchedSchemaHash}`,
);
}
const schemaJSON = yaml.load(fetchedSchemaYAML);

schema.hash = fetchedSchemaHash;
fs.mkdirSync("./public/schemas", { recursive: true });
fs.writeFileSync(
`./public/schemas/${schema.name}.json`,
JSON.stringify(schemaJSON),
);
schema.hash = fetchedSchemaHash;
fs.mkdirSync("./public/schemas", { recursive: true });
fs.writeFileSync(
`./public/schemas/${schema.name}.json`,
JSON.stringify(schemaJSON),
);

console.log(`${schema.url} fetched and cached successfully.`);
}
console.log(`${schema.url} fetched and cached successfully.`);
}
})();
});
}
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"splitpanes": "4.0.4",
"vee-validate": "4.15.1",
"vue": "3.5.18",
"vue-i18n": "^11.1.12",
"vue-router": "4.5.1",
"vue-tsc": "3.0.5",
"vuetify": "3.7.19"
Expand All @@ -63,7 +64,7 @@
"prettier": "3.6.2",
"sass": "1.89.2",
"typescript": "5.5.4",
"vite": "7.0.6",
"vite": "7.2.1",
"vite-plugin-pwa": "1.0.1",
"vite-plugin-vuetify": "2.1.1",
"vitest": "3.2.4",
Expand Down
1,368 changes: 745 additions & 623 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

25 changes: 14 additions & 11 deletions src/components/CreateConfig.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
@click="uploadConfigPrompt()"
/>
</template>
<span>Upload Config</span>
<span>{{ t("createConfig.uploadConfigTooltip") }}</span>
</v-tooltip>
<v-tooltip v-if="state == ComponentStates.DEFAULT" location="right" open-delay="500">
<template #activator="{ props }">
Expand All @@ -29,7 +29,7 @@
@click="state = ComponentStates.ASK_USER_FOR_CONFIG_NAME"
/>
</template>
<span>Create Config</span>
<span>{{ t("createConfig.createConfigTooltip") }}</span>
</v-tooltip>
<v-tooltip v-if="state == ComponentStates.ASK_USER_FOR_CONFIG_NAME" location="right" open-delay="500">
<template #activator="{ props }">
Expand All @@ -43,7 +43,7 @@
@click="resetDialog()"
/>
</template>
<span>Abort</span>
<span>{{ t("createConfig.abortTooltip") }}</span>
</v-tooltip>
<v-tooltip v-if="state == ComponentStates.ASK_USER_FOR_CONFIG_NAME" location="right" open-delay="500">
<template #activator="{ props }">
Expand All @@ -58,25 +58,25 @@
@click="onAcceptBtnClick()"
/>
</template>
<span>Create Config</span>
<span>{{ t("createConfig.createConfigTooltip") }}</span>
</v-tooltip>
</div>
<v-text-field
v-if="state === ComponentStates.ASK_USER_FOR_CONFIG_NAME"
v-model="configName"
density="compact"
data-cy="config-name-input"
placeholder="config name"
:placeholder="t('createConfig.configNamePlaceholder')"
:rules="[validateConfigName]"
/>
<v-dialog v-model="showErrorDialog" @click:outside="resetDialog()">
<v-card color="danger">
<v-card-title>Couldn't load config</v-card-title>
<v-card-title>{{ t("createConfig.errorDialogTitle") }}</v-card-title>
<v-card-text>
<pre style="white-space: pre-wrap"><code>{{ errorStore.getError() }}</code></pre>
</v-card-text>
<v-card-actions>
<v-btn color="primary" @click="resetDialog()"> OK </v-btn>
<v-btn color="primary" @click="resetDialog()">{{ t("createConfig.errorDialogOk") }}</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
Expand All @@ -91,6 +91,9 @@ import Ajv from "ajv";
import { EverestConfig } from "@/modules/evbc";
import { urlToPublicAsset } from "@/utils";
import { useErrorStore } from "@/store/errorStore";
import { useI18n } from "vue-i18n";

const { t } = useI18n({ useScope: "global" });

enum ComponentStates {
DEFAULT,
Expand Down Expand Up @@ -155,13 +158,13 @@ function uploadConfigPrompt() {
*/
function validateConfigName() {
if (configName.value.trim().length === 0) {
return "Please enter a name";
return t("createConfig.validateConfigNameMissing");
} else if (/.*(\.json|\.ya?ml)$/.test(configName.value)) {
return "The name must not contain the file extension";
return t("createConfig.validateConfigNameFileExtension");
} else if (!/^[a-zA-Z0-9-_]+$/.test(configName.value)) {
return "The name must only contain letters, numbers, dashes and underscores";
return t("createConfig.validateConfigNameCharacters");
} else if (Object.keys(available_configs.value).includes(configName.value.trim())) {
return "The name must be unique";
return t("createConfig.validateConfigNameUnique");
} else {
return true;
}
Expand Down
15 changes: 10 additions & 5 deletions src/components/EvConfigCanvas.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,21 @@
icon="mdi-code-tags"
/>
</template>
<span>Show config preview</span>
<span>{{ t("evConfigCanvas.showConfigPreviewTooltip") }}</span>
</v-tooltip>
</template>
</config-preview>
<v-tooltip location="left">
<template #activator="{ props }">
<v-btn id="reset-view-button" icon="mdi-undo" color="primary" v-bind="props" @click="reset_view" />
</template>
<span>Reset View</span>
<span>{{ t("evConfigCanvas.resetViewTooltip") }}</span>
</v-tooltip>
<v-tooltip v-if="current_config" location="left">
<template #activator="{ props }">
<v-btn id="config-save-button" icon="mdi-content-save" color="primary" v-bind="props" @click="save_config" />
</template>
<span>Save Config</span>
<span>{{ t("evConfigCanvas.saveConfigTooltip") }}</span>
</v-tooltip>
</div>
</v-sheet>
Expand All @@ -46,6 +46,7 @@ import EVBackendClient from "@/modules/evbc/client";
import { Notyf } from "notyf";
import ConfigPreview from "@/components/ConfigPreview.vue";
import { storeToRefs } from "pinia";
import { useI18n } from "vue-i18n";

export default defineComponent({
components: { ConfigPreview },
Expand All @@ -55,6 +56,7 @@ export default defineComponent({
const selected_interface: string | null = null;
const notyf = inject<Notyf>("notyf");
const { current_config: current_config } = storeToRefs(evbcStore);
const { t } = useI18n({ useScope: "global" });

ref(false);

Expand Down Expand Up @@ -89,10 +91,12 @@ export default defineComponent({
evbc
.save_config(current_config.value)
.then(() => {
notyf.success(`Successfully saved ${current_config.value._name}`);
notyf.success(t("evConfigCanvas.successfullySavedNotification", { config: current_config.value._name }));
})
.catch((error: string) => {
notyf.error(`Failed to save ${current_config.value._name}\nReason: ${error}`);
notyf.error(
t("evConfigCanvas.failedToSaveNotification", { config: current_config.value._name, error: error }),
);
});
};

Expand All @@ -110,6 +114,7 @@ export default defineComponent({
current_config,
reset_view,
save_config,
t,
};
},
});
Expand Down
Loading