Skip to content
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

Routing and styling refactor #27

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions frontend/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ dist
dist-ssr
*.local
.env
.yarn

# Editor directories and files
.vscode/*
Expand Down
5 changes: 3 additions & 2 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"scripts": {
"dev": "vite",
"build": "tsc -b && vite build",
"sheet2i18n": "sheet2i18n src/sheet2i18n.config.cjs",
"sheet2i18n": "node ./sheet2i18n/index.cjs src/sheet2i18n.config.cjs",
"lint": "yarn lint:scripts && yarn lint:styles && yarn lint:editor && yarn prettier --write .",
"lint:scripts": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"lint:styles": "stylelint \"./src/**/*.(scss)\"",
Expand Down Expand Up @@ -48,16 +48,17 @@
"@typescript-eslint/eslint-plugin": "^7.13.1",
"@typescript-eslint/parser": "^7.13.1",
"@vitejs/plugin-react": "^4.3.1",
"csv-parse": "^5.6.0",
"eclint": "^2.8.1",
"eslint": "^8.57.0",
"eslint-plugin-prettier": "^5.1.3",
"eslint-plugin-react": "^7.34.3",
"eslint-plugin-react-hooks": "^4.6.2",
"eslint-plugin-react-refresh": "^0.4.7",
"node-fetch": "^3.3.2",
"postcss": "^8.4.29",
"prettier": "^3.3.2",
"sass": "^1.77.6",
"sheet2i18n": "^1.1.2",
"stylelint": "^16.6.1",
"stylelint-config-prettier-scss": "^1.0.0",
"stylelint-config-standard-scss": "^13.1.0",
Expand Down
20 changes: 20 additions & 0 deletions frontend/sheet2i18n/index.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
"use strict";

const path = require("path");
const sheet2i18n = require("./sheet2i18n.cjs");

const [, , configPathArg] = process.argv;

const configPath = configPathArg || "sheet2i18n.config";
const currentDir = process.cwd();
const resolvedConfigPath = path.resolve(currentDir, configPath);

try {
sheet2i18n(resolvedConfigPath, currentDir);
} catch (error) {
console.error(
`Failed to execute sheet2i18n with config path: ${resolvedConfigPath}`,
);
console.error(error);
process.exit(1);
}
102 changes: 102 additions & 0 deletions frontend/sheet2i18n/sheet2i18n.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
const fs = require("fs").promises;
const path = require("path");
const parseCSV = require("csv-parse/sync");

/**
* Load CSV files, parse them, and generate JSON files for localization.
* @param {string} configPath - Path to the configuration file.
* @param {string} currentDir - Path to the root folder.
*/
async function loadCsv(configPath, currentDir) {
const { exportPath, tabsUrl, localesKey } = require(configPath);

console.log("[+] IMPORTING LOCALES");

try {
const fetch = (await import("node-fetch")).default;

const responses = await Promise.all(
tabsUrl.map(async (urltab) => {
const response = await fetch(urltab);
return await response.text();
}),
);

const resolvedExportPath = path.resolve(currentDir, exportPath);

const rows = responses.flatMap((response) => getParsedCSV(response));
await handleResponse(localesKey, rows, resolvedExportPath);
} catch (error) {
console.error("Error fetching or processing CSV files:", error);
}
}

/**
* Parse a CSV string into an array of objects.
* @param {string} file - CSV file content as a string.
* @returns {Object[]} Parsed CSV data.
*/
function getParsedCSV(file) {
return parseCSV.parse(file, {
columns: (header) => header.map((col) => col.split(" ")[0].toLowerCase()),
});
}

/**
* Handle the parsed CSV data and generate JSON files for each locale.
* @param {string[]} localesKey - Array of locale keys.
* @param {Object[]} rows - Parsed CSV data.
* @param {string} exportPath - Path to export JSON files.
*/
async function handleResponse(localesKey, rows, exportPath) {
await localesKey.forEach(async (localeKey) => {
const content = writeTranslation(localesKey, rows, localeKey);
await createJson(exportPath, localeKey, `{\n${content}\n}\n`);
});
}

