From 81c69d92b313e08bcc23e7090d5fb3561a9e6e71 Mon Sep 17 00:00:00 2001 From: Tuan Dang Date: Tue, 27 Jun 2023 18:48:26 +0700 Subject: [PATCH 01/10] Restyle org name change section --- .../BillingDetailsTab/CompanyNameSection.tsx | 26 ++++---- .../BillingDetailsTab/InvoiceEmailSection.tsx | 22 +++---- .../BillingDetailsTab/PmtMethodsSection.tsx | 30 +++++---- .../BillingDetailsTab/TaxIDSection.tsx | 24 +++---- .../OrgSettingsPage/OrgSettingsPage.tsx | 23 +------ .../OrgNameChangeSection.tsx | 65 +++++++++++-------- 6 files changed, 92 insertions(+), 98 deletions(-) diff --git a/frontend/src/views/Settings/BillingSettingsPage/components/BillingDetailsTab/CompanyNameSection.tsx b/frontend/src/views/Settings/BillingSettingsPage/components/BillingDetailsTab/CompanyNameSection.tsx index fb2eadf86..07834949a 100644 --- a/frontend/src/views/Settings/BillingSettingsPage/components/BillingDetailsTab/CompanyNameSection.tsx +++ b/frontend/src/views/Settings/BillingSettingsPage/components/BillingDetailsTab/CompanyNameSection.tsx @@ -3,9 +3,11 @@ import { Controller, useForm } from "react-hook-form"; import { yupResolver } from "@hookform/resolvers/yup"; import * as yup from "yup"; -import Button from "@app/components/basic/buttons/Button"; import { useNotificationContext } from "@app/components/context/Notifications/NotificationProvider"; -import { FormControl,Input } from "@app/components/v2"; +import { + Button, + FormControl, + Input} from "@app/components/v2"; import { useOrganization } from "@app/context"; import { useGetOrgBillingDetails, @@ -26,7 +28,7 @@ export const CompanyNameSection = () => { resolver: yupResolver(schema) }); const { data } = useGetOrgBillingDetails(currentOrg?._id ?? ""); - const updateOrgBillingDetails = useUpdateOrgBillingDetails(); + const { mutateAsync, isLoading } = useUpdateOrgBillingDetails(); useEffect(() => { if (data) { @@ -40,7 +42,7 @@ export const CompanyNameSection = () => { try { if (!currentOrg?._id) return; if (name === "") return; - await updateOrgBillingDetails.mutateAsync({ + await mutateAsync({ name, organizationId: currentOrg._id }); @@ -82,15 +84,13 @@ export const CompanyNameSection = () => { name="name" /> -
-
+ ); } \ No newline at end of file diff --git a/frontend/src/views/Settings/BillingSettingsPage/components/BillingDetailsTab/InvoiceEmailSection.tsx b/frontend/src/views/Settings/BillingSettingsPage/components/BillingDetailsTab/InvoiceEmailSection.tsx index 991a21869..ee28da914 100644 --- a/frontend/src/views/Settings/BillingSettingsPage/components/BillingDetailsTab/InvoiceEmailSection.tsx +++ b/frontend/src/views/Settings/BillingSettingsPage/components/BillingDetailsTab/InvoiceEmailSection.tsx @@ -3,9 +3,9 @@ import { Controller, useForm } from "react-hook-form"; import { yupResolver } from "@hookform/resolvers/yup"; import * as yup from "yup"; -import Button from "@app/components/basic/buttons/Button"; import { useNotificationContext } from "@app/components/context/Notifications/NotificationProvider"; import { + Button, FormControl, Input} from "@app/components/v2"; import { useOrganization } from "@app/context"; @@ -28,7 +28,7 @@ export const InvoiceEmailSection = () => { resolver: yupResolver(schema) }); const { data } = useGetOrgBillingDetails(currentOrg?._id ?? ""); - const updateOrgBillingDetails = useUpdateOrgBillingDetails(); + const { mutateAsync, isLoading } = useUpdateOrgBillingDetails(); useEffect(() => { if (data) { @@ -43,7 +43,7 @@ export const InvoiceEmailSection = () => { if (!currentOrg?._id) return; if (email === "") return; - await updateOrgBillingDetails.mutateAsync({ + await mutateAsync({ email, organizationId: currentOrg._id }); @@ -85,15 +85,13 @@ export const InvoiceEmailSection = () => { name="email" /> -
-
+ ); } \ No newline at end of file diff --git a/frontend/src/views/Settings/BillingSettingsPage/components/BillingDetailsTab/PmtMethodsSection.tsx b/frontend/src/views/Settings/BillingSettingsPage/components/BillingDetailsTab/PmtMethodsSection.tsx index ecdf27bb7..1535fa3e4 100644 --- a/frontend/src/views/Settings/BillingSettingsPage/components/BillingDetailsTab/PmtMethodsSection.tsx +++ b/frontend/src/views/Settings/BillingSettingsPage/components/BillingDetailsTab/PmtMethodsSection.tsx @@ -1,6 +1,10 @@ -import { faPlus } from "@fortawesome/free-solid-svg-icons"; -import Button from "@app/components/basic/buttons/Button"; +import { faPlus } from "@fortawesome/free-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; + +import { + Button +} from "@app/components/v2"; import { useOrganization } from "@app/context"; import { useAddOrgPmtMethod } from "@app/hooks/api"; @@ -8,11 +12,11 @@ import { PmtMethodsTable } from "./PmtMethodsTable"; export const PmtMethodsSection = () => { const { currentOrg } = useOrganization(); - const addOrgPmtMethod = useAddOrgPmtMethod(); + const { mutateAsync, isLoading } = useAddOrgPmtMethod(); const handleAddPmtMethodBtnClick = async () => { if (!currentOrg?._id) return; - const url = await addOrgPmtMethod.mutateAsync({ + const url = await mutateAsync({ organizationId: currentOrg._id, success_url: window.location.href, cancel_url: window.location.href @@ -27,16 +31,14 @@ export const PmtMethodsSection = () => {

Payment Methods

-
-
+ diff --git a/frontend/src/views/Settings/BillingSettingsPage/components/BillingDetailsTab/TaxIDSection.tsx b/frontend/src/views/Settings/BillingSettingsPage/components/BillingDetailsTab/TaxIDSection.tsx index ff5f0430d..b7865b2c0 100644 --- a/frontend/src/views/Settings/BillingSettingsPage/components/BillingDetailsTab/TaxIDSection.tsx +++ b/frontend/src/views/Settings/BillingSettingsPage/components/BillingDetailsTab/TaxIDSection.tsx @@ -1,6 +1,9 @@ -import { faPlus } from "@fortawesome/free-solid-svg-icons"; -import Button from "@app/components/basic/buttons/Button"; +import { faPlus } from "@fortawesome/free-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; + +import { Button } from "@app/components/v2"; +// import Button from "@app/components/basic/buttons/Button"; import { usePopUp } from "@app/hooks/usePopUp"; import { TaxIDModal } from "./TaxIDModal"; @@ -17,16 +20,13 @@ export const TaxIDSection = () => {

Tax ID

-
-
+ { const { data: incidentContact, isLoading: IsIncidentContactLoading } = useGetOrgIncidentContact(orgId); - const renameOrg = useRenameOrg(); + const removeUserOrgMembership = useDeleteOrgMembership(); const addUserToOrg = useAddUserToOrg(); const updateOrgUserRole = useUpdateOrgUserRole(); @@ -59,24 +58,6 @@ export const OrgSettingsPage = () => { const isMoreUsersNotAllowed = subscription?.memberLimit ? (subscription.membersUsed >= subscription.memberLimit) : false; - const onRenameOrg = async (name: string) => { - if (!currentOrg?._id) return; - - try { - await renameOrg.mutateAsync({ orgId: currentOrg?._id, newOrgName: name }); - createNotification({ - text: "Successfully renamed organization", - type: "success" - }); - } catch (error) { - console.error(error); - createNotification({ - text: "Failed to rename organization", - type: "error" - }); - } - }; - const onRemoveUserOrgMembership = async (membershipId: string) => { if (!currentOrg?._id) return; @@ -216,7 +197,7 @@ export const OrgSettingsPage = () => {

{t("settings.org.description")}

- +

{t("section.members.org-members")} diff --git a/frontend/src/views/Settings/OrgSettingsPage/components/OrgNameChangeSection/OrgNameChangeSection.tsx b/frontend/src/views/Settings/OrgSettingsPage/components/OrgNameChangeSection/OrgNameChangeSection.tsx index 525b52471..0a1a59075 100644 --- a/frontend/src/views/Settings/OrgSettingsPage/components/OrgNameChangeSection/OrgNameChangeSection.tsx +++ b/frontend/src/views/Settings/OrgSettingsPage/components/OrgNameChangeSection/OrgNameChangeSection.tsx @@ -1,17 +1,13 @@ import { useEffect } from "react"; import { Controller, useForm } from "react-hook-form"; import { useTranslation } from "react-i18next"; -import { faCheck } from "@fortawesome/free-solid-svg-icons"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { yupResolver } from "@hookform/resolvers/yup"; import * as yup from "yup"; +import { useNotificationContext } from "@app/components/context/Notifications/NotificationProvider"; import { Button, FormControl, Input } from "@app/components/v2"; - -type Props = { - orgName?: string; - onOrgNameChange: (name: string) => Promise; -}; +import { useOrganization } from "@app/context"; +import { useRenameOrg } from "@app/hooks/api"; const formSchema = yup.object({ name: yup.string().required().label("Project Name") @@ -19,33 +15,54 @@ const formSchema = yup.object({ type FormData = yup.InferType; -export const OrgNameChangeSection = ({ onOrgNameChange, orgName }: Props): JSX.Element => { +export const OrgNameChangeSection = (): JSX.Element => { + const { t } = useTranslation(); + const { currentOrg } = useOrganization(); + const { createNotification } = useNotificationContext(); const { handleSubmit, control, - reset, - formState: { isDirty, isSubmitting } + reset } = useForm({ resolver: yupResolver(formSchema) }); - const { t } = useTranslation(); + const { mutateAsync, isLoading } = useRenameOrg(); useEffect(() => { - reset({ name: orgName }); - }, [orgName]); + if (currentOrg) { + reset({ name: currentOrg.name }); + } + }, [currentOrg]); const onFormSubmit = async ({ name }: FormData) => { - await onOrgNameChange(name); + try { + if (!currentOrg?._id) return; + if (name === "") return; + + await mutateAsync({ orgId: currentOrg?._id, newOrgName: name }); + createNotification({ + text: "Successfully renamed organization", + type: "success" + }); + } catch (error) { + console.error(error); + createNotification({ + text: "Failed to rename organization", + type: "error" + }); + } }; return ( -

-
-

{t("common.display-name")}

-
+ +

{t("common.display-name")}

+
( - + )} control={control} @@ -53,17 +70,13 @@ export const OrgNameChangeSection = ({ onOrgNameChange, orgName }: Props): JSX.E />
-
); }; From 0e9c71ae9f6b92ede511f00df40eb90461641195 Mon Sep 17 00:00:00 2001 From: akhilmhdh Date: Tue, 27 Jun 2023 23:52:03 +0530 Subject: [PATCH 02/10] feat(multi-line): added support for multi-line in ui --- frontend/src/hooks/index.ts | 1 + frontend/src/hooks/useSyntaxHighlight.tsx | 45 ++++++ .../EnvComparisonRow/EnvComparisonRow.tsx | 126 ++++++--------- .../components/SecretInputRow/MaskedInput.tsx | 153 +++++++++--------- .../SecretInputRow/SecretInputRow.tsx | 57 +++---- 5 files changed, 200 insertions(+), 182 deletions(-) create mode 100644 frontend/src/hooks/useSyntaxHighlight.tsx diff --git a/frontend/src/hooks/index.ts b/frontend/src/hooks/index.ts index fc7acc575..a3ded034c 100644 --- a/frontend/src/hooks/index.ts +++ b/frontend/src/hooks/index.ts @@ -1,4 +1,5 @@ export { useLeaveConfirm } from "./useLeaveConfirm"; export { usePersistentState } from "./usePersistentState"; export { usePopUp } from "./usePopUp"; +export { useSyntaxHighlight } from "./useSyntaxHighlight"; export { useToggle } from "./useToggle"; diff --git a/frontend/src/hooks/useSyntaxHighlight.tsx b/frontend/src/hooks/useSyntaxHighlight.tsx new file mode 100644 index 000000000..edb3f85cd --- /dev/null +++ b/frontend/src/hooks/useSyntaxHighlight.tsx @@ -0,0 +1,45 @@ +import { faCircle } from "@fortawesome/free-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { useCallback } from "react"; + +const REGEX = /([$]{.*?})/g; + +export const useSyntaxHighlight = () => { + const syntaxHighlight = useCallback((text: string, isHidden?: boolean) => { + if (isHidden) { + return text + .split("") + .slice(0, 200) + .map((el, i) => + el === "\n" ? ( + el + ) : ( + + ) + ); + } + + // append a space on last new line this to show new line in ui for code component + const val = text.at(-1) === "\n" ? text.concat(" ") : text; + if (val?.length === 0) return EMPTY; + return val?.split(REGEX).map((word, i) => + word.match(REGEX) !== null ? ( + + ${ + {word.slice(2, word.length - 1)} + } + + ) : ( + + {word} + + ) + ); + }, []); + + return syntaxHighlight; +}; diff --git a/frontend/src/views/DashboardPage/components/EnvComparisonRow/EnvComparisonRow.tsx b/frontend/src/views/DashboardPage/components/EnvComparisonRow/EnvComparisonRow.tsx index 8b75eb39d..2c40e78f6 100644 --- a/frontend/src/views/DashboardPage/components/EnvComparisonRow/EnvComparisonRow.tsx +++ b/frontend/src/views/DashboardPage/components/EnvComparisonRow/EnvComparisonRow.tsx @@ -1,8 +1,9 @@ /* eslint-disable react/jsx-no-useless-fragment */ -import { useCallback, useState } from "react"; -import { faCircle, faEye, faEyeSlash, faKey, faMinus } from "@fortawesome/free-solid-svg-icons"; +import { useCallback, useRef, useState } from "react"; +import { faEye, faEyeSlash, faKey, faMinus } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { twMerge } from "tailwind-merge"; +import { useToggle } from "~/hooks/useToggle"; +import { useSyntaxHighlight } from "@app/hooks"; type Props = { secrets: any[] | undefined; @@ -12,7 +13,8 @@ type Props = { userAvailableEnvs?: any[]; }; -const REGEX = /([$]{.*?})/g; +const SEC_VAL_LINE_HEIGHT = 21; +const MAX_MULTI_LINE = 6; const DashboardInput = ({ isOverridden, @@ -25,84 +27,54 @@ const DashboardInput = ({ isReadOnly?: boolean; secret?: any; }): JSX.Element => { - const syntaxHighlight = useCallback((val: string) => { - if (val === undefined) - return ( - - - - ); - if (val?.length === 0) - return EMPTY; - return val?.split(REGEX).map((word, index) => - word.match(REGEX) !== null ? ( - - {word.slice(0, 2)} - {word.slice(2, word.length - 1)} - {word.slice(word.length - 1, word.length) === "}" ? ( - - {word.slice(word.length - 1, word.length)} - - ) : ( - - {word.slice(word.length - 1, word.length)} - - )} - - ) : ( - - {word} - - ) - ); - }, []); + const ref = useRef(null); + const [isFocused, setIsFocused] = useToggle(); + const syntaxHighlight = useSyntaxHighlight(); + + const value = isOverridden ? secret.valueOverride : secret?.value || ""; + const multilineExpandUnit = ((value?.match(/\n/g)?.length || 0) + 1) * SEC_VAL_LINE_HEIGHT; + const maxMultilineHeight = Math.min(multilineExpandUnit, 21 * MAX_MULTI_LINE); return ( -
- +