From 5f9bb8cd68be3d9f61b520f2771ff44f48952854 Mon Sep 17 00:00:00 2001 From: Lucas Magnus Date: Sun, 25 Feb 2024 14:11:54 -0300 Subject: [PATCH 1/4] feat: add admin validation --- .../components/organisms/menu-actions-asset/index.tsx | 2 +- frontend/src/components/templates/asset-home/index.tsx | 2 +- .../components/templates/contracts-detail/index.tsx | 2 +- frontend/src/components/templates/contracts/index.tsx | 2 +- .../src/components/templates/cost-center/index.tsx | 2 +- frontend/src/components/templates/home/index.tsx | 2 +- frontend/src/components/templates/profile/index.tsx | 2 +- .../templates/role-permissions-template/index.tsx | 2 +- .../src/components/templates/team-members/index.tsx | 2 +- .../templates/team-members/item-menu/index.tsx | 2 +- .../templates/team-members/item-user/index.tsx | 2 +- .../components/templates/token-management/index.tsx | 2 +- .../vault-detail/components/distribute/index.tsx | 2 +- .../src/components/templates/vault-detail/index.tsx | 2 +- frontend/src/hooks/useAuth/context.tsx | 4 ++-- frontend/src/hooks/useAuth/use-auth-types.d.ts | 8 ++++---- frontend/src/utils/index.tsx | 10 +++++----- 17 files changed, 25 insertions(+), 25 deletions(-) diff --git a/frontend/src/components/organisms/menu-actions-asset/index.tsx b/frontend/src/components/organisms/menu-actions-asset/index.tsx index 20602613..98691370 100644 --- a/frontend/src/components/organisms/menu-actions-asset/index.tsx +++ b/frontend/src/components/organisms/menu-actions-asset/index.tsx @@ -21,7 +21,7 @@ import { interface IMenuActionsAsset { action: AssetActions - permissions: Hooks.UseAuthTypes.IUserPermission[] | undefined + permissions: Hooks.UseAuthTypes.IUserPermission | undefined } export const MenuActionsAsset: React.FC = ({ diff --git a/frontend/src/components/templates/asset-home/index.tsx b/frontend/src/components/templates/asset-home/index.tsx index 5e348ea2..a2f89d00 100644 --- a/frontend/src/components/templates/asset-home/index.tsx +++ b/frontend/src/components/templates/asset-home/index.tsx @@ -21,7 +21,7 @@ interface IAssetHomeTemplate { asset: Hooks.UseAssetsTypes.IAssetDto paymentsAsset: Hooks.UseDashboardsTypes.IAsset | undefined chartPeriod: TChartPeriod - permissions: Hooks.UseAuthTypes.IUserPermission[] | undefined + permissions: Hooks.UseAuthTypes.IUserPermission | undefined selectedFile: File | null setSelectedFile: Dispatch> setChartPeriod: Dispatch> diff --git a/frontend/src/components/templates/contracts-detail/index.tsx b/frontend/src/components/templates/contracts-detail/index.tsx index dd53e61f..c8a7f7ea 100644 --- a/frontend/src/components/templates/contracts-detail/index.tsx +++ b/frontend/src/components/templates/contracts-detail/index.tsx @@ -30,7 +30,7 @@ interface IContractsDetailTemplate { currentBalance: string history: Hooks.UseContractsTypes.IHistory[] | undefined deposited: number | undefined - userPermissions: Hooks.UseAuthTypes.IUserPermission[] | undefined + userPermissions: Hooks.UseAuthTypes.IUserPermission | undefined currentInVault: string | undefined hasAssetInVault: boolean hasWallet: boolean diff --git a/frontend/src/components/templates/contracts/index.tsx b/frontend/src/components/templates/contracts/index.tsx index fd9f0b59..0f19598d 100644 --- a/frontend/src/components/templates/contracts/index.tsx +++ b/frontend/src/components/templates/contracts/index.tsx @@ -31,7 +31,7 @@ import { Paginator } from 'components/molecules/paginator' interface IContractsTemplate { loading: boolean contracts: Hooks.UseContractsTypes.IContract[] | undefined - userPermissions: Hooks.UseAuthTypes.IUserPermission[] | undefined + userPermissions: Hooks.UseAuthTypes.IUserPermission | undefined currentPage: number totalPages: number changePage(page: number): void diff --git a/frontend/src/components/templates/cost-center/index.tsx b/frontend/src/components/templates/cost-center/index.tsx index 51e305c6..ac553ea5 100644 --- a/frontend/src/components/templates/cost-center/index.tsx +++ b/frontend/src/components/templates/cost-center/index.tsx @@ -11,7 +11,7 @@ import { IHorizonData } from 'app/core/pages/cost-center' interface ICostCenterTemplate { transactions: Hooks.UseHorizonTypes.ITransactions | undefined - userPermissions: Hooks.UseAuthTypes.IUserPermission[] | undefined + userPermissions: Hooks.UseAuthTypes.IUserPermission | undefined accountData: Hooks.UseHorizonTypes.IAccount | undefined sponsorAccount: string | undefined latestFeeCharged: number | undefined diff --git a/frontend/src/components/templates/home/index.tsx b/frontend/src/components/templates/home/index.tsx index 6b6161a1..6a7d422f 100644 --- a/frontend/src/components/templates/home/index.tsx +++ b/frontend/src/components/templates/home/index.tsx @@ -24,7 +24,7 @@ import { carouselData } from './carousel-data' interface IHomeTemplate { loading: boolean assets: Hooks.UseAssetsTypes.IAssetDto[] | undefined - userPermissions: Hooks.UseAuthTypes.IUserPermission[] | undefined + userPermissions: Hooks.UseAuthTypes.IUserPermission | undefined } export const HomeTemplate: React.FC = () => { diff --git a/frontend/src/components/templates/profile/index.tsx b/frontend/src/components/templates/profile/index.tsx index 9f6bac35..cd0b5142 100644 --- a/frontend/src/components/templates/profile/index.tsx +++ b/frontend/src/components/templates/profile/index.tsx @@ -26,7 +26,7 @@ interface IProfileTemplate { profile: Hooks.UseAuthTypes.IUserDto | undefined roles: Hooks.UseAuthTypes.IRole[] | undefined loadingRoles: boolean - userPermissions: Hooks.UseAuthTypes.IUserPermission[] | undefined + userPermissions: Hooks.UseAuthTypes.IUserPermission | undefined } export const ProfileTemplate: React.FC = ({ diff --git a/frontend/src/components/templates/role-permissions-template/index.tsx b/frontend/src/components/templates/role-permissions-template/index.tsx index 940db641..77d7281a 100644 --- a/frontend/src/components/templates/role-permissions-template/index.tsx +++ b/frontend/src/components/templates/role-permissions-template/index.tsx @@ -26,7 +26,7 @@ import { IChange } from 'app/core/pages/role-permissions' interface IRolePermissionsTemplate { loading: boolean roles: Hooks.UseAuthTypes.IRole[] | undefined - userPermissions: Hooks.UseAuthTypes.IUserPermission[] | undefined + userPermissions: Hooks.UseAuthTypes.IUserPermission | undefined permissions: Hooks.UseAuthTypes.IPermission[] | undefined rolesPermissions: Hooks.UseAuthTypes.IRolePermission[] | undefined updatingRolesPermissions: boolean diff --git a/frontend/src/components/templates/team-members/index.tsx b/frontend/src/components/templates/team-members/index.tsx index 302250d5..a5018712 100644 --- a/frontend/src/components/templates/team-members/index.tsx +++ b/frontend/src/components/templates/team-members/index.tsx @@ -27,7 +27,7 @@ interface ISettingsTemplate { handleEditRole(params: Hooks.UseAuthTypes.IUserRole): Promise roles: Hooks.UseAuthTypes.IRole[] | undefined loadingRoles: boolean - permissions: Hooks.UseAuthTypes.IUserPermission[] | undefined + permissions: Hooks.UseAuthTypes.IUserPermission | undefined } export const TeamMembersTemplate: React.FC = ({ diff --git a/frontend/src/components/templates/team-members/item-menu/index.tsx b/frontend/src/components/templates/team-members/item-menu/index.tsx index dd856021..13eb3514 100644 --- a/frontend/src/components/templates/team-members/item-menu/index.tsx +++ b/frontend/src/components/templates/team-members/item-menu/index.tsx @@ -14,7 +14,7 @@ import { MenuDotsIcon } from 'components/icons' interface IItemMenu { onOpen(): void - permissions: Hooks.UseAuthTypes.IUserPermission[] | undefined + permissions: Hooks.UseAuthTypes.IUserPermission | undefined } export const ItemMenu: React.FC = ({ onOpen, permissions }) => { diff --git a/frontend/src/components/templates/team-members/item-user/index.tsx b/frontend/src/components/templates/team-members/item-user/index.tsx index 066154a1..09ff5e53 100644 --- a/frontend/src/components/templates/team-members/item-user/index.tsx +++ b/frontend/src/components/templates/team-members/item-user/index.tsx @@ -13,7 +13,7 @@ interface IItemUser { handleEditRole(params: Hooks.UseAuthTypes.IUserRole): Promise roles: Hooks.UseAuthTypes.IRole[] | undefined loadingRoles: boolean - permissions: Hooks.UseAuthTypes.IUserPermission[] | undefined + permissions: Hooks.UseAuthTypes.IUserPermission | undefined } export const ItemUser: React.FC = ({ diff --git a/frontend/src/components/templates/token-management/index.tsx b/frontend/src/components/templates/token-management/index.tsx index 58590fb4..429c881f 100644 --- a/frontend/src/components/templates/token-management/index.tsx +++ b/frontend/src/components/templates/token-management/index.tsx @@ -43,7 +43,7 @@ import { Filter } from './filter' interface ITokenManagementTemplate { loading: boolean assets: Hooks.UseAssetsTypes.IAssetDto[] | undefined - userPermissions: Hooks.UseAuthTypes.IUserPermission[] | undefined + userPermissions: Hooks.UseAuthTypes.IUserPermission | undefined currentPage: number totalPages: number changePage(page: number): void diff --git a/frontend/src/components/templates/vault-detail/components/distribute/index.tsx b/frontend/src/components/templates/vault-detail/components/distribute/index.tsx index 6f502c16..1bbca68c 100644 --- a/frontend/src/components/templates/vault-detail/components/distribute/index.tsx +++ b/frontend/src/components/templates/vault-detail/components/distribute/index.tsx @@ -38,7 +38,7 @@ interface IDistributeVault { vaults: Hooks.UseVaultsTypes.IVault[] | undefined vault: Hooks.UseVaultsTypes.IVault | undefined selectedAsset: Hooks.UseAssetsTypes.IAssetDto | undefined - userPermissions: Hooks.UseAuthTypes.IUserPermission[] | undefined + userPermissions: Hooks.UseAuthTypes.IUserPermission | undefined } export const DistributeVault: React.FC = ({ diff --git a/frontend/src/components/templates/vault-detail/index.tsx b/frontend/src/components/templates/vault-detail/index.tsx index 0d9ed98e..80836699 100644 --- a/frontend/src/components/templates/vault-detail/index.tsx +++ b/frontend/src/components/templates/vault-detail/index.tsx @@ -28,7 +28,7 @@ interface IVaultDetailTemplate { vaultCategories: Hooks.UseVaultsTypes.IVaultCategory[] | undefined deletingVault: boolean isPrevDisabled: boolean - userPermissions: Hooks.UseAuthTypes.IUserPermission[] | undefined + userPermissions: Hooks.UseAuthTypes.IUserPermission | undefined loadingUserPermissions: boolean onSubmit( amount: string, diff --git a/frontend/src/hooks/useAuth/context.tsx b/frontend/src/hooks/useAuth/context.tsx index 8511a34d..5cdaca05 100644 --- a/frontend/src/hooks/useAuth/context.tsx +++ b/frontend/src/hooks/useAuth/context.tsx @@ -33,7 +33,7 @@ export const AuthProvider: React.FC = ({ children }) => { Hooks.UseAuthTypes.IUserDto | undefined >() const [userPermissions, setUserPermissions] = useState< - Hooks.UseAuthTypes.IUserPermission[] | undefined + Hooks.UseAuthTypes.IUserPermission | undefined >() const [rolesPermissions, setRolesPermissions] = useState< Hooks.UseAuthTypes.IRolePermission[] | undefined @@ -203,7 +203,7 @@ export const AuthProvider: React.FC = ({ children }) => { }, [getAccountData]) const getUserPermissions = useCallback(async (): Promise< - Hooks.UseAuthTypes.IUserPermission[] | undefined + Hooks.UseAuthTypes.IUserPermission | undefined > => { setLoadingUserPermissions(true) try { diff --git a/frontend/src/hooks/useAuth/use-auth-types.d.ts b/frontend/src/hooks/useAuth/use-auth-types.d.ts index 3a520376..35717e90 100644 --- a/frontend/src/hooks/useAuth/use-auth-types.d.ts +++ b/frontend/src/hooks/useAuth/use-auth-types.d.ts @@ -46,8 +46,8 @@ declare namespace Hooks { } interface IUserPermission { - name: string - action: string + admin: boolean + permissions: { name: string; action: string }[] } interface IRolePermission { @@ -70,7 +70,7 @@ declare namespace Hooks { getProfile: () => Promise editUsersRole: (params: IUserRole) => Promise getUserPermissions: () => Promise< - Hooks.UseAuthTypes.IUserPermission[] | undefined + Hooks.UseAuthTypes.IUserPermission | undefined > getRolesPermissions: () => Promise< Hooks.UseAuthTypes.IRolePermission[] | undefined @@ -91,7 +91,7 @@ declare namespace Hooks { roles: IRole[] | undefined users: IUserDto[] | undefined profile: IUserDto | undefined - userPermissions: IUserPermission[] | undefined + userPermissions: IUserPermission | undefined rolesPermissions: IRolePermission[] | undefined permissions: IPermission[] | undefined updatingRolesPermissions: boolean diff --git a/frontend/src/utils/index.tsx b/frontend/src/utils/index.tsx index 63c9d231..1a48704d 100644 --- a/frontend/src/utils/index.tsx +++ b/frontend/src/utils/index.tsx @@ -6,12 +6,12 @@ export const isDark = (colorMode: 'dark' | 'light'): boolean => { export const havePermission = ( permission: Permissions, - permissions: Hooks.UseAuthTypes.IUserPermission[] | undefined + userPermission: Hooks.UseAuthTypes.IUserPermission | undefined ): boolean => { - if (!permissions) return false + if (userPermission?.admin) return true + if (!userPermission) return false return ( - permissions.filter( - (item: Hooks.UseAuthTypes.IUserPermission) => item.action === permission - ).length > 0 + userPermission.permissions.filter(item => item.action === permission) + .length > 0 ) } From 91ab1eeec2cbf1785e813005597f010d06d9e05f Mon Sep 17 00:00:00 2001 From: Lucas Magnus Date: Sun, 25 Feb 2024 16:06:49 -0300 Subject: [PATCH 2/4] feat: rename asset --- .../src/app/core/pages/asset-home/index.tsx | 38 ++++++- .../src/app/core/pages/cost-center/index.tsx | 9 +- .../app/core/pages/role-permissions/index.tsx | 6 +- .../src/app/core/pages/roles-manage/index.tsx | 6 +- .../src/app/core/pages/team-members/index.tsx | 6 +- .../components/atoms/mob-nav-item/index.tsx | 2 +- .../src/components/molecules/header/index.tsx | 2 +- .../molecules/sidebar-content/index.tsx | 14 +-- .../organisms/menu-admin-mobile/index.tsx | 2 +- .../components/organisms/sidebar/index.tsx | 4 +- .../components/form-edit-asset/index.tsx | 56 ++++++++++ .../components/templates/asset-home/index.tsx | 101 +++++++++++++----- .../templates/cost-center/index.tsx | 4 +- .../role-permissions-template/index.tsx | 4 +- .../templates/roles-manage-template/index.tsx | 6 +- .../templates/team-members/index.tsx | 4 +- frontend/src/hooks/useAssets/context.tsx | 21 ++++ .../src/hooks/useAssets/use-assets-types.d.ts | 7 ++ 18 files changed, 234 insertions(+), 58 deletions(-) create mode 100644 frontend/src/components/templates/asset-home/components/form-edit-asset/index.tsx diff --git a/frontend/src/app/core/pages/asset-home/index.tsx b/frontend/src/app/core/pages/asset-home/index.tsx index 7694173a..ae9cf24e 100644 --- a/frontend/src/app/core/pages/asset-home/index.tsx +++ b/frontend/src/app/core/pages/asset-home/index.tsx @@ -35,7 +35,13 @@ export const AssetHome: React.FC = () => { const [isLargerThanMd] = useMediaQuery('(min-width: 768px)') const [isSmallerThanMd] = useMediaQuery('(max-width: 768px)') - const { loadingAsset, getAssetById, updateImage } = useAssets() + const { + loadingAsset, + updatingAsset, + getAssetById, + updateImage, + updateAsset, + } = useAssets() const { loadingUserPermissions, userPermissions, getUserPermissions } = useAuth() const { getPaymentsByAssetId, loadingChart } = useDashboards() @@ -90,6 +96,34 @@ export const AssetHome: React.FC = () => { return false } + const handleUpdateAsset = async ( + name: string, + code: string + ): Promise => { + try { + if (!asset?.id) { + throw new Error('Invalid asset') + } + const isSuccess = await updateAsset(asset.id, { name: name, code: code }) + + if (isSuccess) { + if (id) { + getAssetById(id).then(asset => setAsset(asset)) + } + return true + } + + toastError(MessagesError.errorOccurred) + } catch (error) { + let message + if (error instanceof Error) message = error.message + else message = String(error) + toastError(message) + } + + return false + } + const toastError = (message: string): void => { toast({ title: 'Update logo error!', @@ -135,6 +169,8 @@ export const AssetHome: React.FC = () => { setSelectedFile={setSelectedFile} setChartPeriod={setChartPeriod} handleUploadImage={handleUploadImage} + updatingAsset={updatingAsset} + handleUpdateAsset={handleUpdateAsset} /> )} diff --git a/frontend/src/app/core/pages/cost-center/index.tsx b/frontend/src/app/core/pages/cost-center/index.tsx index 8868b0f4..2ce39564 100644 --- a/frontend/src/app/core/pages/cost-center/index.tsx +++ b/frontend/src/app/core/pages/cost-center/index.tsx @@ -26,7 +26,8 @@ export interface IHorizonData { } export const CostCenter: React.FC = () => { - const [isLargerThanMd] = useMediaQuery('(min-width: 768px)') + const [isLargerThanLg] = useMediaQuery('(min-width: 992px)') + const [sponsorAccount, setSponsorAccount] = useState() const [transactions, setTransactions] = useState() @@ -279,7 +280,7 @@ export const CostCenter: React.FC = () => { { getTransactionData={getTransactionData} /> - {isLargerThanMd && ( + {isLargerThanLg && ( @@ -319,7 +320,7 @@ export const CostCenter: React.FC = () => { )} - {!isLargerThanMd && ( + {!isLargerThanLg && ( {operatingExpensesHelperP1} diff --git a/frontend/src/app/core/pages/role-permissions/index.tsx b/frontend/src/app/core/pages/role-permissions/index.tsx index 92fbf1d0..cd07cbd6 100644 --- a/frontend/src/app/core/pages/role-permissions/index.tsx +++ b/frontend/src/app/core/pages/role-permissions/index.tsx @@ -18,7 +18,7 @@ export interface IChange { } export const RolePermissions: React.FC = () => { - const [isLargerThanMd] = useMediaQuery('(min-width: 768px)') + const [isLargerThanLg] = useMediaQuery('(min-width: 992px)') const [changes, setChanges] = useState([]) const [loading, setLoading] = useState(true) @@ -97,7 +97,7 @@ export const RolePermissions: React.FC = () => { { setChanges={setChanges} /> - {isLargerThanMd && ( + {isLargerThanLg && ( diff --git a/frontend/src/app/core/pages/roles-manage/index.tsx b/frontend/src/app/core/pages/roles-manage/index.tsx index f6b5ad3f..c0392589 100644 --- a/frontend/src/app/core/pages/roles-manage/index.tsx +++ b/frontend/src/app/core/pages/roles-manage/index.tsx @@ -12,7 +12,7 @@ import { Sidebar } from 'components/organisms/sidebar' import { RolesManageTemplate } from 'components/templates/roles-manage-template' export const RolesManage: React.FC = () => { - const [isLargerThanMd] = useMediaQuery('(min-width: 768px)') + const [isLargerThanLg] = useMediaQuery('(min-width: 992px)') const { getRoles, @@ -112,7 +112,7 @@ export const RolesManage: React.FC = () => { { handleRole={handleRole} /> - {isLargerThanMd && ( + {isLargerThanLg && ( diff --git a/frontend/src/app/core/pages/team-members/index.tsx b/frontend/src/app/core/pages/team-members/index.tsx index ec3970d2..bc86698e 100644 --- a/frontend/src/app/core/pages/team-members/index.tsx +++ b/frontend/src/app/core/pages/team-members/index.tsx @@ -11,7 +11,7 @@ import { Sidebar } from 'components/organisms/sidebar' import { TeamMembersTemplate } from 'components/templates/team-members' export const TeamMembers: React.FC = () => { - const [isLargerThanMd] = useMediaQuery('(min-width: 768px)') + const [isLargerThanLg] = useMediaQuery('(min-width: 992px)') const { getAllUsers, @@ -52,7 +52,7 @@ export const TeamMembers: React.FC = () => { { permissions={userPermissions} /> - {isLargerThanMd && ( + {isLargerThanLg && ( diff --git a/frontend/src/components/atoms/mob-nav-item/index.tsx b/frontend/src/components/atoms/mob-nav-item/index.tsx index f44b1a74..70f09cf0 100644 --- a/frontend/src/components/atoms/mob-nav-item/index.tsx +++ b/frontend/src/components/atoms/mob-nav-item/index.tsx @@ -13,7 +13,7 @@ export const MobileNav: React.FC = ({ onOpen }: IMobileProps) => { onClick={onOpen} aria-label="open menu" me={4} - display={{ base: 'flex', md: 'none' }} + display={{ base: 'flex', lg: 'none' }} fill="black" _dark={{ fill: 'white' }} icon={} diff --git a/frontend/src/components/molecules/header/index.tsx b/frontend/src/components/molecules/header/index.tsx index 38e932ff..ac3e3df0 100644 --- a/frontend/src/components/molecules/header/index.tsx +++ b/frontend/src/components/molecules/header/index.tsx @@ -65,7 +65,7 @@ export const Header: React.FC = ({ onOpen }) => { h="4.5rem" w="full" align="center" - ps={{ base: 2, md: 12 }} + ps={{ base: 2, lg: 12 }} pe={6} pos="fixed" zIndex={99} diff --git a/frontend/src/components/molecules/sidebar-content/index.tsx b/frontend/src/components/molecules/sidebar-content/index.tsx index 711e414f..d4da01d2 100644 --- a/frontend/src/components/molecules/sidebar-content/index.tsx +++ b/frontend/src/components/molecules/sidebar-content/index.tsx @@ -31,18 +31,18 @@ export const SidebarContent: React.FC = ({ onClose, ...rest }: ISidebarProps) => { - const [isLargerThanMd] = useMediaQuery('(min-width: 768px)') + const [isLargerThanLg] = useMediaQuery('(min-width: 992px)') return ( = ({ h={14} justifyContent="space-between" alignItems="center" - display={{ base: 'flex', md: 'none' }} + display={{ base: 'flex', lg: 'none' }} w="full" pl="2rem" mb="1rem" @@ -93,7 +93,7 @@ export const SidebarContent: React.FC = ({ ))} - {isLargerThanMd && } + {isLargerThanLg && } } @@ -110,7 +110,7 @@ export const SidebarContent: React.FC = ({ > Administration - {!isLargerThanMd && } + {!isLargerThanLg && } = ({ selected }) => { } path={`${PathRoute.COST_CENTER}`} /> diff --git a/frontend/src/components/organisms/sidebar/index.tsx b/frontend/src/components/organisms/sidebar/index.tsx index 0b85d3da..103ef633 100644 --- a/frontend/src/components/organisms/sidebar/index.tsx +++ b/frontend/src/components/organisms/sidebar/index.tsx @@ -74,7 +74,7 @@ export const Sidebar: React.FC = ({ children, highlightMenu }) => { onClose()} - display={{ base: 'none', md: 'block' }} + display={{ base: 'none', lg: 'block' }} highlightMenu={highlightMenu} /> = ({ children, highlightMenu }) => { /> - + {children} diff --git a/frontend/src/components/templates/asset-home/components/form-edit-asset/index.tsx b/frontend/src/components/templates/asset-home/components/form-edit-asset/index.tsx new file mode 100644 index 00000000..c11ee468 --- /dev/null +++ b/frontend/src/components/templates/asset-home/components/form-edit-asset/index.tsx @@ -0,0 +1,56 @@ +import { Stack, Input, ButtonGroup, Button } from '@chakra-ui/react' +import { useState } from 'react' + +interface IProps { + asset: Hooks.UseAssetsTypes.IAssetDto + updatingAsset: boolean + handleUpdate(name: string, code: string): void + onClose(): void +} + +export const FormEditAsset: React.FC = ({ + asset, + updatingAsset, + handleUpdate, + onClose, +}) => { + const [name, setName] = useState(asset.name) + const [code, setCode] = useState(asset.code) + + const onSubmit = (): void => { + if (!name || !code) return + + handleUpdate(name, code) + } + + return ( + + setName(event.target.value)} + mt="1rem" + /> + setCode(event.target.value)} + /> + + + + + + ) +} diff --git a/frontend/src/components/templates/asset-home/index.tsx b/frontend/src/components/templates/asset-home/index.tsx index a2f89d00..e056c95b 100644 --- a/frontend/src/components/templates/asset-home/index.tsx +++ b/frontend/src/components/templates/asset-home/index.tsx @@ -1,4 +1,17 @@ -import { Container, Flex, Tag, Text } from '@chakra-ui/react' +import { + Container, + Flex, + FocusLock, + IconButton, + Popover, + PopoverArrow, + PopoverCloseButton, + PopoverContent, + PopoverTrigger, + Tag, + Text, + useDisclosure, +} from '@chakra-ui/react' import React, { Dispatch, SetStateAction } from 'react' import { havePermission } from 'utils' @@ -8,8 +21,9 @@ import { TooltipsData } from 'utils/constants/tooltips-data' import { formatAccount, toCrypto } from 'utils/formatter' import { AssetImage } from './components/asset-image' +import { FormEditAsset } from './components/form-edit-asset' import { Permissions } from 'components/enums/permissions' -import { LinkIcon, WalletIcon } from 'components/icons' +import { EditIcon, LinkIcon, WalletIcon } from 'components/icons' import { TChartPeriod } from 'components/molecules/chart-period' import { ChartPayments } from '../../molecules/chart-payments' @@ -18,6 +32,7 @@ import { InfoCard } from '../../molecules/info-card' interface IAssetHomeTemplate { loading: boolean loadingChart: boolean + updatingAsset: boolean asset: Hooks.UseAssetsTypes.IAssetDto paymentsAsset: Hooks.UseDashboardsTypes.IAsset | undefined chartPeriod: TChartPeriod @@ -26,19 +41,25 @@ interface IAssetHomeTemplate { setSelectedFile: Dispatch> setChartPeriod: Dispatch> handleUploadImage(): Promise + handleUpdateAsset(name: string, code: string): Promise } export const AssetHomeTemplate: React.FC = ({ asset, loadingChart, paymentsAsset, + updatingAsset, chartPeriod, permissions, selectedFile, setChartPeriod, setSelectedFile, handleUploadImage, + handleUpdateAsset, }) => { + const { onOpen, onClose, isOpen } = useDisclosure() + const firstFieldRef = React.useRef(null) + return ( @@ -57,33 +78,65 @@ export const AssetHomeTemplate: React.FC = ({ - - - {`${asset.name} (${asset.code})`} - - - window.open( - `${STELLAR_EXPERT_ASSET}/${asset.code}-${asset.issuer.key.publicKey}`, - '_blank' - ) - } - > - + + + + {`${asset.name} (${asset.code})`} + + {permissions?.admin && ( + + + } + aria-label="Edit" + /> + + + + + + + + + + )} + + {typesAsset.find(type => type.id === asset.asset_type) + ?.name || ''} + + + + window.open( + `${STELLAR_EXPERT_ASSET}/${asset.code}-${asset.issuer.key.publicKey}`, + '_blank' + ) + } + > + - - {typesAsset.find(type => type.id === asset.asset_type)?.name || - ''} - @@ -131,7 +184,7 @@ export const AssetHomeTemplate: React.FC = ({ } + icon={} value={toCrypto(Number(asset.assetData?.amount || 0))} helper={TooltipsData.totalSupply} /> diff --git a/frontend/src/components/templates/cost-center/index.tsx b/frontend/src/components/templates/cost-center/index.tsx index ac553ea5..302ba876 100644 --- a/frontend/src/components/templates/cost-center/index.tsx +++ b/frontend/src/components/templates/cost-center/index.tsx @@ -36,7 +36,7 @@ export const CostCenterTemplate: React.FC = ({ getTransactionsByLink, getTransactionData, }) => { - const [isSmallerThanMd] = useMediaQuery('(max-width: 768px)') + const [isLargerThanLg] = useMediaQuery('(min-width: 992px)') return ( @@ -50,7 +50,7 @@ export const CostCenterTemplate: React.FC = ({ Administration - {isSmallerThanMd && } + {!isLargerThanLg && } = ({ onSubmit, setChanges, }) => { - const [isSmallerThanMd] = useMediaQuery('(max-width: 768px)') + const [isLargerThanLg] = useMediaQuery('(min-width: 992px)') const havePermissionByRole = ( permissionId: number, @@ -95,7 +95,7 @@ export const RolePermissionsTemplate: React.FC = ({ Administration - {isSmallerThanMd && } + {!isLargerThanLg && } = ({ handleDeleteRole, }) => { const { isOpen, onOpen, onClose } = useDisclosure() - const [isSmallerThanMd] = useMediaQuery('(max-width: 768px)') + const [isLargerThanLg] = useMediaQuery('(min-width: 992px)') return ( <> @@ -69,7 +69,7 @@ export const RolesManageTemplate: React.FC = ({ Administration - {isSmallerThanMd && } + {!isLargerThanLg && } = ({ permissions, }) => { const [isSmallerThanMd] = useMediaQuery('(max-width: 768px)') + const [isLargerThanLg] = useMediaQuery('(min-width: 992px)') + const { onOpen } = useDisclosure() return ( @@ -53,7 +55,7 @@ export const TeamMembersTemplate: React.FC = ({ Administration - {isSmallerThanMd && } + {!isLargerThanLg && } diff --git a/frontend/src/hooks/useAssets/context.tsx b/frontend/src/hooks/useAssets/context.tsx index c6f349df..046ad787 100644 --- a/frontend/src/hooks/useAssets/context.tsx +++ b/frontend/src/hooks/useAssets/context.tsx @@ -18,6 +18,7 @@ export const AssetsProvider: React.FC = ({ children }) => { const [loadingAssets, setLoadingAssets] = useState(true) const [loadingAsset, setLoadingAsset] = useState(true) const [loadingOperation, setLoadingOperation] = useState(false) + const [updatingAsset, setUpdatingAsset] = useState(false) const [assets, setAssets] = useState< Hooks.UseAssetsTypes.IAssetDto[] | undefined >() @@ -369,6 +370,24 @@ export const AssetsProvider: React.FC = ({ children }) => { } } + const updateAsset = async ( + id: number, + params: Hooks.UseAssetsTypes.IAssetUpdate + ): Promise => { + setUpdatingAsset(true) + try { + const response = await http.put(`/assets/${id}/update-name-code`, params) + return response.status === 200 + } catch (error) { + if (axios.isAxiosError(error)) { + throw new Error(error.message) + } + throw new Error(MessagesError.errorOccurred) + } finally { + setUpdatingAsset(false) + } + } + return ( = ({ children }) => { loadingAsset, loadingOperation, assets, + updatingAsset, mint, burn, distribute, @@ -391,6 +411,7 @@ export const AssetsProvider: React.FC = ({ children }) => { updateImage, updateContractId, getPagedAssets, + updateAsset, }} > {children} diff --git a/frontend/src/hooks/useAssets/use-assets-types.d.ts b/frontend/src/hooks/useAssets/use-assets-types.d.ts index d61362c5..b1fcc085 100644 --- a/frontend/src/hooks/useAssets/use-assets-types.d.ts +++ b/frontend/src/hooks/useAssets/use-assets-types.d.ts @@ -142,10 +142,16 @@ declare namespace Hooks { freeze_enabled?: boolean } + interface IAssetUpdate { + name: string + code: string + } + interface IAssetsContext { loadingOperation: boolean loadingAssets: boolean loadingAsset: boolean + updatingAsset: boolean assets: IAssetDto[] | undefined mint: (params: IMintRequest) => Promise burn: (params: IBurnRequest) => Promise @@ -169,6 +175,7 @@ declare namespace Hooks { limit: number filters?: IFilter }) => Promise + updateAsset: (id: number, params: IAssetUpdate) => Promise } } } From 5b924b117d4f304405b95641647736382af3036a Mon Sep 17 00:00:00 2001 From: Lucas Magnus Date: Mon, 26 Feb 2024 09:14:34 -0300 Subject: [PATCH 3/4] feat: role manage super user --- frontend/src/app/core/pages/roles-manage/index.tsx | 7 +++++++ .../components/templates/roles-manage-template/index.tsx | 3 +++ .../templates/roles-manage-template/item-role/index.tsx | 7 ++++++- 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/frontend/src/app/core/pages/roles-manage/index.tsx b/frontend/src/app/core/pages/roles-manage/index.tsx index c0392589..19779340 100644 --- a/frontend/src/app/core/pages/roles-manage/index.tsx +++ b/frontend/src/app/core/pages/roles-manage/index.tsx @@ -20,11 +20,13 @@ export const RolesManage: React.FC = () => { updateRole, deleteRole, getProfile, + getUserPermissions, creatingRole, updatingRole, roles, loadingRoles, deletingRole, + userPermissions } = useAuth() const toast = useToast() @@ -33,6 +35,10 @@ export const RolesManage: React.FC = () => { getRoles() }, [getRoles]) + useEffect(() => { + getUserPermissions() + }, [getUserPermissions]) + const handleRole = async (name: string, id?: number): Promise => { try { const profile = await getProfile() @@ -124,6 +130,7 @@ export const RolesManage: React.FC = () => { updatingRole={updatingRole} deletingRole={deletingRole} loadingRoles={loadingRoles} + userPermissions={userPermissions} handleDeleteRole={handleDeleteRole} handleRole={handleRole} /> diff --git a/frontend/src/components/templates/roles-manage-template/index.tsx b/frontend/src/components/templates/roles-manage-template/index.tsx index 95cedbc1..849c94a4 100644 --- a/frontend/src/components/templates/roles-manage-template/index.tsx +++ b/frontend/src/components/templates/roles-manage-template/index.tsx @@ -28,6 +28,7 @@ interface IRolesManageTemplate { creatingRole: boolean updatingRole: boolean deletingRole: boolean + userPermissions: Hooks.UseAuthTypes.IUserPermission | undefined handleRole(name: string, id?: number): Promise handleDeleteRole(id: number, idNewUsersRole: number): Promise } @@ -38,6 +39,7 @@ export const RolesManageTemplate: React.FC = ({ updatingRole, deletingRole, loadingRoles, + userPermissions, handleRole, handleDeleteRole, }) => { @@ -114,6 +116,7 @@ export const RolesManageTemplate: React.FC = ({ loading={creatingRole || updatingRole || deletingRole} roles={roles} loadingRoles={loadingRoles} + userPermissions={userPermissions} handleRole={handleRole} handleDeleteRole={handleDeleteRole} /> diff --git a/frontend/src/components/templates/roles-manage-template/item-role/index.tsx b/frontend/src/components/templates/roles-manage-template/item-role/index.tsx index a9ba37dd..9b28bd0e 100644 --- a/frontend/src/components/templates/roles-manage-template/item-role/index.tsx +++ b/frontend/src/components/templates/roles-manage-template/item-role/index.tsx @@ -13,6 +13,7 @@ interface IItemRole { roles: Hooks.UseAuthTypes.IRole[] | undefined loading: boolean loadingRoles: boolean + userPermissions: Hooks.UseAuthTypes.IUserPermission | undefined handleRole(name: string, id?: number): Promise handleDeleteRole(id: number, idNewUsersRole: number): Promise } @@ -22,6 +23,7 @@ export const ItemRole: React.FC = ({ roles, loading, loadingRoles, + userPermissions, handleRole, handleDeleteRole, }) => { @@ -38,7 +40,10 @@ export const ItemRole: React.FC = ({ } = useDisclosure() const isDisabled = (role: Hooks.UseAuthTypes.IRole): boolean => { - return role.admin === 1 || role.created_by != Authentication.getUser()?.id + if (userPermissions?.admin) { + return false + } + return role.created_by != Authentication.getUser()?.id } return ( From 9f4d10e450efdcbf27418310fd3f5efaf6f2d781 Mon Sep 17 00:00:00 2001 From: Lucas Magnus Date: Mon, 26 Feb 2024 11:07:55 -0300 Subject: [PATCH 4/4] feat: update username --- .../src/app/core/pages/team-members/index.tsx | 19 +++- .../templates/team-members/index.tsx | 25 +++-- .../team-members/item-menu/index.tsx | 14 ++- .../team-members/item-user/index.tsx | 39 ++++++-- .../modal-update-username/index.tsx | 99 +++++++++++++++++++ frontend/src/hooks/useAuth/context.tsx | 22 +++++ .../src/hooks/useAuth/use-auth-types.d.ts | 2 + 7 files changed, 202 insertions(+), 18 deletions(-) create mode 100644 frontend/src/components/templates/team-members/modal-update-username/index.tsx diff --git a/frontend/src/app/core/pages/team-members/index.tsx b/frontend/src/app/core/pages/team-members/index.tsx index bc86698e..b2432897 100644 --- a/frontend/src/app/core/pages/team-members/index.tsx +++ b/frontend/src/app/core/pages/team-members/index.tsx @@ -16,6 +16,7 @@ export const TeamMembers: React.FC = () => { const { getAllUsers, editUsersRole, + updateUsername, getRoles, getUserPermissions, users, @@ -24,6 +25,7 @@ export const TeamMembers: React.FC = () => { loadingRoles, userPermissions, loadingUserPermissions, + updatingUsername, } = useAuth() useEffect(() => { @@ -42,6 +44,19 @@ export const TeamMembers: React.FC = () => { return false } + const handleUpdateUsername = async ( + id: number, + name: string + ): Promise => { + const isSuccess = await updateUsername(id, name) + + if (isSuccess) { + getAllUsers() + return true + } + return false + } + useEffect(() => { getAllUsers() getRoles() @@ -61,10 +76,12 @@ export const TeamMembers: React.FC = () => { {isLargerThanLg && ( diff --git a/frontend/src/components/templates/team-members/index.tsx b/frontend/src/components/templates/team-members/index.tsx index d77f019a..9c922a68 100644 --- a/frontend/src/components/templates/team-members/index.tsx +++ b/frontend/src/components/templates/team-members/index.tsx @@ -21,27 +21,31 @@ import { MenuAdminMobile } from 'components/organisms/menu-admin-mobile' import { ItemMenu } from './item-menu' import { ItemUser } from './item-user' -interface ISettingsTemplate { +interface ITeamMembersTemplateTemplate { users: Hooks.UseAuthTypes.IUserDto[] | undefined loading: boolean - handleEditRole(params: Hooks.UseAuthTypes.IUserRole): Promise roles: Hooks.UseAuthTypes.IRole[] | undefined loadingRoles: boolean permissions: Hooks.UseAuthTypes.IUserPermission | undefined + updatingUsername: boolean + handleEditRole(params: Hooks.UseAuthTypes.IUserRole): Promise + handleUpdateUsername(id: number, name: string): Promise } -export const TeamMembersTemplate: React.FC = ({ +export const TeamMembersTemplate: React.FC = ({ users, loading, - handleEditRole, roles, loadingRoles, permissions, + updatingUsername, + handleEditRole, + handleUpdateUsername, }) => { const [isSmallerThanMd] = useMediaQuery('(max-width: 768px)') const [isLargerThanLg] = useMediaQuery('(min-width: 992px)') - const { onOpen } = useDisclosure() + const { onOpen: onOpenChangeRole, onOpen: onOpenRename } = useDisclosure() return ( @@ -107,7 +111,11 @@ export const TeamMembersTemplate: React.FC = ({ {`${user.role}`} - + ))} @@ -118,6 +126,7 @@ export const TeamMembersTemplate: React.FC = ({ ID Member Role + @@ -126,10 +135,12 @@ export const TeamMembersTemplate: React.FC = ({ key={index} user={user} loading={loading} - handleEditRole={handleEditRole} roles={roles} loadingRoles={loadingRoles} permissions={permissions} + updatingUsername={updatingUsername} + handleEditRole={handleEditRole} + handleUpdateUsername={handleUpdateUsername} /> ))} diff --git a/frontend/src/components/templates/team-members/item-menu/index.tsx b/frontend/src/components/templates/team-members/item-menu/index.tsx index 13eb3514..c17b914a 100644 --- a/frontend/src/components/templates/team-members/item-menu/index.tsx +++ b/frontend/src/components/templates/team-members/item-menu/index.tsx @@ -13,11 +13,16 @@ import { Permissions } from 'components/enums/permissions' import { MenuDotsIcon } from 'components/icons' interface IItemMenu { - onOpen(): void + onOpenChangeRole(): void + onOpenRename(): void permissions: Hooks.UseAuthTypes.IUserPermission | undefined } -export const ItemMenu: React.FC = ({ onOpen, permissions }) => { +export const ItemMenu: React.FC = ({ + onOpenChangeRole, + onOpenRename, + permissions, +}) => { return ( <> {havePermission(Permissions.EDIT_USERS_ROLE, permissions) && ( @@ -36,7 +41,10 @@ export const ItemMenu: React.FC = ({ onOpen, permissions }) => { icon={} /> - Change role + Change role + {permissions?.admin && ( + Edit username + )} )} diff --git a/frontend/src/components/templates/team-members/item-user/index.tsx b/frontend/src/components/templates/team-members/item-user/index.tsx index 09ff5e53..0ff96f81 100644 --- a/frontend/src/components/templates/team-members/item-user/index.tsx +++ b/frontend/src/components/templates/team-members/item-user/index.tsx @@ -6,36 +6,57 @@ import { formatName } from 'utils/formatter' import { ModalEditRole } from 'components/molecules' import { ItemMenu } from '../item-menu' +import { ModalUpdateUsername } from '../modal-update-username' interface IItemUser { user: Hooks.UseAuthTypes.IUserDto loading: boolean - handleEditRole(params: Hooks.UseAuthTypes.IUserRole): Promise + updatingUsername: boolean roles: Hooks.UseAuthTypes.IRole[] | undefined loadingRoles: boolean permissions: Hooks.UseAuthTypes.IUserPermission | undefined + handleEditRole(params: Hooks.UseAuthTypes.IUserRole): Promise + handleUpdateUsername(id: number, name: string): Promise } export const ItemUser: React.FC = ({ user, loading, - handleEditRole, roles, loadingRoles, permissions, + updatingUsername, + handleEditRole, + handleUpdateUsername, }) => { - const { isOpen, onOpen, onClose } = useDisclosure() + const { + isOpen: isOpenChangeRole, + onOpen: onOpenChangeRole, + onClose: onCloseChangeRole, + } = useDisclosure() + const { + isOpen: isOpenUpdateUsername, + onOpen: onOpenUpdateUsername, + onClose: onCloseUpdateUsername, + } = useDisclosure() return ( <> + {user.id} @@ -43,7 +64,11 @@ export const ItemUser: React.FC = ({ {user.role} { - + } diff --git a/frontend/src/components/templates/team-members/modal-update-username/index.tsx b/frontend/src/components/templates/team-members/modal-update-username/index.tsx new file mode 100644 index 00000000..aa271946 --- /dev/null +++ b/frontend/src/components/templates/team-members/modal-update-username/index.tsx @@ -0,0 +1,99 @@ +import { + Alert, + AlertIcon, + Box, + Button, + Input, + Modal, + ModalBody, + ModalCloseButton, + ModalContent, + ModalHeader, + ModalOverlay, +} from '@chakra-ui/react' +import React, { useState } from 'react' +import { useForm } from 'react-hook-form' + +import { GAService } from 'utils/ga' + +interface IModalUpdateUsername { + isOpen: boolean + user: Hooks.UseAuthTypes.IUserDto + updatingUsername: boolean + onClose(): void + handleUpdateUsername(id: number, name: string): Promise +} + +export const ModalUpdateUsername: React.FC = ({ + isOpen, + user, + updatingUsername, + onClose, + handleUpdateUsername, +}) => { + const [errorSubmit, setErrorSubmit] = useState(null) + const [username, setUsername] = useState(user.name) + const { handleSubmit } = useForm() + + const onSubmit = async (): Promise => { + setErrorSubmit(null) + try { + const isSuccess = await handleUpdateUsername(user.id, username) + + if (isSuccess) { + GAService.GAEvent('username_updated') + onClose() + } + } catch (error) { + let message + if (error instanceof Error) message = error.message + else message = String(error) + setErrorSubmit(message) + } + } + + return ( + + + + Edit username + + + + {errorSubmit && ( + + + {errorSubmit} + + )} +
{ + onSubmit() + })} + > + { + setUsername(event.target.value) + }} + w="full" + /> + +
+
+
+
+
+ ) +} diff --git a/frontend/src/hooks/useAuth/context.tsx b/frontend/src/hooks/useAuth/context.tsx index 5cdaca05..0152fb3a 100644 --- a/frontend/src/hooks/useAuth/context.tsx +++ b/frontend/src/hooks/useAuth/context.tsx @@ -18,6 +18,7 @@ export const AuthProvider: React.FC = ({ children }) => { Authentication.getUser() ) const [loading, setLoading] = useState(false) + const [updatingUsername, setUpdatingUsername] = useState(false) const [loadingUserPermissions, setLoadingUserPermissions] = useState(true) const [updatingRolesPermissions, setUpdatingRolesPermissions] = useState(false) @@ -369,6 +370,25 @@ export const AuthProvider: React.FC = ({ children }) => { } } + const updateUsername = async (id: number, name: string): Promise => { + setUpdatingUsername(true) + try { + const response = await http.put(`users/${id}/update-name`, { name: name }) + if (response.status !== 200) { + throw new Error() + } + + return true + } catch (error) { + if (axios.isAxiosError(error) && error?.response?.status === 400) { + throw new Error(error.message) + } + throw new Error(MessagesError.errorOccurred) + } finally { + setUpdatingUsername(false) + } + } + const isAuthenticated = !!user return ( @@ -389,6 +409,7 @@ export const AuthProvider: React.FC = ({ children }) => { createRole, updateRole, deleteRole, + updateUsername, isAuthenticated, loading, loadingRoles, @@ -403,6 +424,7 @@ export const AuthProvider: React.FC = ({ children }) => { updatingRole, deletingRole, loadingUserPermissions, + updatingUsername, }} > {children} diff --git a/frontend/src/hooks/useAuth/use-auth-types.d.ts b/frontend/src/hooks/useAuth/use-auth-types.d.ts index 35717e90..1a3c723c 100644 --- a/frontend/src/hooks/useAuth/use-auth-types.d.ts +++ b/frontend/src/hooks/useAuth/use-auth-types.d.ts @@ -84,6 +84,7 @@ declare namespace Hooks { ) => Promise createRole: (userId: number, name: string) => Promise updateRole: (id: number, name: string) => Promise + updateUsername: (id: number, name: string) => Promise deleteRole: (id: number, idNewUsersRole: number) => Promise isAuthenticated: boolean loading: boolean @@ -99,6 +100,7 @@ declare namespace Hooks { updatingRole: boolean deletingRole: boolean loadingUserPermissions: boolean + updatingUsername: boolean } } }