/**
* Write translation content for a specific locale.
* @param {string[]} localesKey - Array of locale keys.
* @param {Object[]} rows - Parsed CSV data.
* @param {string} locale - Current locale key.
* @returns {string} Translation content as a JSON string.
*/
function writeTranslation(localesKey, rows, locale) {
const fallback =
localesKey[(localesKey.indexOf(locale) + 1) % localesKey.length];

return rows
.map((row) => {
let { key } = row;
if (!key) return;

key = key.replace(/\s+/g, "");

const newRow =
row[locale]?.replace(/"/g, "'").replace(/(?:\r\n|\r|\n)/g, "<br>") ||
row[fallback];

return newRow ? ` "${key}": "${newRow}"` : undefined;
})
.filter(Boolean)
.join(",\n");
}

/**
* Create a JSON file with the given content.
* @param {string} exportPath - Path to export JSON files.
* @param {string} locale - Locale key.
* @param {string} content - JSON content as a string.
*/
async function createJson(exportPath, locale, content) {
try {
const filePath = `${exportPath}/${locale}.json`;
await fs.writeFile(filePath, content);
console.log(`JSON in ${locale} is saved.`);
} catch (error) {
console.error(`Error saving JSON for ${locale}:`, error);
}
}

module.exports = loadCsv;
4 changes: 2 additions & 2 deletions frontend/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Loading from "@components/loading/Loading";
import CookieConsent from "@containers/cookieConsent/CookieConsent";
import { hasConsent } from "@containers/cookieConsent/cookieConsentHelper";
import CookieConsent from "@components/cookieConsent/CookieConsent";
import { hasConsent } from "@components/cookieConsent/cookieConsentHelper";
import Router from "@routes/Router";
import "@shared/i18n";
import "@styles/index.scss";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import cookieTypes from "@containers/cookieConsent/cookieConsent.config";
import cookieTypes from "./cookieConsent.config";
import {
COOKIE_CONSENT_DURATION,
getCookieConsentPreferences,
setCookiePreferencesInStorage,
} from "@containers/cookieConsent/cookieConsentHelper";
import ICookiePreferences from "@containers/cookieConsent/interfaces/ICookiePreferences";
} from "./cookieConsentHelper";
import ICookiePreferences from "./interfaces/ICookiePreferences";
import { useCallback, useEffect, useState } from "react";
import CookieBanner from "./cookieBanner/CookieBanner";
import CookieModal from "./cookieModal/CookieModal";
Expand Down Expand Up @@ -53,6 +53,7 @@ export default function CookieConsent() {
cookiePreferences={cookiePreferences}
setCookiePreferences={setCookiePreferences}
/>

<CookieBanner
showBanner={cookieBannerOpen}
openModal={() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,10 @@ export default function CookieBanner({
<Slide in={showBanner}>
<div
className={classes["cookie-banner"]}
sx={(theme) => ({ bottom: theme.spacing(2) })}
sx={(theme) => ({
bottom: theme.spacing(2),
zIndex: theme.zIndex.cookieBanner,
})}
>
<StyledContainer className={classes["container"]}>
<div
Expand All @@ -73,11 +76,19 @@ export default function CookieBanner({
<div>
<CookieIcon />
</div>
<div className="flex-column">
<Typography variant="body2" className="mb-xxs">
<div
sx={{
display: "flex",
flexDirection: "column",
}}
>
<Typography
variant="body2"
sx={{ marginBottom: "var(--mui-customProperties-spacing-xxs)" }}
>
{t("cookie_banner__description")}
</Typography>
<div className="mr-a">
<div sx={{ marginRight: "auto" }}>
<Link
href={t("cookie_consent_link")}
underline="always"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import ICookiePreferences from "@containers/cookieConsent/interfaces/ICookiePreferences";
import ICookiePreferences from "./interfaces/ICookiePreferences";

export const COOKIE_PREFERENCES = "COOKIE_PREFERENCES";
export const COOKIE_CONSENT_DURATION = 1000 * 60 * 60 * 24 * 365;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import Switch from "@components/switch/Switch";
import Table from "@components/table/Table";
import TableRow from "@components/tableRow/TableRow";
import Typography from "@mui/material/Typography";
import ICookieSection from "@containers/cookieConsent/interfaces/ICookieSection";
import ICookieSection from "@components/cookieConsent/interfaces/ICookieSection";
import CloseIcon from "@icons/CloseIcon";
import {
Dispatch,
Expand Down Expand Up @@ -64,10 +64,23 @@ export default function CookieModal({
);

return (
<Dialog open={open} onClose={closeModal} maxWidth="xs">
<div className="m-lg">
<div className="flex-column gap-md mb-md">
<div className="flex align-center justify-between">
<Dialog open={open} onClose={closeModal} maxWidth="sm">
<div sx={(theme) => ({ margin: theme.customProperties.spacing.lg })}>
<div
sx={(theme) => ({
display: "flex",
flexDirection: "column",
gap: theme.customProperties.spacing.md,
marginBottom: theme.customProperties.spacing.md,
})}
>
<div
sx={{
display: "flex",
alignItems: "center",
justifyContent: "space-between",
}}
>
<Typography variant="h5">{t("cookie_modal__title")}</Typography>
<IconButton aria-label={t("global__close")} onClick={closeModal}>
<CloseIcon />
Expand All @@ -80,7 +93,7 @@ export default function CookieModal({
{t("cookie_modal__description_2")}
</Typography>
<Link
className="mr-a"
sx={(theme) => ({ marginRight: theme.customProperties.spacing.a })}
href={t("cookie_consent_link")}
underline="always"
external
Expand All @@ -90,7 +103,13 @@ export default function CookieModal({
</Typography>
</Link>
</div>
<div className="flex-column gap-lg">
<div
sx={(theme) => ({
display: "flex",
flexDirection: "column",
gap: theme.customProperties.spacing.lg,
})}
>
<Typography variant="body2">
{t("cookie_modal__description_3")}
</Typography>
Expand All @@ -103,7 +122,12 @@ export default function CookieModal({
onChange={handleExpand(index)}
>
<AccordionSummary>
<Typography variant="h6" className="mr-a">
<Typography
variant="h6"
sx={(theme) => ({
marginRight: theme.customProperties.spacing.a,
})}
>
{t(cookieType.title)}
</Typography>
<Switch
Expand All @@ -121,13 +145,20 @@ export default function CookieModal({
<Typography
variant="body2"
key={index}
className="mx-md mb-md"
sx={(theme) => ({
marginX: theme.customProperties.spacing.md,
marginBottom: theme.customProperties.spacing.md,
})}
>
{t(description)}
</Typography>
))}
{cookieType.cookies && (
<div className="m-md">
<div
sx={(theme) => ({
margin: theme.customProperties.spacing.md,
})}
>
<Table
columnTitles={[
t("cookie_modal__cookie_name"),
Expand All @@ -152,7 +183,14 @@ export default function CookieModal({
))}
</div>

<div className="flex-column justify-center gap-sm">
<div
sx={(theme) => ({
display: "flex",
flexDirection: "column",
gap: theme.customProperties.spacing.sm,
justifyContent: "center",
})}
>
<Button variant="contained" onClick={handleAcceptSelection}>
{t("cookie_modal__allow_selection")}
</Button>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export default function DebugBanner() {
const pages = [
{
name: t(homeRoute.name),
to: homeRoute.paths[t("locale__key")],
to: `${homeRoute.paths[t("locale__key")]}`,
},
{
name: t(uikitRoute.name),
Expand All @@ -42,11 +42,13 @@ export default function DebugBanner() {
}

return (
<div className={"container"}>
<div
className={classes["container"]}
sx={(theme) => ({
zIndex: theme.zIndex.debugBanner,
})}
>
<div
sx={(theme) => ({
zIndex: theme.zIndex.debugBanner,
})}
className={classNames(classes["content"], {
[classes["local"]]: __ENV__ === "local",
[classes["dev"]]: __ENV__ === "dev",
Expand All @@ -63,9 +65,7 @@ export default function DebugBanner() {
))}
</div>

<Button size="small" onClick={closeBanner}>
{t("global__hide")}
</Button>
<Button onClick={closeBanner}>{t("global__hide")}</Button>
</div>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,13 @@ export default function FieldHelperText({
}

return (
<Typography variant="caption" className="mt-xxs ml-md">
<Typography
variant="caption"
sx={(theme) => ({
marginTop: theme.customProperties.spacing.xxs,
marginLeft: theme.customProperties.spacing.md,
})}
>
{helperText}
</Typography>
);
Expand Down
Loading
Loading