From 484bef7b087d3f355b5bb0e5e809871b095837e5 Mon Sep 17 00:00:00 2001 From: gromon42 Date: Tue, 16 Apr 2024 12:45:48 +0200 Subject: [PATCH 1/4] feat(projects): doing sidebar runs --- README.md | 18 +++--- frontend/src/atoms/dialog.atoms.ts | 4 -- frontend/src/atoms/navigation.atoms.ts | 3 - frontend/src/atoms/run.atoms.ts | 17 ----- .../src/components/{common => }/Button.tsx | 0 .../src/components/{common => }/Dialog.tsx | 2 +- frontend/src/components/DynamicField.tsx | 27 ++++++++ .../components/{common => }/DynamicFields.tsx | 1 - .../components/{common => }/EmptyState.tsx | 0 frontend/src/components/{common => }/Form.tsx | 0 .../components/{common => }/FormButtons.tsx | 0 .../src/components/{common => }/Header.tsx | 3 +- frontend/src/components/{common => }/Nav.tsx | 3 +- .../{common => }/NavigationItem.tsx | 0 .../components/{common => }/ServerError.tsx | 0 .../src/components/{common => }/Subheader.tsx | 9 ++- .../components/{common => }/SwitchField.tsx | 0 frontend/src/components/TextField.tsx | 52 +++++++++++++++ frontend/src/components/TextareaField.tsx | 55 ++++++++++++++++ .../src/components/common/DynamicField.tsx | 47 -------------- frontend/src/components/common/TextField.tsx | 63 ------------------- .../src/components/common/TextareaField.tsx | 63 ------------------- .../self-service/SelfServiceEditDialog.tsx | 16 ----- .../self-service/SelfServiceRunSidebar.tsx | 18 ------ frontend/src/enums/dialog-ids.enum.ts | 1 - frontend/src/hoc/with-page-title.tsx | 4 +- frontend/src/main.tsx | 8 +-- .../AppShell.tsx => pages/App.tsx} | 12 ++-- .../{atoms/user.atoms.ts => pages/atoms.tsx} | 10 ++- frontend/src/pages/self-service/atoms.tsx | 1 + .../self-service/catalog-list/atoms.tsx} | 5 +- .../catalog-list/catalog-list.tsx} | 37 ++++------- .../catalog-list/service-card.tsx} | 23 ++----- .../create-service-dialog/atoms.tsx} | 20 +++--- .../create-service-dialog.tsx} | 17 +++-- .../self-service/self-service.tsx} | 6 +- .../services-runs-sidebar/atoms.tsx | 31 +++++++++ .../service-runs-table.tsx} | 2 +- .../services-runs-sidebar.tsx | 18 ++++++ frontend/src/types/catalog.type.ts | 2 +- frontend/src/types/user.type.ts | 6 ++ 41 files changed, 268 insertions(+), 336 deletions(-) delete mode 100644 frontend/src/atoms/dialog.atoms.ts delete mode 100644 frontend/src/atoms/navigation.atoms.ts delete mode 100644 frontend/src/atoms/run.atoms.ts rename frontend/src/components/{common => }/Button.tsx (100%) rename frontend/src/components/{common => }/Dialog.tsx (98%) create mode 100644 frontend/src/components/DynamicField.tsx rename frontend/src/components/{common => }/DynamicFields.tsx (84%) rename frontend/src/components/{common => }/EmptyState.tsx (100%) rename frontend/src/components/{common => }/Form.tsx (100%) rename frontend/src/components/{common => }/FormButtons.tsx (100%) rename frontend/src/components/{common => }/Header.tsx (97%) rename frontend/src/components/{common => }/Nav.tsx (95%) rename frontend/src/components/{common => }/NavigationItem.tsx (100%) rename frontend/src/components/{common => }/ServerError.tsx (100%) rename frontend/src/components/{common => }/Subheader.tsx (59%) rename frontend/src/components/{common => }/SwitchField.tsx (100%) create mode 100644 frontend/src/components/TextField.tsx create mode 100644 frontend/src/components/TextareaField.tsx delete mode 100644 frontend/src/components/common/DynamicField.tsx delete mode 100644 frontend/src/components/common/TextField.tsx delete mode 100644 frontend/src/components/common/TextareaField.tsx delete mode 100644 frontend/src/components/self-service/SelfServiceEditDialog.tsx delete mode 100644 frontend/src/components/self-service/SelfServiceRunSidebar.tsx rename frontend/src/{components/AppShell.tsx => pages/App.tsx} (67%) rename frontend/src/{atoms/user.atoms.ts => pages/atoms.tsx} (62%) create mode 100644 frontend/src/pages/self-service/atoms.tsx rename frontend/src/{atoms/catalog.atoms.ts => pages/self-service/catalog-list/atoms.tsx} (88%) rename frontend/src/{components/self-service/SelfServiceCatalog.tsx => pages/self-service/catalog-list/catalog-list.tsx} (60%) rename frontend/src/{components/self-service/SelfServiceCard.tsx => pages/self-service/catalog-list/service-card.tsx} (83%) rename frontend/src/{atoms/service.atoms.ts => pages/self-service/create-service-dialog/atoms.tsx} (80%) rename frontend/src/{components/self-service/SelfServiceCreateDialog.tsx => pages/self-service/create-service-dialog/create-service-dialog.tsx} (82%) rename frontend/src/{components/self-service/SelfService.tsx => pages/self-service/self-service.tsx} (66%) create mode 100644 frontend/src/pages/self-service/services-runs-sidebar/atoms.tsx rename frontend/src/{components/self-service/SelfServiceRunTable.tsx => pages/self-service/services-runs-sidebar/service-runs-table.tsx} (98%) create mode 100644 frontend/src/pages/self-service/services-runs-sidebar/services-runs-sidebar.tsx create mode 100644 frontend/src/types/user.type.ts diff --git a/README.md b/README.md index de29e0c..da97cb6 100644 --- a/README.md +++ b/README.md @@ -359,15 +359,15 @@ The Qovery and Torii projects are two different projects with different goals: Here is a features table to help you understand the difference: | Feature | Qovery (Internal Developer Platform) | Torii (Internal Developer Portal) | -|-----------------------|--------------------------------------|-----------------------------------| -| Build | ✅ | ❌ | -| Deploy | ✅ | ❌ | -| Run | ✅ | ❌ | -| Ephemeral Environment | ✅ | ❌ | -| Self-Service | ✅ | ✅ | -| Catalogs Service | ❌ | ✅ | -| Scorecard Service | ❌ | ✅ | -| Workflow Service | Partial with the concept of Pipeline | ✅ | +| --------------------- | ------------------------------------ | --------------------------------- | +| Build | ✅ | ❌ | +| Deploy | ✅ | ❌ | +| Run | ✅ | ❌ | +| Ephemeral Environment | ✅ | ❌ | +| Self-Service | ✅ | ✅ | +| Catalogs Service | ❌ | ✅ | +| Scorecard Service | ❌ | ✅ | +| Workflow Service | Partial with the concept of Pipeline | ✅ | ### Why Torii? diff --git a/frontend/src/atoms/dialog.atoms.ts b/frontend/src/atoms/dialog.atoms.ts deleted file mode 100644 index f66deb2..0000000 --- a/frontend/src/atoms/dialog.atoms.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { atom } from "jotai"; -import { atomFamily } from "jotai/utils"; - -export const dialogOpenedAtomFamily = atomFamily(() => atom(false)); diff --git a/frontend/src/atoms/navigation.atoms.ts b/frontend/src/atoms/navigation.atoms.ts deleted file mode 100644 index 53daf33..0000000 --- a/frontend/src/atoms/navigation.atoms.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { atom } from "jotai"; - -export const pageTitleAtom = atom(""); diff --git a/frontend/src/atoms/run.atoms.ts b/frontend/src/atoms/run.atoms.ts deleted file mode 100644 index 5794644..0000000 --- a/frontend/src/atoms/run.atoms.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { API_URL } from "@/config"; -import { makeQueryAtoms } from "@/lib/make-query-atoms"; -import { selectedCatalogSlugAtom } from "./catalog.atoms"; - -export const [runsAtom, runsStatusAtom] = makeQueryAtoms( - `catalogs-${1}-runs`, - (get) => { - const selectedCatalogSlug = get(selectedCatalogSlugAtom); - - return `${API_URL}/runs/${selectedCatalogSlug}/runs`; - }, - (params) => () => { - return fetch(params as string) - .then((res) => res.json()) - .then((data) => data.results); - } -); diff --git a/frontend/src/components/common/Button.tsx b/frontend/src/components/Button.tsx similarity index 100% rename from frontend/src/components/common/Button.tsx rename to frontend/src/components/Button.tsx diff --git a/frontend/src/components/common/Dialog.tsx b/frontend/src/components/Dialog.tsx similarity index 98% rename from frontend/src/components/common/Dialog.tsx rename to frontend/src/components/Dialog.tsx index 89b9bd9..7cd1a5c 100644 --- a/frontend/src/components/common/Dialog.tsx +++ b/frontend/src/components/Dialog.tsx @@ -1,4 +1,3 @@ -import { dialogOpenedAtomFamily } from "@/atoms/dialog.atoms"; import { DialogIds } from "@/enums/dialog-ids.enum"; import { ThemeColors } from "@/enums/theme-colors.enum"; import { Dialog as HeadlessDialog, Transition } from "@headlessui/react"; @@ -6,6 +5,7 @@ import { XMarkIcon } from "@heroicons/react/24/outline"; import { useAtom } from "jotai"; import { Fragment, ReactNode } from "react"; import { Button } from "./Button"; +import { dialogOpenedAtomFamily } from "@/pages/atoms"; export interface DialogProps { id: DialogIds; diff --git a/frontend/src/components/DynamicField.tsx b/frontend/src/components/DynamicField.tsx new file mode 100644 index 0000000..c12776a --- /dev/null +++ b/frontend/src/components/DynamicField.tsx @@ -0,0 +1,27 @@ +import { Field } from "@/types/catalog.type"; +import SwitchField from "./SwitchField"; +import TextField from "./TextField"; +import TextareaField from "./TextareaField"; + +export interface DynamicFieldProps { + field: Field; + initialFocus?: { + name: string; + }; +} + +export function DynamicField({ field, initialFocus }: DynamicFieldProps) { + const focused = initialFocus?.name === field.slug; + + if (field.type === "text") { + return ; + } else if (field.type === "number") { + return ; + } else if (field.type === "textarea") { + return ; + } else if (field.type === "boolean") { + return ; + } + + return

