From 36203af229285d3bbae990b010a226f3b689a68d Mon Sep 17 00:00:00 2001 From: Lucas Marques Date: Tue, 29 Oct 2024 10:43:49 +0100 Subject: [PATCH] feat(ui): fix eslint config and add prettier (#368) --- .github/workflows/ci.yaml | 30 +- ui/.eslintrc.cjs | 18 - ui/.prettierrc | 6 + ui/eslint.config.mjs | 31 + ui/package.json | 12 +- ui/postcss.config.js | 6 +- ui/src/App.tsx | 48 +- ui/src/assets/avocado/AvocadoOff.tsx | 2 +- ui/src/assets/avocado/AvocadoOn.tsx | 2 +- ui/src/assets/avocado/AvocadoSeed.tsx | 2 +- ui/src/assets/icons/AngleDownIcon.tsx | 2 +- ui/src/assets/icons/AppsIcon.tsx | 2 +- ui/src/assets/icons/ArrowLeftIcon.tsx | 2 +- .../assets/icons/ArrowResizeDiagonalIcon.tsx | 2 +- ui/src/assets/icons/ArrowRightIcon.tsx | 2 +- ui/src/assets/icons/BarsIcon.tsx | 2 +- ui/src/assets/icons/CheckIcon.tsx | 2 +- ui/src/assets/icons/CodeBranchIcon.tsx | 2 +- ui/src/assets/icons/CopyIcon.tsx | 2 +- ui/src/assets/icons/DownloadAltIcon.tsx | 2 +- .../assets/icons/ExclamationTriangleIcon.tsx | 2 +- ui/src/assets/icons/EyeIcon.tsx | 2 +- ui/src/assets/icons/EyeSlashIcon.tsx | 2 +- ui/src/assets/icons/GithubIcon.tsx | 2 +- ui/src/assets/icons/GitlabIcon.tsx | 2 +- ui/src/assets/icons/LayerGroupIcon.tsx | 2 +- ui/src/assets/icons/LoaderIcon.tsx | 2 +- ui/src/assets/icons/MinusIcon.tsx | 2 +- ui/src/assets/icons/MultiplyIcon.tsx | 2 +- ui/src/assets/icons/SearchIcon.tsx | 2 +- ui/src/assets/icons/SyncIcon.tsx | 2 +- ui/src/assets/icons/TimesIcon.tsx | 2 +- ui/src/assets/icons/WindowIcon.tsx | 2 +- ui/src/assets/illustrations/Burrito.tsx | 2 +- ui/src/assets/illustrations/ChiliDark.tsx | 4 +- ui/src/assets/illustrations/ChiliLight.tsx | 4 +- ui/src/assets/illustrations/Sombrero.tsx | 4 +- ui/src/clients/layers/client.ts | 6 +- ui/src/clients/layers/types.ts | 4 +- ui/src/clients/logs/client.ts | 11 +- ui/src/clients/reactQueryConfig.ts | 19 +- ui/src/clients/repositories/client.ts | 4 +- ui/src/clients/runs/client.ts | 10 +- ui/src/components/buttons/AttemptButton.tsx | 20 +- .../components/buttons/GenericIconButton.tsx | 29 +- ui/src/components/buttons/LogsButton.tsx | 16 +- .../components/buttons/OpenInLogsButton.tsx | 12 +- ui/src/components/buttons/SocialButton.tsx | 16 +- ui/src/components/cards/Card.tsx | 86 +- ui/src/components/cards/RunCard.tsx | 32 +- ui/src/components/core/Box.tsx | 12 +- ui/src/components/core/Button.tsx | 38 +- ui/src/components/core/Checkbox.tsx | 20 +- ui/src/components/core/Dropdown.tsx | 16 +- ui/src/components/core/Input.tsx | 34 +- ui/src/components/core/Toggle.tsx | 30 +- .../components/dropdowns/AttemptsDropdown.tsx | 56 +- ui/src/components/dropdowns/DateDropdown.tsx | 60 +- .../dropdowns/PaginationDropdown.tsx | 59 +- .../dropdowns/RepositoriesDropdown.tsx | 64 +- .../components/dropdowns/StatesDropdown.tsx | 56 +- ui/src/components/loaders/CardLoader.tsx | 10 +- ui/src/components/loaders/RunCardLoader.tsx | 10 +- ui/src/components/loaders/TableLoader.tsx | 10 +- ui/src/components/misc/ProfilePicture.tsx | 16 +- ui/src/components/misc/ThemeToggle.tsx | 24 +- .../components/navigation/NavigationBar.tsx | 28 +- .../navigation/NavigationButton.tsx | 14 +- .../components/navigation/NavigationLink.tsx | 10 +- ui/src/components/tables/Table.tsx | 142 +-- ui/src/components/temp/TrafficCone.tsx | 14 +- ui/src/components/tools/LayerChecklist.tsx | 177 +-- ui/src/components/tools/LogsTerminal.tsx | 62 +- ui/src/components/tools/ModalLogsTerminal.tsx | 30 +- ui/src/components/widgets/ProgressBar.tsx | 17 +- ui/src/components/widgets/Running.tsx | 4 +- ui/src/components/widgets/Tag.tsx | 22 +- ui/src/contexts/ThemeContext.tsx | 28 +- ui/src/layout/Layout.tsx | 10 +- ui/src/main.tsx | 10 +- ui/src/modals/SlidingPane.tsx | 13 +- ui/src/pages/Layers.tsx | 234 ++-- ui/src/pages/Login.tsx | 60 +- ui/src/pages/Logs.tsx | 122 +- ui/src/pages/Pulls.tsx | 8 +- ui/tailwind.config.js | 84 +- ui/yarn.lock | 1004 ++++++++++++++++- 87 files changed, 2111 insertions(+), 979 deletions(-) delete mode 100644 ui/.eslintrc.cjs create mode 100644 ui/.prettierrc create mode 100644 ui/eslint.config.mjs diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 529098a1..d69d24cb 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -58,8 +58,8 @@ jobs: run: | git diff --exit-code ./manifests - lint: - name: Lint + lint-go: + name: Lint Go runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 @@ -73,5 +73,29 @@ jobs: version: v1.55 args: --timeout=5m + lint-ts: + name: Lint TS + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 20 + - name: Run install + uses: borales/actions-yarn@v4 + with: + cmd: install + dir: ui + - name: Run eslint + uses: borales/actions-yarn@v5 + with: + cmd: lint + dir: ui + - name: Run prettier + uses: borales/actions-yarn@v5 + with: + cmd: format-check + dir: ui + build-and-push: - uses: ./.github/workflows/build-and-push.yaml \ No newline at end of file + uses: ./.github/workflows/build-and-push.yaml diff --git a/ui/.eslintrc.cjs b/ui/.eslintrc.cjs deleted file mode 100644 index d6c95379..00000000 --- a/ui/.eslintrc.cjs +++ /dev/null @@ -1,18 +0,0 @@ -module.exports = { - root: true, - env: { browser: true, es2020: true }, - extends: [ - 'eslint:recommended', - 'plugin:@typescript-eslint/recommended', - 'plugin:react-hooks/recommended', - ], - ignorePatterns: ['dist', '.eslintrc.cjs'], - parser: '@typescript-eslint/parser', - plugins: ['react-refresh'], - rules: { - 'react-refresh/only-export-components': [ - 'warn', - { allowConstantExport: true }, - ], - }, -} diff --git a/ui/.prettierrc b/ui/.prettierrc new file mode 100644 index 00000000..93462e6d --- /dev/null +++ b/ui/.prettierrc @@ -0,0 +1,6 @@ +{ + "semi": true, + "trailingComma": "none", + "singleQuote": true, + "printWidth": 80 +} diff --git a/ui/eslint.config.mjs b/ui/eslint.config.mjs new file mode 100644 index 00000000..1280e55a --- /dev/null +++ b/ui/eslint.config.mjs @@ -0,0 +1,31 @@ +import reactPlugin from 'eslint-plugin-react'; +import hooksPlugin from 'eslint-plugin-react-hooks'; +import tseslint from 'typescript-eslint'; +import eslint from '@eslint/js'; + +export default [ + { + plugins: { + react: reactPlugin, + }, + rules: { + ...reactPlugin.configs['jsx-runtime'].rules, + }, + settings: { + react: { + version: 'detect', + }, + }, + }, + { + plugins: { + 'react-hooks': hooksPlugin, + }, + rules: hooksPlugin.configs.recommended.rules, + }, + eslint.configs.recommended, + ...tseslint.configs.recommended, + { + ignores: ['**/dist'], + }, +]; diff --git a/ui/package.json b/ui/package.json index 27a181fe..4573ef71 100644 --- a/ui/package.json +++ b/ui/package.json @@ -6,8 +6,10 @@ "scripts": { "dev": "vite", "build": "tsc && vite build", - "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", - "preview": "vite preview" + "lint": "eslint -c eslint.config.mjs ./src/**/*.{ts,tsx} --report-unused-disable-directives --max-warnings 0 .", + "preview": "vite preview", + "format": "prettier --config .prettierrc 'src/**/*.{ts,tsx}' --write", + "format-check": "prettier --config .prettierrc 'src/**/*.{ts,tsx}' --check" }, "dependencies": { "@floating-ui/react": "^0.26.9", @@ -22,6 +24,7 @@ "tailwind-merge": "^2.0.0" }, "devDependencies": { + "@eslint/compat": "^1.2.1", "@types/react": "^18.3.11", "@types/react-dom": "^18.3.0", "@typescript-eslint/eslint-plugin": "^7.1.0", @@ -29,11 +32,16 @@ "@vitejs/plugin-react-swc": "^3.7.0", "autoprefixer": "^10.4.19", "eslint": "^8.57.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-prettier": "^5.2.1", + "eslint-plugin-react": "^7.37.2", "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-refresh": "^0.4.13", "postcss": "^8.4.38", + "prettier": "3.3.3", "tailwindcss": "^3.4.4", "typescript": "^5.3.3", + "typescript-eslint": "^8.11.0", "vite": "^5.4.9" } } diff --git a/ui/postcss.config.js b/ui/postcss.config.js index 2e7af2b7..ba807304 100644 --- a/ui/postcss.config.js +++ b/ui/postcss.config.js @@ -1,6 +1,6 @@ export default { plugins: { tailwindcss: {}, - autoprefixer: {}, - }, -} + autoprefixer: {} + } +}; diff --git a/ui/src/App.tsx b/ui/src/App.tsx index a64b337c..2f25af4d 100644 --- a/ui/src/App.tsx +++ b/ui/src/App.tsx @@ -1,50 +1,50 @@ -import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; +import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { createBrowserRouter, RouterProvider, - Navigate, -} from "react-router-dom"; + Navigate +} from 'react-router-dom'; -import ThemeProvider from "@/contexts/ThemeContext"; +import ThemeProvider from '@/contexts/ThemeContext'; -import Layout from "@/layout/Layout"; -import Layers from "@/pages/Layers"; -import Pulls from "@/pages/Pulls"; -import Logs from "@/pages/Logs"; -import Login from "@/pages/Login"; +import Layout from '@/layout/Layout'; +import Layers from '@/pages/Layers'; +import Pulls from '@/pages/Pulls'; +import Logs from '@/pages/Logs'; +import Login from '@/pages/Login'; const queryClient = new QueryClient(); const router = createBrowserRouter([ { - path: "/", + path: '/', element: , children: [ { index: true, - element: , + element: }, { - path: "layers", - element: , + path: 'layers', + element: }, { - path: "pulls", - element: , + path: 'pulls', + element: }, { - path: "logs/:namespace?/:layerId?/:runId?", - element: , - }, - ], + path: 'logs/:namespace?/:layerId?/:runId?', + element: + } + ] }, { - path: "/login", - element: , + path: '/login', + element: }, { - path: "*", - element: , - }, + path: '*', + element: + } ]); function App() { diff --git a/ui/src/assets/avocado/AvocadoOff.tsx b/ui/src/assets/avocado/AvocadoOff.tsx index 69998b29..24f3e325 100644 --- a/ui/src/assets/avocado/AvocadoOff.tsx +++ b/ui/src/assets/avocado/AvocadoOff.tsx @@ -1,4 +1,4 @@ -import { SVGProps } from "react"; +import { SVGProps } from 'react'; const AvocadoOff = (props: SVGProps) => ( ) => ( ) => ( ) => ( diff --git a/ui/src/assets/icons/AppsIcon.tsx b/ui/src/assets/icons/AppsIcon.tsx index 96ea3731..e479f936 100644 --- a/ui/src/assets/icons/AppsIcon.tsx +++ b/ui/src/assets/icons/AppsIcon.tsx @@ -1,4 +1,4 @@ -import { SVGProps } from "react"; +import { SVGProps } from 'react'; const AppsIcon = (props: SVGProps) => ( diff --git a/ui/src/assets/icons/ArrowLeftIcon.tsx b/ui/src/assets/icons/ArrowLeftIcon.tsx index e68e576e..818bcdc6 100644 --- a/ui/src/assets/icons/ArrowLeftIcon.tsx +++ b/ui/src/assets/icons/ArrowLeftIcon.tsx @@ -1,4 +1,4 @@ -import { SVGProps } from "react"; +import { SVGProps } from 'react'; const ArrowLeftIcon = (props: SVGProps) => ( diff --git a/ui/src/assets/icons/ArrowResizeDiagonalIcon.tsx b/ui/src/assets/icons/ArrowResizeDiagonalIcon.tsx index be6097b8..b35ce792 100644 --- a/ui/src/assets/icons/ArrowResizeDiagonalIcon.tsx +++ b/ui/src/assets/icons/ArrowResizeDiagonalIcon.tsx @@ -1,4 +1,4 @@ -import { SVGProps } from "react"; +import { SVGProps } from 'react'; const ArrowResizeDiagonalIcon = (props: SVGProps) => ( diff --git a/ui/src/assets/icons/ArrowRightIcon.tsx b/ui/src/assets/icons/ArrowRightIcon.tsx index d005ecd5..56d763ea 100644 --- a/ui/src/assets/icons/ArrowRightIcon.tsx +++ b/ui/src/assets/icons/ArrowRightIcon.tsx @@ -1,4 +1,4 @@ -import { SVGProps } from "react"; +import { SVGProps } from 'react'; const ArrowRightIcon = (props: SVGProps) => ( diff --git a/ui/src/assets/icons/BarsIcon.tsx b/ui/src/assets/icons/BarsIcon.tsx index 837086c1..6971f83b 100644 --- a/ui/src/assets/icons/BarsIcon.tsx +++ b/ui/src/assets/icons/BarsIcon.tsx @@ -1,4 +1,4 @@ -import { SVGProps } from "react"; +import { SVGProps } from 'react'; const BarsIcon = (props: SVGProps) => ( diff --git a/ui/src/assets/icons/CheckIcon.tsx b/ui/src/assets/icons/CheckIcon.tsx index a3275233..ce685935 100644 --- a/ui/src/assets/icons/CheckIcon.tsx +++ b/ui/src/assets/icons/CheckIcon.tsx @@ -1,4 +1,4 @@ -import { SVGProps } from "react"; +import { SVGProps } from 'react'; const CheckIcon = (props: SVGProps) => ( diff --git a/ui/src/assets/icons/CodeBranchIcon.tsx b/ui/src/assets/icons/CodeBranchIcon.tsx index 3fd4a2a2..c377e207 100644 --- a/ui/src/assets/icons/CodeBranchIcon.tsx +++ b/ui/src/assets/icons/CodeBranchIcon.tsx @@ -1,4 +1,4 @@ -import { SVGProps } from "react"; +import { SVGProps } from 'react'; const CodeBranchIcon = (props: SVGProps) => ( diff --git a/ui/src/assets/icons/CopyIcon.tsx b/ui/src/assets/icons/CopyIcon.tsx index 9875f8bb..c302e6d6 100644 --- a/ui/src/assets/icons/CopyIcon.tsx +++ b/ui/src/assets/icons/CopyIcon.tsx @@ -1,4 +1,4 @@ -import { SVGProps } from "react"; +import { SVGProps } from 'react'; const CopyIcon = (props: SVGProps) => ( diff --git a/ui/src/assets/icons/DownloadAltIcon.tsx b/ui/src/assets/icons/DownloadAltIcon.tsx index 5fd7403f..c004634f 100644 --- a/ui/src/assets/icons/DownloadAltIcon.tsx +++ b/ui/src/assets/icons/DownloadAltIcon.tsx @@ -1,4 +1,4 @@ -import { SVGProps } from "react"; +import { SVGProps } from 'react'; const DownloadAltIcon = (props: SVGProps) => ( diff --git a/ui/src/assets/icons/ExclamationTriangleIcon.tsx b/ui/src/assets/icons/ExclamationTriangleIcon.tsx index 882ccb44..7d1b2fba 100644 --- a/ui/src/assets/icons/ExclamationTriangleIcon.tsx +++ b/ui/src/assets/icons/ExclamationTriangleIcon.tsx @@ -1,4 +1,4 @@ -import { SVGProps } from "react"; +import { SVGProps } from 'react'; const ExclamationTriangleIcon = (props: SVGProps) => ( diff --git a/ui/src/assets/icons/EyeIcon.tsx b/ui/src/assets/icons/EyeIcon.tsx index ec5e5939..5e4ab2f7 100644 --- a/ui/src/assets/icons/EyeIcon.tsx +++ b/ui/src/assets/icons/EyeIcon.tsx @@ -1,4 +1,4 @@ -import { SVGProps } from "react"; +import { SVGProps } from 'react'; const EyeIcon = (props: SVGProps) => ( diff --git a/ui/src/assets/icons/EyeSlashIcon.tsx b/ui/src/assets/icons/EyeSlashIcon.tsx index b1d2ee5f..b126e483 100644 --- a/ui/src/assets/icons/EyeSlashIcon.tsx +++ b/ui/src/assets/icons/EyeSlashIcon.tsx @@ -1,4 +1,4 @@ -import { SVGProps } from "react"; +import { SVGProps } from 'react'; const EyeSlashIcon = (props: SVGProps) => ( diff --git a/ui/src/assets/icons/GithubIcon.tsx b/ui/src/assets/icons/GithubIcon.tsx index 4fbd283a..c343dd10 100644 --- a/ui/src/assets/icons/GithubIcon.tsx +++ b/ui/src/assets/icons/GithubIcon.tsx @@ -1,4 +1,4 @@ -import { SVGProps } from "react"; +import { SVGProps } from 'react'; const GithubIcon = (props: SVGProps) => ( diff --git a/ui/src/assets/icons/GitlabIcon.tsx b/ui/src/assets/icons/GitlabIcon.tsx index 5779efd4..61496209 100644 --- a/ui/src/assets/icons/GitlabIcon.tsx +++ b/ui/src/assets/icons/GitlabIcon.tsx @@ -1,4 +1,4 @@ -import { SVGProps } from "react"; +import { SVGProps } from 'react'; const GitlabIcon = (props: SVGProps) => ( ) => ( diff --git a/ui/src/assets/icons/LoaderIcon.tsx b/ui/src/assets/icons/LoaderIcon.tsx index f4718e8c..820aa66c 100644 --- a/ui/src/assets/icons/LoaderIcon.tsx +++ b/ui/src/assets/icons/LoaderIcon.tsx @@ -1,4 +1,4 @@ -import { SVGProps } from "react"; +import { SVGProps } from 'react'; const LoaderIcon = (props: SVGProps) => ( diff --git a/ui/src/assets/icons/MinusIcon.tsx b/ui/src/assets/icons/MinusIcon.tsx index 9f3d5505..1fd38ab3 100644 --- a/ui/src/assets/icons/MinusIcon.tsx +++ b/ui/src/assets/icons/MinusIcon.tsx @@ -1,4 +1,4 @@ -import { SVGProps } from "react"; +import { SVGProps } from 'react'; const MinusIcon = (props: SVGProps) => ( diff --git a/ui/src/assets/icons/MultiplyIcon.tsx b/ui/src/assets/icons/MultiplyIcon.tsx index 31cec907..fae0d990 100644 --- a/ui/src/assets/icons/MultiplyIcon.tsx +++ b/ui/src/assets/icons/MultiplyIcon.tsx @@ -1,4 +1,4 @@ -import { SVGProps } from "react"; +import { SVGProps } from 'react'; const MultiplyIcon = (props: SVGProps) => ( diff --git a/ui/src/assets/icons/SearchIcon.tsx b/ui/src/assets/icons/SearchIcon.tsx index 16d1068c..a01cb8b3 100644 --- a/ui/src/assets/icons/SearchIcon.tsx +++ b/ui/src/assets/icons/SearchIcon.tsx @@ -1,4 +1,4 @@ -import { SVGProps } from "react"; +import { SVGProps } from 'react'; const SearchIcon = (props: SVGProps) => ( diff --git a/ui/src/assets/icons/SyncIcon.tsx b/ui/src/assets/icons/SyncIcon.tsx index 6381fd19..2195cb21 100644 --- a/ui/src/assets/icons/SyncIcon.tsx +++ b/ui/src/assets/icons/SyncIcon.tsx @@ -1,4 +1,4 @@ -import { SVGProps } from "react"; +import { SVGProps } from 'react'; const SyncIcon = (props: SVGProps) => ( diff --git a/ui/src/assets/icons/TimesIcon.tsx b/ui/src/assets/icons/TimesIcon.tsx index 60f7079a..c3e7f294 100644 --- a/ui/src/assets/icons/TimesIcon.tsx +++ b/ui/src/assets/icons/TimesIcon.tsx @@ -1,4 +1,4 @@ -import { SVGProps } from "react"; +import { SVGProps } from 'react'; const TimesIcon = (props: SVGProps) => ( diff --git a/ui/src/assets/icons/WindowIcon.tsx b/ui/src/assets/icons/WindowIcon.tsx index 6ed2926e..337a67d9 100644 --- a/ui/src/assets/icons/WindowIcon.tsx +++ b/ui/src/assets/icons/WindowIcon.tsx @@ -1,4 +1,4 @@ -import { SVGProps } from "react"; +import { SVGProps } from 'react'; const WindowIcon = (props: SVGProps) => ( diff --git a/ui/src/assets/illustrations/Burrito.tsx b/ui/src/assets/illustrations/Burrito.tsx index c13c2926..cc87250e 100644 --- a/ui/src/assets/illustrations/Burrito.tsx +++ b/ui/src/assets/illustrations/Burrito.tsx @@ -1,4 +1,4 @@ -import { SVGProps } from "react"; +import { SVGProps } from 'react'; const Burrito = (props: SVGProps) => ( ) => ( ) => ( y={135} maskUnits="userSpaceOnUse" style={{ - maskType: "alpha", + maskType: 'alpha' }} > ) => ( ) => ( y={135} maskUnits="userSpaceOnUse" style={{ - maskType: "alpha", + maskType: 'alpha' }} > ) => ( ) => ( y={246} maskUnits="userSpaceOnUse" style={{ - maskType: "alpha", + maskType: 'alpha' }} > { const response = await axios.get( @@ -14,4 +14,4 @@ export const syncLayer = async (namespace: string, name: string) => { `${import.meta.env.VITE_API_BASE_URL}/layers/${namespace}/${name}/sync` ); return response; -} +}; diff --git a/ui/src/clients/layers/types.ts b/ui/src/clients/layers/types.ts index 2704d6bf..9220c235 100644 --- a/ui/src/clients/layers/types.ts +++ b/ui/src/clients/layers/types.ts @@ -19,8 +19,8 @@ export type Layer = { isPR: boolean; }; -export type LayerState = "success" | "warning" | "error" | "disabled"; -export type ManualSyncStatus = "none" | "annotated" | "pending"; +export type LayerState = 'success' | 'warning' | 'error' | 'disabled'; +export type ManualSyncStatus = 'none' | 'annotated' | 'pending'; export type Run = { id: string; diff --git a/ui/src/clients/logs/client.ts b/ui/src/clients/logs/client.ts index c4fa46be..7c9a687d 100644 --- a/ui/src/clients/logs/client.ts +++ b/ui/src/clients/logs/client.ts @@ -1,8 +1,13 @@ -import axios from "axios"; +import axios from 'axios'; -import { Logs } from "@/clients/logs/types.ts"; +import { Logs } from '@/clients/logs/types.ts'; -export const fetchLogs = async (namespace: string, layer: string, runId: string, attemptId: number | null) => { +export const fetchLogs = async ( + namespace: string, + layer: string, + runId: string, + attemptId: number | null +) => { const response = await axios.get( `${import.meta.env.VITE_API_BASE_URL}/logs/${namespace}/${layer}/${runId}/${attemptId}` ); diff --git a/ui/src/clients/reactQueryConfig.ts b/ui/src/clients/reactQueryConfig.ts index 4d9bd64f..1cfb0475 100644 --- a/ui/src/clients/reactQueryConfig.ts +++ b/ui/src/clients/reactQueryConfig.ts @@ -1,6 +1,17 @@ export const reactQueryKeys = { - layers: ["layers"], - repositories: ["repositories"], - attempts: (namespace: string, layer: string, runId: string) => ["run", namespace, layer, runId, "attempts"], - logs: (namespace: string, layer: string, runId: string, attemptId: number | null) => ["logs", namespace, layer, runId, attemptId], + layers: ['layers'], + repositories: ['repositories'], + attempts: (namespace: string, layer: string, runId: string) => [ + 'run', + namespace, + layer, + runId, + 'attempts' + ], + logs: ( + namespace: string, + layer: string, + runId: string, + attemptId: number | null + ) => ['logs', namespace, layer, runId, attemptId] }; diff --git a/ui/src/clients/repositories/client.ts b/ui/src/clients/repositories/client.ts index e4b3eb78..6316642d 100644 --- a/ui/src/clients/repositories/client.ts +++ b/ui/src/clients/repositories/client.ts @@ -1,6 +1,6 @@ -import axios from "axios"; +import axios from 'axios'; -import { Repositories } from "@/clients/repositories/types.ts"; +import { Repositories } from '@/clients/repositories/types.ts'; export const fetchRepositories = async () => { const response = await axios.get( diff --git a/ui/src/clients/runs/client.ts b/ui/src/clients/runs/client.ts index 950e3749..f1dd5921 100644 --- a/ui/src/clients/runs/client.ts +++ b/ui/src/clients/runs/client.ts @@ -1,8 +1,12 @@ -import axios from "axios"; +import axios from 'axios'; -import { Attempts } from "@/clients/runs/types.ts"; +import { Attempts } from '@/clients/runs/types.ts'; -export const fetchAttempts = async (namespace: string, layer: string, runId: string) => { +export const fetchAttempts = async ( + namespace: string, + layer: string, + runId: string +) => { const response = await axios.get( `${import.meta.env.VITE_API_BASE_URL}/run/${namespace}/${layer}/${runId}/attempts` ); diff --git a/ui/src/components/buttons/AttemptButton.tsx b/ui/src/components/buttons/AttemptButton.tsx index be36f8ac..d374ede7 100644 --- a/ui/src/components/buttons/AttemptButton.tsx +++ b/ui/src/components/buttons/AttemptButton.tsx @@ -1,11 +1,11 @@ -import React from "react"; -import { twMerge } from "tailwind-merge"; +import React from 'react'; +import { twMerge } from 'tailwind-merge'; -import TimesIcon from "@/assets/icons/TimesIcon"; +import TimesIcon from '@/assets/icons/TimesIcon'; export interface AttemptButtonProps { className?: string; - variant?: "light" | "dark"; + variant?: 'light' | 'dark'; attempt: number; isActive?: boolean; onClick?: () => void; @@ -14,11 +14,11 @@ export interface AttemptButtonProps { const AttemptButton: React.FC = ({ className, - variant = "light", + variant = 'light', attempt, isActive, onClick, - onClose, + onClose }) => { const styles = { base: { @@ -28,7 +28,7 @@ const AttemptButton: React.FC = ({ dark: `bg-nuances-300 text-nuances-400 - fill-nuances-400`, + fill-nuances-400` }, isActive: { @@ -38,13 +38,13 @@ const AttemptButton: React.FC = ({ dark: `bg-nuances-black text-nuances-white - fill-nuances-50`, - }, + fill-nuances-50` + } }; const handleClose = (e: React.MouseEvent) => { e.stopPropagation(); - onClose && onClose(); + onClose?.(); }; return ( diff --git a/ui/src/components/buttons/GenericIconButton.tsx b/ui/src/components/buttons/GenericIconButton.tsx index ba535b26..b6ef38c9 100644 --- a/ui/src/components/buttons/GenericIconButton.tsx +++ b/ui/src/components/buttons/GenericIconButton.tsx @@ -1,9 +1,9 @@ -import React from "react"; -import { twMerge } from "tailwind-merge"; -import { Tooltip } from "react-tooltip"; +import React from 'react'; +import { twMerge } from 'tailwind-merge'; +import { Tooltip } from 'react-tooltip'; export interface GenericIconButtonProps { className?: string; - variant?: "light" | "dark"; + variant?: 'light' | 'dark'; disabled?: boolean; tooltip?: string; width?: number; @@ -12,7 +12,6 @@ export interface GenericIconButtonProps { Icon: React.FC>; } - const GenericIconButton: React.FC = ({ className, variant, @@ -23,13 +22,17 @@ const GenericIconButton: React.FC = ({ height = 40, Icon }) => { - const hoverClass = !disabled ? (variant === "light" ? "hover:bg-primary-300" : "hover:bg-nuances-black") : ""; + const hoverClass = !disabled + ? variant === 'light' + ? 'hover:bg-primary-300' + : 'hover:bg-nuances-black' + : ''; return (
); diff --git a/ui/src/components/buttons/LogsButton.tsx b/ui/src/components/buttons/LogsButton.tsx index 38844f21..a91fca5c 100644 --- a/ui/src/components/buttons/LogsButton.tsx +++ b/ui/src/components/buttons/LogsButton.tsx @@ -1,23 +1,23 @@ -import React from "react"; -import { twMerge } from "tailwind-merge"; +import React from 'react'; +import { twMerge } from 'tailwind-merge'; -import WindowIcon from "@/assets/icons/WindowIcon"; +import WindowIcon from '@/assets/icons/WindowIcon'; export interface LogsButtonProps extends React.HTMLAttributes { className?: string; - variant?: "light" | "dark"; + variant?: 'light' | 'dark'; } const LogsButton = React.forwardRef( - ({ className, variant = "light", ...props }, ref) => { + ({ className, variant = 'light', ...props }, ref) => { return ( ))} diff --git a/ui/src/components/dropdowns/RepositoriesDropdown.tsx b/ui/src/components/dropdowns/RepositoriesDropdown.tsx index 6fad8f2f..98de7a78 100644 --- a/ui/src/components/dropdowns/RepositoriesDropdown.tsx +++ b/ui/src/components/dropdowns/RepositoriesDropdown.tsx @@ -1,5 +1,5 @@ -import React, { useState, useRef } from "react"; -import { twMerge } from "tailwind-merge"; +import React, { useState, useRef } from 'react'; +import { twMerge } from 'tailwind-merge'; import { useFloating, useClick, @@ -12,20 +12,20 @@ import { flip, size, autoUpdate, - FloatingPortal, -} from "@floating-ui/react"; -import { useQuery } from "@tanstack/react-query"; + FloatingPortal +} from '@floating-ui/react'; +import { useQuery } from '@tanstack/react-query'; -import { fetchRepositories } from "@/clients/repositories/client"; -import { reactQueryKeys } from "@/clients/reactQueryConfig"; +import { fetchRepositories } from '@/clients/repositories/client'; +import { reactQueryKeys } from '@/clients/reactQueryConfig'; -import Dropdown from "@/components/core/Dropdown"; -import Input from "@/components/core/Input"; -import Checkbox from "@/components/core/Checkbox"; +import Dropdown from '@/components/core/Dropdown'; +import Input from '@/components/core/Input'; +import Checkbox from '@/components/core/Checkbox'; export interface RepositoriesDropdownProps { className?: string; - variant?: "light" | "dark"; + variant?: 'light' | 'dark'; disabled?: boolean; selectedRepositories: string[]; setSelectedRepositories: (repositories: string[]) => void; @@ -33,19 +33,19 @@ export interface RepositoriesDropdownProps { const RepositoriesDropdown: React.FC = ({ className, - variant = "light", + variant = 'light', disabled, selectedRepositories, - setSelectedRepositories, + setSelectedRepositories }) => { const [isOpen, setIsOpen] = useState(false); - const [search, setSearch] = useState(""); + const [search, setSearch] = useState(''); const [activeIndex, setActiveIndex] = useState(null); const listElementsRef = useRef>([]); const { refs, floatingStyles, context } = useFloating({ - placement: "bottom-start", + placement: 'bottom-start', open: isOpen, onOpenChange: setIsOpen, whileElementsMounted: autoUpdate, @@ -56,23 +56,23 @@ const RepositoriesDropdown: React.FC = ({ apply({ availableHeight, elements }) { elements.floating.style.maxHeight = `${availableHeight}px`; }, - padding: 8, - }), - ], + padding: 8 + }) + ] }); const click = useClick(context, { enabled: !disabled, - event: "mousedown", + event: 'mousedown' }); const listNavigation = useListNavigation(context, { enabled: !disabled, listRef: listElementsRef, activeIndex: activeIndex, - onNavigate: setActiveIndex, + onNavigate: setActiveIndex }); const dismiss = useDismiss(context); - const role = useRole(context, { role: "combobox" }); + const role = useRole(context, { role: 'combobox' }); const { getReferenceProps, getFloatingProps, getItemProps } = useInteractions( [click, listNavigation, dismiss, role] @@ -85,8 +85,8 @@ const RepositoriesDropdown: React.FC = ({ ...data, results: data.results.filter((r) => r.name.toLowerCase().includes(search.toLowerCase()) - ), - }), + ) + }) }); const handleSearch = (e: React.ChangeEvent) => { @@ -110,7 +110,7 @@ const RepositoriesDropdown: React.FC = ({ shadow-light`, dark: `bg-nuances-black text-nuances-300 - shadow-dark`, + shadow-dark` }; return ( @@ -152,9 +152,9 @@ const RepositoriesDropdown: React.FC = ({ -mx-2 my-2 ${ - variant === "light" - ? "border-primary-600" - : "border-nuances-300" + variant === 'light' + ? 'border-primary-600' + : 'border-nuances-300' } `} /> @@ -171,9 +171,9 @@ const RepositoriesDropdown: React.FC = ({ -mx-2 my-2 ${ - variant === "light" - ? "border-primary-600" - : "border-nuances-300" + variant === 'light' + ? 'border-primary-600' + : 'border-nuances-300' } `} /> @@ -199,11 +199,11 @@ const RepositoriesDropdown: React.FC = ({ handleSelect(repository.name); }, onKeyDown(event) { - if (event.key === "Enter" || event.key === " ") { + if (event.key === 'Enter' || event.key === ' ') { event.preventDefault(); handleSelect(repository.name); } - }, + } })} /> )) diff --git a/ui/src/components/dropdowns/StatesDropdown.tsx b/ui/src/components/dropdowns/StatesDropdown.tsx index efd7bdb6..74440645 100644 --- a/ui/src/components/dropdowns/StatesDropdown.tsx +++ b/ui/src/components/dropdowns/StatesDropdown.tsx @@ -1,5 +1,5 @@ -import React, { useState, useRef } from "react"; -import { twMerge } from "tailwind-merge"; +import React, { useState, useRef } from 'react'; +import { twMerge } from 'tailwind-merge'; import { useFloating, useClick, @@ -13,34 +13,34 @@ import { flip, size, autoUpdate, - FloatingPortal, -} from "@floating-ui/react"; + FloatingPortal +} from '@floating-ui/react'; -import Dropdown from "@/components/core/Dropdown"; -import Checkbox from "@/components/core/Checkbox"; +import Dropdown from '@/components/core/Dropdown'; +import Checkbox from '@/components/core/Checkbox'; -import { LayerState } from "@/clients/layers/types"; +import { LayerState } from '@/clients/layers/types'; export interface StatesDropdownProps { className?: string; - variant?: "light" | "dark"; + variant?: 'light' | 'dark'; disabled?: boolean; selectedStates: LayerState[]; setSelectedStates: (states: LayerState[]) => void; } const options: Array<{ value: LayerState; label: string }> = [ - { value: "success", label: "OK" }, - { value: "warning", label: "OutOfSync" }, - { value: "error", label: "Error" }, + { value: 'success', label: 'OK' }, + { value: 'warning', label: 'OutOfSync' }, + { value: 'error', label: 'Error' } ]; const StatesDropdown: React.FC = ({ className, - variant = "light", + variant = 'light', disabled, selectedStates, - setSelectedStates, + setSelectedStates }) => { const [isOpen, setIsOpen] = useState(false); const [activeIndex, setActiveIndex] = useState(null); @@ -50,7 +50,7 @@ const StatesDropdown: React.FC = ({ const isTypingRef = useRef(false); const { refs, floatingStyles, context } = useFloating({ - placement: "bottom-start", + placement: 'bottom-start', open: isOpen, onOpenChange: setIsOpen, whileElementsMounted: autoUpdate, @@ -61,20 +61,20 @@ const StatesDropdown: React.FC = ({ apply({ availableHeight, elements }) { elements.floating.style.maxHeight = `${availableHeight}px`; }, - padding: 8, - }), - ], + padding: 8 + }) + ] }); const click = useClick(context, { enabled: !disabled, - event: "mousedown", + event: 'mousedown' }); const listNavigation = useListNavigation(context, { enabled: !disabled, listRef: listElementsRef, activeIndex: activeIndex, - onNavigate: setActiveIndex, + onNavigate: setActiveIndex }); const typeahead = useTypeahead(context, { enabled: !disabled, @@ -83,10 +83,10 @@ const StatesDropdown: React.FC = ({ onMatch: setActiveIndex, onTypingChange(isTyping) { isTypingRef.current = isTyping; - }, + } }); const dismiss = useDismiss(context); - const role = useRole(context, { role: "select" }); + const role = useRole(context, { role: 'select' }); const { getReferenceProps, getFloatingProps, getItemProps } = useInteractions( [click, listNavigation, typeahead, dismiss, role] @@ -106,7 +106,7 @@ const StatesDropdown: React.FC = ({ shadow-light`, dark: `bg-nuances-black text-nuances-300 - shadow-dark`, + shadow-dark` }; return ( @@ -144,9 +144,9 @@ const StatesDropdown: React.FC = ({ -mx-2 my-2 ${ - variant === "light" - ? "border-primary-600" - : "border-nuances-300" + variant === 'light' + ? 'border-primary-600' + : 'border-nuances-300' } `} /> @@ -169,16 +169,16 @@ const StatesDropdown: React.FC = ({ handleSelect(value); }, onKeyDown(event) { - if (event.key === "Enter") { + if (event.key === 'Enter') { event.preventDefault(); handleSelect(value); } - if (event.key === " " && !isTypingRef.current) { + if (event.key === ' ' && !isTypingRef.current) { event.preventDefault(); handleSelect(value); } - }, + } })} /> ))} diff --git a/ui/src/components/loaders/CardLoader.tsx b/ui/src/components/loaders/CardLoader.tsx index 8fa41fe8..effc9e47 100644 --- a/ui/src/components/loaders/CardLoader.tsx +++ b/ui/src/components/loaders/CardLoader.tsx @@ -1,20 +1,20 @@ -import React from "react"; -import { twMerge } from "tailwind-merge"; +import React from 'react'; +import { twMerge } from 'tailwind-merge'; export interface CardLoaderProps { className?: string; - variant?: "light" | "dark"; + variant?: 'light' | 'dark'; } const CardLoader: React.FC = ({ className, - variant = "light", + variant = 'light' }) => { const styles = { light: `bg-[linear-gradient(270deg,_#D8EBFF_0%,_#ECF5FF_100%)] shadow-light`, dark: `bg-[linear-gradient(270deg,_#252525_0%,_rgba(68,_67,_67,_0.24)_100%)] - shadow-dark`, + shadow-dark` }; return ( diff --git a/ui/src/components/loaders/RunCardLoader.tsx b/ui/src/components/loaders/RunCardLoader.tsx index d4380772..a0ecb416 100644 --- a/ui/src/components/loaders/RunCardLoader.tsx +++ b/ui/src/components/loaders/RunCardLoader.tsx @@ -1,20 +1,20 @@ -import React from "react"; -import { twMerge } from "tailwind-merge"; +import React from 'react'; +import { twMerge } from 'tailwind-merge'; export interface RunCardLoaderProps { className?: string; - variant?: "light" | "dark"; + variant?: 'light' | 'dark'; } const RunCardLoader: React.FC = ({ className, - variant = "light", + variant = 'light' }) => { const style = { light: `bg-[linear-gradient(270deg,_#D8EBFF_0%,_#ECF5FF_100%)] shadow-light`, dark: `bg-[linear-gradient(270deg,_#252525_0%,_rgba(68,_67,_67,_0.24)_100%)] - shadow-dark`, + shadow-dark` }; return ( diff --git a/ui/src/components/loaders/TableLoader.tsx b/ui/src/components/loaders/TableLoader.tsx index a83091af..6aa35481 100644 --- a/ui/src/components/loaders/TableLoader.tsx +++ b/ui/src/components/loaders/TableLoader.tsx @@ -1,18 +1,18 @@ -import React from "react"; -import { twMerge } from "tailwind-merge"; +import React from 'react'; +import { twMerge } from 'tailwind-merge'; export interface TableLoaderProps { className?: string; - variant?: "light" | "dark"; + variant?: 'light' | 'dark'; } const TableLoader: React.FC = ({ className, - variant = "light", + variant = 'light' }) => { const styles = { light: `bg-[linear-gradient(270deg,_#D8EBFF_0%,_#ECF5FF_100%)]`, - dark: `bg-[linear-gradient(270deg,_#252525_0%,_rgba(68,_67,_67,_0.24)_100%)]`, + dark: `bg-[linear-gradient(270deg,_#252525_0%,_rgba(68,_67,_67,_0.24)_100%)]` }; return ( diff --git a/ui/src/components/misc/ProfilePicture.tsx b/ui/src/components/misc/ProfilePicture.tsx index f14d3dac..93c0e6f6 100644 --- a/ui/src/components/misc/ProfilePicture.tsx +++ b/ui/src/components/misc/ProfilePicture.tsx @@ -1,18 +1,18 @@ -import React, { useState, useRef } from "react"; -import { twMerge } from "tailwind-merge"; +import React, { useState, useRef } from 'react'; +import { twMerge } from 'tailwind-merge'; -import ThemeToggle from "@/components/misc/ThemeToggle"; +import ThemeToggle from '@/components/misc/ThemeToggle'; -import Sombrero from "@/assets/illustrations/Sombrero"; +import Sombrero from '@/assets/illustrations/Sombrero'; export interface ProfilePictureProps { className?: string; - variant?: "light" | "dark"; + variant?: 'light' | 'dark'; } const ProfilePicture: React.FC = ({ className, - variant = "light", + variant = 'light' }) => { const [open, setOpen] = useState(false); const pictureRef = useRef(null); @@ -37,12 +37,12 @@ const ProfilePicture: React.FC = ({ text-primary-600`, dark: `bg-nuances-black outline-nuances-300 - text-primary-100`, + text-primary-100` }; return (
diff --git a/ui/src/components/misc/ThemeToggle.tsx b/ui/src/components/misc/ThemeToggle.tsx index 92832b6a..986445ab 100644 --- a/ui/src/components/misc/ThemeToggle.tsx +++ b/ui/src/components/misc/ThemeToggle.tsx @@ -1,35 +1,35 @@ -import React, { useContext } from "react"; -import { twMerge } from "tailwind-merge"; +import React, { useContext } from 'react'; +import { twMerge } from 'tailwind-merge'; -import { ThemeContext } from "@/contexts/ThemeContext"; +import { ThemeContext } from '@/contexts/ThemeContext'; -import Box from "@/components/core/Box"; -import Toggle from "@/components/core/Toggle"; +import Box from '@/components/core/Box'; +import Toggle from '@/components/core/Toggle'; export interface ThemeToggleProps { className?: string; - variant?: "light" | "dark"; + variant?: 'light' | 'dark'; } const ThemeToggle: React.FC = ({ className, - variant = "light", + variant = 'light' }) => { const { theme, setTheme } = useContext(ThemeContext); return ( setTheme(theme === "dark" ? "light" : "dark")} - label={`${variant === "dark" ? "Disable" : "Enable"} Dark Mode`} + checked={theme === 'dark'} + onChange={() => setTheme(theme === 'dark' ? 'light' : 'dark')} + label={`${variant === 'dark' ? 'Disable' : 'Enable'} Dark Mode`} /> ); diff --git a/ui/src/components/navigation/NavigationBar.tsx b/ui/src/components/navigation/NavigationBar.tsx index 975e0a94..802a7196 100644 --- a/ui/src/components/navigation/NavigationBar.tsx +++ b/ui/src/components/navigation/NavigationBar.tsx @@ -1,27 +1,27 @@ -import React from "react"; -import { twMerge } from "tailwind-merge"; -import { NavLink } from "react-router-dom"; +import React from 'react'; +import { twMerge } from 'tailwind-merge'; +import { NavLink } from 'react-router-dom'; -import ProfilePicture from "@/components/misc/ProfilePicture"; -import Burrito from "@/assets/illustrations/Burrito"; -import LayerGroupIcon from "@/assets/icons/LayerGroupIcon"; -import CodeBranchIcon from "@/assets/icons/CodeBranchIcon"; -import WindowIcon from "@/assets/icons/WindowIcon"; +import ProfilePicture from '@/components/misc/ProfilePicture'; +import Burrito from '@/assets/illustrations/Burrito'; +import LayerGroupIcon from '@/assets/icons/LayerGroupIcon'; +import CodeBranchIcon from '@/assets/icons/CodeBranchIcon'; +import WindowIcon from '@/assets/icons/WindowIcon'; export interface NavigationBarProps { className?: string; - variant?: "light" | "dark"; + variant?: 'light' | 'dark'; } export const NavigationBar: React.FC = ({ className, - variant = "light", + variant = 'light' }) => { const styles = { light: `bg-background-light fill-nuances-black`, dark: `bg-background-dark - fill-nuances-50`, + fill-nuances-50` }; return ( @@ -45,7 +45,7 @@ export const NavigationBar: React.FC = ({
- isActive ? "fill-inherit" : "fill-primary-600" + isActive ? 'fill-inherit' : 'fill-primary-600' } to="/layers" > @@ -53,7 +53,7 @@ export const NavigationBar: React.FC = ({ - isActive ? "fill-inherit" : "fill-primary-600" + isActive ? 'fill-inherit' : 'fill-primary-600' } to="/pulls" > @@ -61,7 +61,7 @@ export const NavigationBar: React.FC = ({ - isActive ? "fill-inherit" : "fill-primary-600" + isActive ? 'fill-inherit' : 'fill-primary-600' } to="/logs" > diff --git a/ui/src/components/navigation/NavigationButton.tsx b/ui/src/components/navigation/NavigationButton.tsx index f75706c5..c14daa37 100644 --- a/ui/src/components/navigation/NavigationButton.tsx +++ b/ui/src/components/navigation/NavigationButton.tsx @@ -1,17 +1,17 @@ -import React from "react"; +import React from 'react'; export interface NavigationButtonProps { - variant?: "light" | "dark"; + variant?: 'light' | 'dark'; icon: React.ReactNode; selected?: boolean; onClick?: () => void; } const NavigationButton: React.FC = ({ - variant = "dark", + variant = 'dark', icon, selected, - onClick, + onClick }) => { const styles = { base: { @@ -23,7 +23,7 @@ const NavigationButton: React.FC = ({ dark: `bg-nuances-400 fill-nuances-300 hover:bg-nuances-black - focus-visible:outline-nuances-300`, + focus-visible:outline-nuances-300` }, selected: { @@ -33,8 +33,8 @@ const NavigationButton: React.FC = ({ dark: `bg-nuances-50 fill-nuances-black - focus-visible:outline-nuances-50`, - }, + focus-visible:outline-nuances-50` + } }; return ( diff --git a/ui/src/components/navigation/NavigationLink.tsx b/ui/src/components/navigation/NavigationLink.tsx index 523b6e30..cf503baf 100644 --- a/ui/src/components/navigation/NavigationLink.tsx +++ b/ui/src/components/navigation/NavigationLink.tsx @@ -1,11 +1,11 @@ -import React from "react"; -import { twMerge } from "tailwind-merge"; +import React from 'react'; +import { twMerge } from 'tailwind-merge'; -import { Link, LinkProps } from "react-router-dom"; +import { Link, LinkProps } from 'react-router-dom'; export interface NavigationLinkProps { className?: string; - to: LinkProps["to"]; + to: LinkProps['to']; children: React.ReactNode; disabled?: boolean; } @@ -14,7 +14,7 @@ const NavigationLink: React.FC = ({ className, to, children, - disabled, + disabled }) => { return !disabled ? ( diff --git a/ui/src/components/tables/Table.tsx b/ui/src/components/tables/Table.tsx index 08fa005b..b22f4b7b 100644 --- a/ui/src/components/tables/Table.tsx +++ b/ui/src/components/tables/Table.tsx @@ -1,37 +1,36 @@ -import React, { useState } from "react"; -import { twMerge } from "tailwind-merge"; +import React, { useState } from 'react'; +import { twMerge } from 'tailwind-merge'; import { createColumnHelper, flexRender, getCoreRowModel, - useReactTable, -} from "@tanstack/react-table"; -import { Tooltip } from "react-tooltip"; + useReactTable +} from '@tanstack/react-table'; +import { Tooltip } from 'react-tooltip'; +import TableLoader from '@/components/loaders/TableLoader'; +import ModalLogsTerminal from '@/components/tools/ModalLogsTerminal'; +import Running from '@/components/widgets/Running'; +import Tag from '@/components/widgets/Tag'; +import ChiliLight from '@/assets/illustrations/ChiliLight'; +import ChiliDark from '@/assets/illustrations/ChiliDark'; +import CodeBranchIcon from '@/assets/icons/CodeBranchIcon'; +import SyncIcon from '@/assets/icons/SyncIcon'; +import GenericIconButton from '@/components/buttons/GenericIconButton'; -import TableLoader from "@/components/loaders/TableLoader"; -import ModalLogsTerminal from "@/components/tools/ModalLogsTerminal"; -import Running from "@/components/widgets/Running"; -import Tag from "@/components/widgets/Tag"; -import ChiliLight from "@/assets/illustrations/ChiliLight"; -import ChiliDark from "@/assets/illustrations/ChiliDark"; -import CodeBranchIcon from "@/assets/icons/CodeBranchIcon"; -import SyncIcon from "@/assets/icons/SyncIcon"; -import GenericIconButton from "@/components/buttons/GenericIconButton"; - -import { Layer, LayerState } from "@/clients/layers/types"; -import { syncLayer } from "@/clients/layers/client"; +import { Layer, LayerState } from '@/clients/layers/types'; +import { syncLayer } from '@/clients/layers/client'; export interface TableProps { className?: string; - variant?: "light" | "dark"; + variant?: 'light' | 'dark'; isLoading?: boolean; data: Layer[]; } const Table: React.FC = ({ className, - variant = "light", + variant = 'light', isLoading, data }) => { @@ -40,38 +39,37 @@ const Table: React.FC = ({ const syncSelectedLayer = async (index: number) => { const sync = await syncLayer(data[index].namespace, data[index].name); if (sync.status === 200) { - data[index].manualSyncStatus = "pending"; + data[index].manualSyncStatus = 'pending'; } - } + }; const columns = [ - columnHelper.accessor("isPR", { - header: "", - cell: (isPR) => isPR.getValue() && , + columnHelper.accessor('isPR', { + header: '', + cell: (isPR) => isPR.getValue() && }), - columnHelper.accessor("namespace", { - header: "Namespace", + columnHelper.accessor('namespace', { + header: 'Namespace' }), - columnHelper.accessor("name", { - header: "Name", + columnHelper.accessor('name', { + header: 'Name' }), - columnHelper.accessor("state", { - header: "State", - cell: (state) => getTag(state.getValue()), + columnHelper.accessor('state', { + header: 'State', + cell: (state) => getTag(state.getValue()) }), - columnHelper.accessor("repository", { - header: "Repository", + columnHelper.accessor('repository', { + header: 'Repository' }), - columnHelper.accessor("branch", { - header: "Branch", + columnHelper.accessor('branch', { + header: 'Branch' }), - columnHelper.accessor("path", { - header: "Path", + columnHelper.accessor('path', { + header: 'Path' }), - columnHelper.accessor("lastResult", { - header: "Last result", - cell: (result) => - ( + columnHelper.accessor('lastResult', { + header: 'Last result', + cell: (result) => (
{result.getValue()} {result.row.original === hoveredRow && @@ -88,11 +86,11 @@ const Table: React.FC = ({ min-w-full w-full pr-4 - ${result.row.original.isRunning && "rounded-xl"} + ${result.row.original.isRunning && 'rounded-xl'} ${ - variant === "light" - ? "bg-[linear-gradient(270deg,_#FFF_58.7%,_rgba(255,_255,_255,_0.00)_100%)]" - : "bg-[linear-gradient(270deg,_#252525_58.7%,_rgba(37,_37,_37,_0.00)_100%)]" + variant === 'light' + ? 'bg-[linear-gradient(270deg,_#FFF_58.7%,_rgba(255,_255,_255,_0.00)_100%)]' + : 'bg-[linear-gradient(270deg,_#252525_58.7%,_rgba(37,_37,_37,_0.00)_100%)]' } `} > @@ -100,11 +98,21 @@ const Table: React.FC = ({ layer={result.row.original} variant={variant} /> - syncSelectedLayer(result.row.index)} - tooltip={result.row.original.manualSyncStatus === "pending" || result.row.original.manualSyncStatus === "annotated" ? "Sync in progress..." : "Sync now"} /> + syncSelectedLayer(result.row.index)} + tooltip={ + result.row.original.manualSyncStatus === 'pending' || + result.row.original.manualSyncStatus === 'annotated' + ? 'Sync in progress...' + : 'Sync now' + } + />
) : result.row.original.isRunning ? (
= ({ pr-4 pointer-events-none ${ - variant === "light" - ? "bg-[linear-gradient(270deg,_#FFF_58.7%,_rgba(255,_255,_255,_0.00)_100%)]" - : "bg-[linear-gradient(270deg,_#000_58.7%,_rgba(0,_0,_0,_0.00)_100%)]" + variant === 'light' + ? 'bg-[linear-gradient(270deg,_#FFF_58.7%,_rgba(255,_255,_255,_0.00)_100%)]' + : 'bg-[linear-gradient(270deg,_#000_58.7%,_rgba(0,_0,_0,_0.00)_100%)]' } `} > @@ -131,16 +139,16 @@ const Table: React.FC = ({
) : null}
- ), - }), + ) + }) ]; const getTag = (state: LayerState) => { return (
- {state === "error" && - (variant === "light" ? ( + {state === 'error' && + (variant === 'light' ? ( = ({ const table = useReactTable({ data, columns, - getCoreRowModel: getCoreRowModel(), + getCoreRowModel: getCoreRowModel() }); const styles = { header: { light: `text-primary-600`, - dark: `text-nuances-300`, + dark: `text-nuances-300` }, row: { base: { @@ -177,17 +185,17 @@ const Table: React.FC = ({ dark: `text-nuances-50 fill-nuances-50 hover:bg-nuances-400 - hover:shadow-dark`, // BUG: not working on Safari + hover:shadow-dark` // BUG: not working on Safari }, running: { light: `outline-blue-400`, - dark: `outline-blue-500`, - }, + dark: `outline-blue-500` + } }, separator: { light: `border-primary-500`, - dark: `border-nuances-300`, - }, + dark: `border-nuances-300` + } }; return ( @@ -336,11 +344,11 @@ const Table: React.FC = ({ px-6 py-4`, cell.row.original.isRunning && - "first:rounded-l-2xl last:rounded-r-2xl" + 'first:rounded-l-2xl last:rounded-r-2xl' )} data-tooltip-id="table-tooltip" data-tooltip-content={ - cell.column.id === "lastResult" && + cell.column.id === 'lastResult' && cell.row.original.isRunning ? (cell.getValue() as string) : null @@ -390,7 +398,7 @@ const Table: React.FC = ({
); diff --git a/ui/src/components/temp/TrafficCone.tsx b/ui/src/components/temp/TrafficCone.tsx index 2151197c..ddce525b 100644 --- a/ui/src/components/temp/TrafficCone.tsx +++ b/ui/src/components/temp/TrafficCone.tsx @@ -1,4 +1,4 @@ -import { SVGProps } from "react"; +import { SVGProps } from 'react'; const TrafficCone = (props: SVGProps) => ( ) => ( diff --git a/ui/src/components/tools/LayerChecklist.tsx b/ui/src/components/tools/LayerChecklist.tsx index 02a9b10c..17c381c4 100644 --- a/ui/src/components/tools/LayerChecklist.tsx +++ b/ui/src/components/tools/LayerChecklist.tsx @@ -6,95 +6,116 @@ import { Layer } from '@/clients/layers/types'; // Define the props for the LayerChecklist component interface LayerChecklistProps { - layers: Layer[]; - variant?: 'light' | 'dark'; // Optional: To pass variant to Checkbox - onSelectionChange?: (selectedLayers: { name: string; namespace: string }[]) => void; // Updated callback prop + layers: Layer[]; + variant?: 'light' | 'dark'; // Optional: To pass variant to Checkbox + onSelectionChange?: ( + selectedLayers: { name: string; namespace: string }[] + ) => void; // Updated callback prop } const LayerChecklist: React.FC = ({ - layers, - variant = 'light', - onSelectionChange, + layers, + variant = 'light', + onSelectionChange }) => { - // State to keep track of selected layers using unique keys - const [selectedLayers, setSelectedLayers] = useState<{ name: string; namespace: string }[]>([]); - const selectAllRef = useRef(null); + // State to keep track of selected layers using unique keys + const [selectedLayers, setSelectedLayers] = useState< + { name: string; namespace: string }[] + >([]); + const selectAllRef = useRef(null); - // Function to generate a unique key for each layer - const getLayerKey = (layer: Layer): string => `${layer.namespace}-${layer.name}`; + // Function to generate a unique key for each layer + const getLayerKey = (layer: Layer): string => + `${layer.namespace}-${layer.name}`; - // Update the indeterminate state based on selection - useEffect(() => { - if (selectAllRef.current) { - const isIndeterminate = - selectedLayers.length > 0 && selectedLayers.length < layers.length; - selectAllRef.current.indeterminate = isIndeterminate; - } - }, [selectedLayers, layers.length]); + // Update the indeterminate state based on selection + useEffect(() => { + if (selectAllRef.current) { + const isIndeterminate = + selectedLayers.length > 0 && selectedLayers.length < layers.length; + selectAllRef.current.indeterminate = isIndeterminate; + } + }, [selectedLayers, layers.length]); - // Handler for individual layer checkbox toggle - const handleToggle = (layer: Layer) => { - setSelectedLayers((prevSelected) => - prevSelected.some((selectedLayer) => selectedLayer.name === layer.name && selectedLayer.namespace === layer.namespace) - ? prevSelected.filter((selectedLayer) => selectedLayer.name !== layer.name || selectedLayer.namespace !== layer.namespace) - : [...prevSelected, { name: layer.name, namespace: layer.namespace }] - ); - }; + // Handler for individual layer checkbox toggle + const handleToggle = (layer: Layer) => { + setSelectedLayers((prevSelected) => + prevSelected.some( + (selectedLayer) => + selectedLayer.name === layer.name && + selectedLayer.namespace === layer.namespace + ) + ? prevSelected.filter( + (selectedLayer) => + selectedLayer.name !== layer.name || + selectedLayer.namespace !== layer.namespace + ) + : [...prevSelected, { name: layer.name, namespace: layer.namespace }] + ); + }; - // Handler to select all layers - const handleSelectAll = () => { - setSelectedLayers(layers.map(layer => ({ name: layer.name, namespace: layer.namespace }))); - }; + // Handler to select all layers + const handleSelectAll = () => { + setSelectedLayers( + layers.map((layer) => ({ name: layer.name, namespace: layer.namespace })) + ); + }; - // Handler to unselect all layers - const handleUnselectAll = () => { - setSelectedLayers([]); - }; + // Handler to unselect all layers + const handleUnselectAll = () => { + setSelectedLayers([]); + }; - useEffect(() => { - if (onSelectionChange) { - onSelectionChange(selectedLayers); - } - }, [selectedLayers, onSelectionChange]); + useEffect(() => { + if (onSelectionChange) { + onSelectionChange(selectedLayers); + } + }, [selectedLayers, onSelectionChange]); - return ( -
-
- - -
-
    - {layers.map((layer) => { - const key = getLayerKey(layer); - return ( -
  • -
    - selectedLayer.name === layer.name && selectedLayer.namespace === layer.namespace)} - onChange={() => handleToggle(layer)} - variant={variant} - /> - -
    -
  • - ); - })} -
-
- ); + return ( +
+
+ + +
+
    + {layers.map((layer) => { + const key = getLayerKey(layer); + return ( +
  • +
    + + selectedLayer.name === layer.name && + selectedLayer.namespace === layer.namespace + )} + onChange={() => handleToggle(layer)} + variant={variant} + /> + +
    +
  • + ); + })} +
+
+ ); }; export default LayerChecklist; diff --git a/ui/src/components/tools/LogsTerminal.tsx b/ui/src/components/tools/LogsTerminal.tsx index 434c6438..c25918d5 100644 --- a/ui/src/components/tools/LogsTerminal.tsx +++ b/ui/src/components/tools/LogsTerminal.tsx @@ -1,33 +1,33 @@ -import React, { useState, useEffect } from "react"; -import { twMerge } from "tailwind-merge"; -import { useQuery } from "@tanstack/react-query"; -import { Tooltip } from "react-tooltip"; +import React, { useState, useEffect } from 'react'; +import { twMerge } from 'tailwind-merge'; +import { useQuery } from '@tanstack/react-query'; +import { Tooltip } from 'react-tooltip'; -import { fetchAttempts } from "@/clients/runs/client"; -import { fetchLogs } from "@/clients/logs/client"; -import { reactQueryKeys } from "@/clients/reactQueryConfig"; +import { fetchAttempts } from '@/clients/runs/client'; +import { fetchLogs } from '@/clients/logs/client'; +import { reactQueryKeys } from '@/clients/reactQueryConfig'; -import AttemptsDropdown from "@/components/dropdowns/AttemptsDropdown"; -import AttemptButton from "@/components/buttons/AttemptButton"; +import AttemptsDropdown from '@/components/dropdowns/AttemptsDropdown'; +import AttemptButton from '@/components/buttons/AttemptButton'; -import SyncIcon from "@/assets/icons/SyncIcon"; -import CopyIcon from "@/assets/icons/CopyIcon"; -import DownloadAltIcon from "@/assets/icons/DownloadAltIcon"; +import SyncIcon from '@/assets/icons/SyncIcon'; +import CopyIcon from '@/assets/icons/CopyIcon'; +import DownloadAltIcon from '@/assets/icons/DownloadAltIcon'; -import { Layer } from "@/clients/layers/types"; +import { Layer } from '@/clients/layers/types'; export interface LogsTerminalProps { className?: string; - variant?: "light" | "dark"; + variant?: 'light' | 'dark'; layer: Layer; run: string; } const LogsTerminal: React.FC = ({ className, - variant = "light", + variant = 'light', layer: { namespace, name }, - run, + run }) => { const styles = { light: `bg-nuances-50 @@ -37,7 +37,7 @@ const LogsTerminal: React.FC = ({ dark: `bg-nuances-400 text-nuances-50 fill-nuances-50 - border-nuances-black`, + border-nuances-black` }; const [selectedAttempts, setSelectedAttempts] = useState([]); @@ -50,13 +50,13 @@ const LogsTerminal: React.FC = ({ const attemptsQuery = useQuery({ queryKey: reactQueryKeys.attempts(namespace, name, run), - queryFn: () => fetchAttempts(namespace, name, run), + queryFn: () => fetchAttempts(namespace, name, run) }); const logsQuery = useQuery({ queryKey: reactQueryKeys.logs(namespace, name, run, activeAttempt), queryFn: () => fetchLogs(namespace, name, run, activeAttempt), - enabled: activeAttempt !== null && !attemptsQuery.isFetching, + enabled: activeAttempt !== null && !attemptsQuery.isFetching }); useEffect(() => { @@ -71,7 +71,7 @@ const LogsTerminal: React.FC = ({ const handleCopy = () => { if (logsQuery.isSuccess) { - navigator.clipboard.writeText(logsQuery.data.results.join("")); // TODO: check if this works properly + navigator.clipboard.writeText(logsQuery.data.results.join('')); // TODO: check if this works properly setDisplayLogsCopiedTooltip(true); } }; @@ -98,9 +98,9 @@ const LogsTerminal: React.FC = ({ {namespace} = ({ logsQuery.refetch()} />
setDisplayLogsCopiedTooltip(false)} > = ({ className={` h-[1px] w-full - ${variant === "light" ? "border-primary-600" : "border-nuances-300"} + ${variant === 'light' ? 'border-primary-600' : 'border-nuances-300'} `} />
@@ -172,9 +172,9 @@ const LogsTerminal: React.FC = ({ text-sm px-4 ${ - variant === "light" - ? "text-primary-600" - : "text-nuances-300" + variant === 'light' + ? 'text-primary-600' + : 'text-nuances-300' } `} > @@ -190,7 +190,7 @@ const LogsTerminal: React.FC = ({ id="terminal-tooltip" isOpen={displayLogsCopiedTooltip} opacity={1} - variant={variant === "light" ? "dark" : "light"} + variant={variant === 'light' ? 'dark' : 'light'} />
); diff --git a/ui/src/components/tools/ModalLogsTerminal.tsx b/ui/src/components/tools/ModalLogsTerminal.tsx index a914b630..9eae6443 100644 --- a/ui/src/components/tools/ModalLogsTerminal.tsx +++ b/ui/src/components/tools/ModalLogsTerminal.tsx @@ -1,4 +1,4 @@ -import React, { useState } from "react"; +import React, { useState } from 'react'; import { useFloating, useDismiss, @@ -7,40 +7,40 @@ import { useInteractions, FloatingFocusManager, FloatingOverlay, - FloatingPortal, -} from "@floating-ui/react"; -import { useNavigate } from "react-router-dom"; + FloatingPortal +} from '@floating-ui/react'; +import { useNavigate } from 'react-router-dom'; -import LogsButton from "@/components/buttons/LogsButton"; -import LogsTerminal from "@/components/tools/LogsTerminal"; -import OpenInLogsButton from "@/components/buttons/OpenInLogsButton"; +import LogsButton from '@/components/buttons/LogsButton'; +import LogsTerminal from '@/components/tools/LogsTerminal'; +import OpenInLogsButton from '@/components/buttons/OpenInLogsButton'; -import { Layer } from "@/clients/layers/types"; +import { Layer } from '@/clients/layers/types'; export interface ModalLogsTerminalProps { - variant?: "light" | "dark"; + variant?: 'light' | 'dark'; layer: Layer; } const ModalLogsTerminal: React.FC = ({ - variant = "light", - layer, + variant = 'light', + layer }) => { const [isOpen, setIsOpen] = useState(false); const { refs, context } = useFloating({ open: isOpen, - onOpenChange: setIsOpen, + onOpenChange: setIsOpen }); const click = useClick(context); const role = useRole(context); - const dismiss = useDismiss(context, { outsidePressEvent: "mousedown" }); + const dismiss = useDismiss(context, { outsidePressEvent: 'mousedown' }); const { getReferenceProps, getFloatingProps } = useInteractions([ click, role, - dismiss, + dismiss ]); const navigate = useNavigate(); @@ -76,7 +76,7 @@ const ModalLogsTerminal: React.FC = ({ />
diff --git a/ui/src/components/widgets/ProgressBar.tsx b/ui/src/components/widgets/ProgressBar.tsx index e965deb1..947f1ed4 100644 --- a/ui/src/components/widgets/ProgressBar.tsx +++ b/ui/src/components/widgets/ProgressBar.tsx @@ -1,8 +1,8 @@ import React from 'react'; interface ProgressBarProps { - /** - * Progress value between 0 and 100 + /** + * Progress value between 0 and 100 */ value: number; label?: string; @@ -14,13 +14,16 @@ const ProgressBar: React.FC = ({ value, label, color = 'bg-blue-500', - className = '', + className = '' }) => { // Ensure the value is between 0 and 100 const normalizedValue = Math.min(Math.max(value, 0), 100); return ( -
+
= ({ aria-valuemin={0} aria-valuemax={100} > - {label && ( - - {label} - - )} + {label && {label}}
); diff --git a/ui/src/components/widgets/Running.tsx b/ui/src/components/widgets/Running.tsx index 8816f00e..103fdabc 100644 --- a/ui/src/components/widgets/Running.tsx +++ b/ui/src/components/widgets/Running.tsx @@ -1,6 +1,6 @@ -import React from "react"; +import React from 'react'; -import SyncIcon from "@/assets/icons/SyncIcon"; +import SyncIcon from '@/assets/icons/SyncIcon'; const Running: React.FC = () => { return ( diff --git a/ui/src/components/widgets/Tag.tsx b/ui/src/components/widgets/Tag.tsx index 7924cbc5..2ab891b2 100644 --- a/ui/src/components/widgets/Tag.tsx +++ b/ui/src/components/widgets/Tag.tsx @@ -1,6 +1,6 @@ -import React from "react"; +import React from 'react'; -import { LayerState } from "@/clients/layers/types"; +import { LayerState } from '@/clients/layers/types'; export interface TagProps { variant: LayerState; @@ -15,19 +15,19 @@ const Tag: React.FC = ({ variant }) => { error: `bg-status-error-default text-nuances-white`, disabled: `bg-nuances-50 - text-nuances-200`, + text-nuances-200` }; const getContent = () => { switch (variant) { - case "success": - return "OK"; - case "warning": - return "OutOfSync"; - case "error": - return "Error"; - case "disabled": - return "Disabled"; + case 'success': + return 'OK'; + case 'warning': + return 'OutOfSync'; + case 'error': + return 'Error'; + case 'disabled': + return 'Disabled'; } }; diff --git a/ui/src/contexts/ThemeContext.tsx b/ui/src/contexts/ThemeContext.tsx index 60ecb1fa..8d10a2f5 100644 --- a/ui/src/contexts/ThemeContext.tsx +++ b/ui/src/contexts/ThemeContext.tsx @@ -1,28 +1,28 @@ -import React, { useState, useEffect, createContext } from "react"; +import React, { useState, useEffect, createContext } from 'react'; interface ThemeContextProps { - theme: "light" | "dark"; - setTheme: (theme: "light" | "dark") => void; + theme: 'light' | 'dark'; + setTheme: (theme: 'light' | 'dark') => void; } export const ThemeContext = createContext({ - theme: "light", - setTheme: () => {}, + theme: 'light', + setTheme: () => {} }); const getInitialTheme = () => { - const theme = localStorage.getItem("theme"); - if (theme === "light" || theme === "dark") { + const theme = localStorage.getItem('theme'); + if (theme === 'light' || theme === 'dark') { return theme; } - const userMedia = matchMedia("(prefers-color-scheme: dark)"); + const userMedia = matchMedia('(prefers-color-scheme: dark)'); if (userMedia.matches) { - localStorage.setItem("theme", "dark"); - return "dark"; + localStorage.setItem('theme', 'dark'); + return 'dark'; } else { - localStorage.setItem("theme", "light"); - return "light"; + localStorage.setItem('theme', 'light'); + return 'light'; } }; @@ -31,10 +31,10 @@ interface ThemeProviderProps { } const ThemeProvider: React.FC = ({ children }) => { - const [theme, setTheme] = useState<"light" | "dark">(getInitialTheme()); + const [theme, setTheme] = useState<'light' | 'dark'>(getInitialTheme()); useEffect(() => { - localStorage.setItem("theme", theme); + localStorage.setItem('theme', theme); }, [theme]); return ( diff --git a/ui/src/layout/Layout.tsx b/ui/src/layout/Layout.tsx index f4a0bf82..48ff3a68 100644 --- a/ui/src/layout/Layout.tsx +++ b/ui/src/layout/Layout.tsx @@ -1,9 +1,9 @@ -import React, { useContext } from "react"; -import { Outlet } from "react-router-dom"; +import React, { useContext } from 'react'; +import { Outlet } from 'react-router-dom'; -import { ThemeContext } from "@/contexts/ThemeContext"; +import { ThemeContext } from '@/contexts/ThemeContext'; -import NavigationBar from "@/components/navigation/NavigationBar"; +import NavigationBar from '@/components/navigation/NavigationBar'; const Layout: React.FC = () => { const { theme } = useContext(ThemeContext); @@ -11,7 +11,7 @@ const Layout: React.FC = () => {
diff --git a/ui/src/main.tsx b/ui/src/main.tsx index 966f17a4..93db3799 100644 --- a/ui/src/main.tsx +++ b/ui/src/main.tsx @@ -1,9 +1,9 @@ -import React from "react"; -import ReactDOM from "react-dom/client"; -import App from "./App.tsx"; -import "./index.css"; +import React from 'react'; +import ReactDOM from 'react-dom/client'; +import App from './App.tsx'; +import './index.css'; -ReactDOM.createRoot(document.getElementById("root")!).render( +ReactDOM.createRoot(document.getElementById('root')!).render( diff --git a/ui/src/modals/SlidingPane.tsx b/ui/src/modals/SlidingPane.tsx index 2c577c0f..2b51c553 100644 --- a/ui/src/modals/SlidingPane.tsx +++ b/ui/src/modals/SlidingPane.tsx @@ -6,8 +6,8 @@ interface SlidingPaneProps { isOpen: boolean; onClose: () => void; children?: React.ReactNode; - width?: string; - variant?: "light" | "dark"; + width?: string; + variant?: 'light' | 'dark'; } const SlidingPane: React.FC = ({ @@ -15,7 +15,7 @@ const SlidingPane: React.FC = ({ onClose, children, width = 'w-1/3', - variant = 'light', + variant = 'light' }) => { // Handle Escape key to close the pane useEffect(() => { @@ -42,7 +42,6 @@ const SlidingPane: React.FC = ({ }; }, [isOpen]); - return ReactDOM.createPortal( <> {/* Background */} @@ -62,15 +61,15 @@ const SlidingPane: React.FC = ({ } ${width} ${variant === 'light' ? 'bg-primary-100' : 'bg-nuances-black'}`} > {/* Close Button */} - + {/* Content */}
{children}
diff --git a/ui/src/pages/Layers.tsx b/ui/src/pages/Layers.tsx index 67d3436f..fbe07501 100644 --- a/ui/src/pages/Layers.tsx +++ b/ui/src/pages/Layers.tsx @@ -1,86 +1,86 @@ -import React, { useState, useContext, useCallback, useMemo } from "react"; -import { useSearchParams } from "react-router-dom"; -import { useQuery } from "@tanstack/react-query"; +import React, { useState, useContext, useCallback, useMemo } from 'react'; +import { useSearchParams } from 'react-router-dom'; +import { useQuery } from '@tanstack/react-query'; -import { fetchLayers, syncLayer } from "@/clients/layers/client"; -import { reactQueryKeys } from "@/clients/reactQueryConfig"; +import { fetchLayers, syncLayer } from '@/clients/layers/client'; +import { reactQueryKeys } from '@/clients/reactQueryConfig'; -import { ThemeContext } from "@/contexts/ThemeContext"; +import { ThemeContext } from '@/contexts/ThemeContext'; -import Button from "@/components/core/Button"; -import Input from "@/components/core/Input"; -import StatesDropdown from "@/components/dropdowns/StatesDropdown"; -import RepositoriesDropdown from "@/components/dropdowns/RepositoriesDropdown"; -import Toggle from "@/components/core/Toggle"; -import NavigationButton from "@/components/navigation/NavigationButton"; -import Card from "@/components/cards/Card"; -import Table from "@/components/tables/Table"; +import Button from '@/components/core/Button'; +import Input from '@/components/core/Input'; +import StatesDropdown from '@/components/dropdowns/StatesDropdown'; +import RepositoriesDropdown from '@/components/dropdowns/RepositoriesDropdown'; +import Toggle from '@/components/core/Toggle'; +import NavigationButton from '@/components/navigation/NavigationButton'; +import Card from '@/components/cards/Card'; +import Table from '@/components/tables/Table'; -import SearchIcon from "@/assets/icons/SearchIcon"; -import AppsIcon from "@/assets/icons/AppsIcon"; -import BarsIcon from "@/assets/icons/BarsIcon"; -import CardLoader from "@/components/loaders/CardLoader"; +import SearchIcon from '@/assets/icons/SearchIcon'; +import AppsIcon from '@/assets/icons/AppsIcon'; +import BarsIcon from '@/assets/icons/BarsIcon'; +import CardLoader from '@/components/loaders/CardLoader'; -import { LayerState } from "@/clients/layers/types"; -import PaginationDropdown from "@/components/dropdowns/PaginationDropdown"; -import SlidingPane from "@/modals/SlidingPane"; -import LayerChecklist from "@/components/tools/LayerChecklist"; -import ProgressBar from "@/components/widgets/ProgressBar"; +import { LayerState } from '@/clients/layers/types'; +import PaginationDropdown from '@/components/dropdowns/PaginationDropdown'; +import SlidingPane from '@/modals/SlidingPane'; +import LayerChecklist from '@/components/tools/LayerChecklist'; +import ProgressBar from '@/components/widgets/ProgressBar'; const Layers: React.FC = () => { const { theme } = useContext(ThemeContext); - const [view, setView] = useState<"grid" | "table">("grid"); + const [view, setView] = useState<'grid' | 'table'>('grid'); const [layerOffset, setLayerOffset] = useState(0); const [layerLimit, setLayerLimit] = useState(10); const [searchParams, setSearchParams] = useSearchParams(); const search = useMemo(() => { setLayerOffset(0); - return searchParams.get("search") || ""; + return searchParams.get('search') || ''; }, [searchParams]); const setSearch = useCallback( (search: string) => { - searchParams.set("search", search); + searchParams.set('search', search); setSearchParams(searchParams); }, [searchParams, setSearchParams] ); const stateFilter = useMemo(() => { - const param = searchParams.get("states"); - return (param ? param.split(",") : []) as LayerState[]; + const param = searchParams.get('states'); + return (param ? param.split(',') : []) as LayerState[]; }, [searchParams]); const setStateFilter = useCallback( (stateFilter: LayerState[]) => { - searchParams.set("states", stateFilter.join(",")); + searchParams.set('states', stateFilter.join(',')); setSearchParams(searchParams); }, [searchParams, setSearchParams] ); const repositoryFilter = useMemo(() => { - const param = searchParams.get("repositories"); - return param ? param.split(",") : []; + const param = searchParams.get('repositories'); + return param ? param.split(',') : []; }, [searchParams]); const setRepositoryFilter = useCallback( (repositoryFilter: string[]) => { - searchParams.set("repositories", repositoryFilter.join(",")); + searchParams.set('repositories', repositoryFilter.join(',')); setSearchParams(searchParams); }, [searchParams, setSearchParams] ); const hidePRFilter = useMemo( - () => searchParams.get("hidepr") !== "false", + () => searchParams.get('hidepr') !== 'false', [searchParams] ); const setHidePRFilter = useCallback( (hidePRFilter: boolean) => { - searchParams.set("hidepr", hidePRFilter.toString()); + searchParams.set('hidepr', hidePRFilter.toString()); setSearchParams(searchParams); }, [searchParams, setSearchParams] @@ -106,8 +106,8 @@ const Layers: React.FC = () => { repositoryFilter.length === 0 || repositoryFilter.includes(layer.repository) ) - .filter((layer) => !hidePRFilter || !layer.isPR), - }), + .filter((layer) => !hidePRFilter || !layer.isPR) + }) }); const updateLimit = useCallback( @@ -122,7 +122,9 @@ const Layers: React.FC = () => { [layerOffset, layersQuery] ); - const [selectedLayersForSync, setSelectedLayersForSync] = useState<{ name: string; namespace: string }[]>([]); + const [selectedLayersForSync, setSelectedLayersForSync] = useState< + { name: string; namespace: string }[] + >([]); const [syncProgressValue, setSyncProgressValue] = useState(0); const syncSelectedLayers = async () => { const totalLayers = selectedLayersForSync.length; @@ -132,49 +134,57 @@ const Layers: React.FC = () => { } catch (error) { console.error(`Failed to sync layer ${layer.name}:`, error); } - setSyncProgressValue((prev) => prev + 100 / totalLayers) + setSyncProgressValue((prev) => prev + 100 / totalLayers); } setTimeout(() => { setSyncProgressValue(0); setShowRefreshPane(false); layersQuery.refetch(); }, 1000); - } + }; return (
- setShowRefreshPane(false)} variant={theme}> -
-
-

setShowRefreshPane(false)} + variant={theme} + > +
+
+

- Select Layers to synchronize -

+ > + Select Layers to synchronize +

- {layersQuery.isSuccess && ( - setSelectedLayersForSync(layers)} /> - )} -
-
- - -
-
-
+ {layersQuery.isSuccess && ( + setSelectedLayersForSync(layers)} + /> + )} +
+
+ + +
+
+
{ p-6 pb-3 gap-6 - ${theme === "light" ? "bg-primary-100" : "bg-nuances-black"} + ${theme === 'light' ? 'bg-primary-100' : 'bg-nuances-black'} `} >
@@ -191,23 +201,23 @@ const Layers: React.FC = () => { text-[32px] font-extrabold leading-[130%] - ${theme === "light" ? "text-nuances-black" : "text-nuances-50"} + ${theme === 'light' ? 'text-nuances-black' : 'text-nuances-50'} `} > Layers
@@ -376,10 +386,10 @@ const Layers: React.FC = () => {
- {view === "grid" ? ( + {view === 'grid' ? (
{layersQuery.isLoading ? ( Array.from({ length: 100 }).map((_, index) => ( @@ -391,7 +401,7 @@ const Layers: React.FC = () => { text-lg font-semibold ${ - theme === "light" ? "text-nuances-black" : "text-nuances-50" + theme === 'light' ? 'text-nuances-black' : 'text-nuances-50' } `} > @@ -410,9 +420,9 @@ const Layers: React.FC = () => { text-lg font-semibold ${ - theme === "light" - ? "text-nuances-black" - : "text-nuances-50" + theme === 'light' + ? 'text-nuances-black' + : 'text-nuances-50' } `} > @@ -423,7 +433,7 @@ const Layers: React.FC = () => { <> )}
- ) : view === "table" ? ( + ) : view === 'table' ? (
{layersQuery.isLoading ? ( @@ -433,7 +443,7 @@ const Layers: React.FC = () => { text-lg font-semibold ${ - theme === "light" ? "text-nuances-black" : "text-nuances-50" + theme === 'light' ? 'text-nuances-black' : 'text-nuances-50' } `} > @@ -441,7 +451,13 @@ const Layers: React.FC = () => { ) : layersQuery.isSuccess ? ( layersQuery.data.results.length > 0 ? ( -
+
) : (
{ text-lg font-semibold ${ - theme === "light" - ? "text-nuances-black" - : "text-nuances-50" + theme === 'light' + ? 'text-nuances-black' + : 'text-nuances-50' } `} > diff --git a/ui/src/pages/Login.tsx b/ui/src/pages/Login.tsx index 9864cc0a..1137ac2d 100644 --- a/ui/src/pages/Login.tsx +++ b/ui/src/pages/Login.tsx @@ -1,16 +1,16 @@ -import React, { useContext } from "react"; -import { useNavigate } from "react-router-dom"; +import React, { useContext } from 'react'; +import { useNavigate } from 'react-router-dom'; -import { ThemeContext } from "@/contexts/ThemeContext"; +import { ThemeContext } from '@/contexts/ThemeContext'; -import Input from "@/components/core/Input"; -import Button from "@/components/core/Button"; -import SocialButton from "@/components/buttons/SocialButton"; +import Input from '@/components/core/Input'; +import Button from '@/components/core/Button'; +import SocialButton from '@/components/buttons/SocialButton'; -import Burrito from "@/assets/illustrations/Burrito"; -import EyeSlashIcon from "@/assets/icons/EyeSlashIcon"; -import CoverLight from "@/assets/covers/cover-light.png"; -import CoverDark from "@/assets/covers/cover-dark.png"; +import Burrito from '@/assets/illustrations/Burrito'; +import EyeSlashIcon from '@/assets/icons/EyeSlashIcon'; +import CoverLight from '@/assets/covers/cover-light.png'; +import CoverDark from '@/assets/covers/cover-dark.png'; const Login: React.FC = () => { const { theme } = useContext(ThemeContext); @@ -24,7 +24,7 @@ const Login: React.FC = () => { w-[500px] min-w-[500px] overflow-auto - ${theme === "light" ? "bg-nuances-white" : "bg-nuances-black"} + ${theme === 'light' ? 'bg-nuances-white' : 'bg-nuances-black'} `} >
@@ -35,9 +35,9 @@ const Login: React.FC = () => { text-3xl font-extrabold ${ - theme === "light" - ? "text-nuances-black" - : "text-nuances-white" + theme === 'light' + ? 'text-nuances-black' + : 'text-nuances-white' } `} > @@ -60,8 +60,8 @@ const Login: React.FC = () => { /> @@ -73,9 +73,9 @@ const Login: React.FC = () => { w-full gap-4 ${ - theme === "light" - ? "text-nuances-black border-nuances-black" - : "text-nuances-white border-nuances-white" + theme === 'light' + ? 'text-nuances-black border-nuances-black' + : 'text-nuances-white border-nuances-white' } `} > @@ -87,12 +87,12 @@ const Login: React.FC = () => { navigate("/")} + onClick={() => navigate('/')} /> navigate("/")} + onClick={() => navigate('/')} />
@@ -107,9 +107,9 @@ const Login: React.FC = () => { p-6 rounded-lg ${ - theme === "light" - ? "bg-primary-400 text-nuances-black" - : "bg-nuances-400 text-nuances-50" + theme === 'light' + ? 'bg-primary-400 text-nuances-black' + : 'bg-nuances-400 text-nuances-50' } `} > @@ -131,9 +131,9 @@ const Login: React.FC = () => { px-16 gap-6 ${ - theme === "light" - ? "bg-background-login-light" - : "bg-background-login-dark" + theme === 'light' + ? 'bg-background-login-light' + : 'bg-background-login-dark' } `} > @@ -141,7 +141,7 @@ const Login: React.FC = () => { className={` flex flex-col - ${theme === "light" ? "text-nuances-black" : "text-nuances-white"} + ${theme === 'light' ? 'text-nuances-black' : 'text-nuances-white'} `} > Burrito is a TACoS @@ -158,9 +158,9 @@ const Login: React.FC = () => { translate-y-20 translate-x-28 rounded-lg - ${theme === "light" ? "shadow-light" : "shadow-dark"} + ${theme === 'light' ? 'shadow-light' : 'shadow-dark'} `} - src={theme === "light" ? CoverLight : CoverDark} + src={theme === 'light' ? CoverLight : CoverDark} /> diff --git a/ui/src/pages/Logs.tsx b/ui/src/pages/Logs.tsx index 7e95ec09..9af7740a 100644 --- a/ui/src/pages/Logs.tsx +++ b/ui/src/pages/Logs.tsx @@ -1,25 +1,25 @@ -import React, { useContext, useCallback, useMemo, useState } from "react"; -import { useQuery } from "@tanstack/react-query"; -import { useParams, useSearchParams, useNavigate } from "react-router-dom"; +import React, { useContext, useCallback, useMemo, useState } from 'react'; +import { useQuery } from '@tanstack/react-query'; +import { useParams, useSearchParams, useNavigate } from 'react-router-dom'; -import { fetchLayers } from "@/clients/layers/client"; -import { reactQueryKeys } from "@/clients/reactQueryConfig"; +import { fetchLayers } from '@/clients/layers/client'; +import { reactQueryKeys } from '@/clients/reactQueryConfig'; -import { ThemeContext } from "@/contexts/ThemeContext"; +import { ThemeContext } from '@/contexts/ThemeContext'; -import Button from "@/components/core/Button"; -import Input from "@/components/core/Input"; -import RepositoriesDropdown from "@/components/dropdowns/RepositoriesDropdown"; -import PaginationDropdown from "@/components/dropdowns/PaginationDropdown"; -import DateDropdown from "@/components/dropdowns/DateDropdown"; -import Toggle from "@/components/core/Toggle"; -import RunCardLoader from "@/components/loaders/RunCardLoader"; -import RunCard from "@/components/cards/RunCard"; -import LogsTerminal from "@/components/tools/LogsTerminal"; +import Button from '@/components/core/Button'; +import Input from '@/components/core/Input'; +import RepositoriesDropdown from '@/components/dropdowns/RepositoriesDropdown'; +import PaginationDropdown from '@/components/dropdowns/PaginationDropdown'; +import DateDropdown from '@/components/dropdowns/DateDropdown'; +import Toggle from '@/components/core/Toggle'; +import RunCardLoader from '@/components/loaders/RunCardLoader'; +import RunCard from '@/components/cards/RunCard'; +import LogsTerminal from '@/components/tools/LogsTerminal'; -import SearchIcon from "@/assets/icons/SearchIcon"; +import SearchIcon from '@/assets/icons/SearchIcon'; -import { Layer } from "@/clients/layers/types"; +import { Layer } from '@/clients/layers/types'; const Logs: React.FC = () => { const { theme } = useContext(ThemeContext); @@ -30,56 +30,56 @@ const Logs: React.FC = () => { const navigate = useNavigate(); const search = useMemo( - () => searchParams.get("search") || "", + () => searchParams.get('search') || '', [searchParams] ); const setSearch = useCallback( (search: string) => { - searchParams.set("search", search); + searchParams.set('search', search); setSerchParams(searchParams); }, [searchParams, setSerchParams] ); const repositoryFilter = useMemo(() => { - const param = searchParams.get("repositories"); - return param ? param.split(",") : []; + const param = searchParams.get('repositories'); + return param ? param.split(',') : []; }, [searchParams]); const setRepositoryFilter = useCallback( (repositoryFilter: string[]) => { - searchParams.set("repositories", repositoryFilter.join(",")); + searchParams.set('repositories', repositoryFilter.join(',')); setSerchParams(searchParams); }, [searchParams, setSerchParams] ); - const dateFilter = useMemo<"ascending" | "descending" | null>(() => { - const param = searchParams.get("date"); - return param === "ascending" - ? "ascending" - : param === "descending" - ? "descending" + const dateFilter = useMemo<'ascending' | 'descending' | null>(() => { + const param = searchParams.get('date'); + return param === 'ascending' + ? 'ascending' + : param === 'descending' + ? 'descending' : null; }, [searchParams]); const setDateFilter = useCallback( - (dateFilter: "ascending" | "descending" | null) => { - searchParams.set("date", dateFilter || ""); + (dateFilter: 'ascending' | 'descending' | null) => { + searchParams.set('date', dateFilter || ''); setSerchParams(searchParams); }, [searchParams, setSerchParams] ); const hidePRFilter = useMemo( - () => searchParams.get("hidepr") !== "false", + () => searchParams.get('hidepr') !== 'false', [searchParams] ); const setHidePRFilter = useCallback( (hidePRFilter: boolean) => { - searchParams.set("hidepr", hidePRFilter.toString()); + searchParams.set('hidepr', hidePRFilter.toString()); setSerchParams(searchParams); }, [searchParams, setSerchParams] @@ -101,14 +101,14 @@ const Logs: React.FC = () => { ) .filter((layer) => !hidePRFilter || !layer.isPR) .sort((a, b) => - dateFilter === "ascending" + dateFilter === 'ascending' ? new Date(a.lastRunAt).getTime() - new Date(b.lastRunAt).getTime() - : dateFilter === "descending" + : dateFilter === 'descending' ? new Date(b.lastRunAt).getTime() - new Date(a.lastRunAt).getTime() : 0 - ), - }), + ) + }) }); const updateLimit = useCallback( @@ -130,9 +130,9 @@ const Logs: React.FC = () => { ? `/${run}` : layer.latestRuns.length > 0 ? `/${layer.lastRun.id}` - : "" + : '' }`, - search: searchParams.toString(), + search: searchParams.toString() }); }; @@ -145,7 +145,7 @@ const Logs: React.FC = () => { p-6 pb-3 gap-6 - ${theme === "light" ? "bg-primary-100" : "bg-nuances-black"} + ${theme === 'light' ? 'bg-primary-100' : 'bg-nuances-black'} `} >
@@ -154,13 +154,13 @@ const Logs: React.FC = () => { text-[32px] font-extrabold leading-[130%] - ${theme === "light" ? "text-nuances-black" : "text-nuances-50"} + ${theme === 'light' ? 'text-nuances-black' : 'text-nuances-50'} `} > Logs