'{field.type}' is not a supported field

; +} diff --git a/frontend/src/components/common/DynamicFields.tsx b/frontend/src/components/DynamicFields.tsx similarity index 84% rename from frontend/src/components/common/DynamicFields.tsx rename to frontend/src/components/DynamicFields.tsx index 19aa07d..d2f8d8a 100644 --- a/frontend/src/components/common/DynamicFields.tsx +++ b/frontend/src/components/DynamicFields.tsx @@ -5,7 +5,6 @@ export interface DynamicFieldsProps { fields: Field[]; initialFocus?: { name: string; - ref: React.MutableRefObject; }; } diff --git a/frontend/src/components/common/EmptyState.tsx b/frontend/src/components/EmptyState.tsx similarity index 100% rename from frontend/src/components/common/EmptyState.tsx rename to frontend/src/components/EmptyState.tsx diff --git a/frontend/src/components/common/Form.tsx b/frontend/src/components/Form.tsx similarity index 100% rename from frontend/src/components/common/Form.tsx rename to frontend/src/components/Form.tsx diff --git a/frontend/src/components/common/FormButtons.tsx b/frontend/src/components/FormButtons.tsx similarity index 100% rename from frontend/src/components/common/FormButtons.tsx rename to frontend/src/components/FormButtons.tsx diff --git a/frontend/src/components/common/Header.tsx b/frontend/src/components/Header.tsx similarity index 97% rename from frontend/src/components/common/Header.tsx rename to frontend/src/components/Header.tsx index d0df3fe..eb9c19f 100644 --- a/frontend/src/components/common/Header.tsx +++ b/frontend/src/components/Header.tsx @@ -1,4 +1,3 @@ -import { userAtom } from "@/atoms/user.atoms"; import { Disclosure, Menu, Transition } from "@headlessui/react"; import { Bars3Icon, XMarkIcon } from "@heroicons/react/24/outline"; import clsx from "clsx"; @@ -7,6 +6,7 @@ import { BellIcon } from "lucide-react"; import { Fragment } from "react"; import { MobileNav, Nav } from "./Nav"; import { RouteItem } from "./NavigationItem"; +import { userAtom } from "@/pages/atoms"; export interface HeaderProps { routes: RouteItem[]; @@ -14,6 +14,7 @@ export interface HeaderProps { } export function Header({ routes, userMenu }: HeaderProps) { + /** @TODO This shoud be deleted and place at top level when the back end supports users */ const user = useAtomValue(userAtom); return ( diff --git a/frontend/src/components/common/Nav.tsx b/frontend/src/components/Nav.tsx similarity index 95% rename from frontend/src/components/common/Nav.tsx rename to frontend/src/components/Nav.tsx index 8ab13c0..a75661a 100644 --- a/frontend/src/components/common/Nav.tsx +++ b/frontend/src/components/Nav.tsx @@ -1,9 +1,9 @@ -import { userAtom } from "@/atoms/user.atoms"; import { Disclosure } from "@headlessui/react"; import clsx from "clsx"; import { useAtomValue } from "jotai"; import { BellIcon } from "lucide-react"; import NavigationItem, { RouteItem } from "./NavigationItem"; +import { userAtom } from "@/pages/atoms"; export interface NavProps { routes: RouteItem[]; @@ -14,6 +14,7 @@ export interface MobileNavProps extends NavProps { } export function MobileNav({ routes, userMenu }: MobileNavProps) { + /** @TODO This shoud be deleted and place at top level when the back end supports users */ const user = useAtomValue(userAtom); return ( diff --git a/frontend/src/components/common/NavigationItem.tsx b/frontend/src/components/NavigationItem.tsx similarity index 100% rename from frontend/src/components/common/NavigationItem.tsx rename to frontend/src/components/NavigationItem.tsx diff --git a/frontend/src/components/common/ServerError.tsx b/frontend/src/components/ServerError.tsx similarity index 100% rename from frontend/src/components/common/ServerError.tsx rename to frontend/src/components/ServerError.tsx diff --git a/frontend/src/components/common/Subheader.tsx b/frontend/src/components/Subheader.tsx similarity index 59% rename from frontend/src/components/common/Subheader.tsx rename to frontend/src/components/Subheader.tsx index 0645827..094be8f 100644 --- a/frontend/src/components/common/Subheader.tsx +++ b/frontend/src/components/Subheader.tsx @@ -1,9 +1,8 @@ -import { pageTitleAtom } from "@/atoms/navigation.atoms"; -import { useAtomValue } from "jotai"; - -export function Subheader() { - const pageTitle = useAtomValue(pageTitleAtom); +export interface SubheaderProps { + pageTitle: string; +} +export function Subheader({ pageTitle }: SubheaderProps) { return (
diff --git a/frontend/src/components/common/SwitchField.tsx b/frontend/src/components/SwitchField.tsx similarity index 100% rename from frontend/src/components/common/SwitchField.tsx rename to frontend/src/components/SwitchField.tsx diff --git a/frontend/src/components/TextField.tsx b/frontend/src/components/TextField.tsx new file mode 100644 index 0000000..c2bacfc --- /dev/null +++ b/frontend/src/components/TextField.tsx @@ -0,0 +1,52 @@ +import { Field } from "@/types/catalog.type"; +import { InputHTMLAttributes, useEffect } from "react"; +import { useFormContext } from "react-hook-form"; + +export interface TextFieldProps extends InputHTMLAttributes { + field: Field; + focused: boolean; +} + +const TextField = ({ field, focused, ...props }: TextFieldProps) => { + const { register, setFocus } = useFormContext(); + + useEffect(() => { + if (focused) { + setFocus(field.slug); + } + }, [field.slug, setFocus, focused]); + + return ( +
+
+ + {field.required && ( + + Required + + )} +
+
+ +
+
+ ); +}; + +export default TextField; diff --git a/frontend/src/components/TextareaField.tsx b/frontend/src/components/TextareaField.tsx new file mode 100644 index 0000000..4b9b0d8 --- /dev/null +++ b/frontend/src/components/TextareaField.tsx @@ -0,0 +1,55 @@ +import { Field } from "@/types/catalog.type"; +import { + TextareaHTMLAttributes, + useEffect, + forwardRef, + ForwardedRef, +} from "react"; +import { useFormContext } from "react-hook-form"; + +interface TextareaFieldProps + extends TextareaHTMLAttributes { + field: Field; + focused?: boolean; +} + +const TextareaField = ({ field, focused, ...props }: TextareaFieldProps) => { + const { register, setFocus } = useFormContext(); + + useEffect(() => { + if (focused) { + setFocus(field.slug); + } + }, [field.slug, setFocus, focused]); + + return ( +
+
+ + + {field.required && "Required"} + +
+
+