From 4a8e5f8f8df32bcb534e7ad9be6302f9fb96d3b5 Mon Sep 17 00:00:00 2001 From: "@nishad.shirsat" <nishad.shirsat@ayanworks.com> Date: Thu, 3 Aug 2023 16:08:36 +0530 Subject: [PATCH 1/2] fix: Worked on the send invitation modal Signed-off-by: @nishad.shirsat <nishad.shirsat@ayanworks.com> --- src/app/NavBarStacked.astro | 2 +- src/components/AlertComponent/index.tsx | 19 ++++-- src/components/UserDashBoard.tsx | 16 +++-- src/components/organization/OrgDropDown.tsx | 27 +++++---- .../organization/OrganizationsList.tsx | 2 +- .../invitations/SendInvitationModal.tsx | 59 +++++++++--------- .../organization/users/EditUserRolesModal.tsx | 60 ++++++++++++++----- src/components/organization/users/Members.tsx | 2 +- 8 files changed, 114 insertions(+), 73 deletions(-) diff --git a/src/app/NavBarStacked.astro b/src/app/NavBarStacked.astro index 3eac74f88..a14e0bd53 100644 --- a/src/app/NavBarStacked.astro +++ b/src/app/NavBarStacked.astro @@ -8,7 +8,7 @@ import { asset, url } from '../lib/data.js'; <div class="container py-3 mx-auto"> <div class="flex items-center justify-between"> <div class="flex items-center justify-start"> - <a class="flex mr-4"> + <a class="flex mr-4" href='/'> <img src='/images/CREDEBL_ICON.png' class="h-8 mr-3" diff --git a/src/components/AlertComponent/index.tsx b/src/components/AlertComponent/index.tsx index de37c0fe8..89d2ef8b2 100644 --- a/src/components/AlertComponent/index.tsx +++ b/src/components/AlertComponent/index.tsx @@ -1,18 +1,27 @@ -import { Alert, Avatar, Spinner } from 'flowbite-react'; +import { Alert } from 'flowbite-react'; + +export const AlertComponent = ({ message, type, viewButton, onAlertClose }: { message: string | null, type: string, viewButton?: boolean, onAlertClose: () => void }) => { -export const AlertComponent = ({ message, type, onAlertClose }: { message: string | null, type: string, onAlertClose: () => void }) => { - return message !== null ? <Alert className='mb-4' color={type} onDismiss={() => onAlertClose()} > - <span> + <span className='flex flex-wrap justify-between items-center'> <p> {message} </p> + + { + viewButton + && <p className='md:w-32 lg:w-48 text-base text-primary-700 text-right'> + View more... + </p> + } + </span> + </Alert> - : <></> + : <></> } \ No newline at end of file diff --git a/src/components/UserDashBoard.tsx b/src/components/UserDashBoard.tsx index 41283923c..de375c623 100644 --- a/src/components/UserDashBoard.tsx +++ b/src/components/UserDashBoard.tsx @@ -1,12 +1,13 @@ -import type { AxiosResponse } from "axios"; import { useEffect, useState } from "react"; -import { getUserInvitations } from "../api/invitations"; -import { getOrganizations } from "../api/organization"; -import { apiStatusCodes } from "../config/CommonConstant"; -import { pathRoutes } from "../config/pathRoutes"; + import { AlertComponent } from "./AlertComponent"; -import type { Organisation } from "./organization/interfaces"; +import type { AxiosResponse } from "axios"; import CustomAvatar from '../components/Avatar' +import type { Organisation } from "./organization/interfaces"; +import { apiStatusCodes } from "../config/CommonConstant"; +import { getOrganizations } from "../api/organization"; +import { getUserInvitations } from "../api/invitations"; +import { pathRoutes } from "../config/pathRoutes"; const initialPageState = { pageNumber: 1, @@ -17,6 +18,7 @@ const initialPageState = { const UserDashBoard = () => { const [message, setMessage] = useState<string | null>(null) + const [viewButton, setViewButton] = useState<boolean>(false) const [error, setError] = useState<string | null>(null) const [currentPage, setCurrentPage] = useState(initialPageState); const [loading, setLoading] = useState<boolean>(false) @@ -37,6 +39,7 @@ const UserDashBoard = () => { if (invitationList.length > 0) { setMessage('You have some pending received invitations') + setViewButton(true) } setCurrentPage({ @@ -91,6 +94,7 @@ const UserDashBoard = () => { <AlertComponent message={message ? message : error} type={message ? 'warning' : 'failure'} + viewButton={viewButton} onAlertClose={() => { setMessage(null) setError(null) diff --git a/src/components/organization/OrgDropDown.tsx b/src/components/organization/OrgDropDown.tsx index fef10f797..ffa793fd9 100644 --- a/src/components/organization/OrgDropDown.tsx +++ b/src/components/organization/OrgDropDown.tsx @@ -12,8 +12,6 @@ import { pathRoutes } from '../../config/pathRoutes'; const OrgDropDown = () => { const [orgList, setOrgList] = useState<Organisation[]>([]); const [activeOrg, setactiveOrg] = useState<Organisation | null>(null) - - useEffect(() => { getAllorgs() @@ -36,31 +34,34 @@ const OrgDropDown = () => { }; const setActiveOrg = async (organizations: Organisation[]) => { - + let activeOrg: Organisation | null = null const orgId = await getFromLocalStorage(storageKeys.ORG_ID) if (orgId) { activeOrg = organizations?.find(org => org.id === Number(orgId)) as Organisation setactiveOrg(activeOrg || null) - await setToLocalStorage(storageKeys.ORG_ID, orgId.toString()); } else { activeOrg = organizations && organizations[0] setactiveOrg(activeOrg || null) - await setToLocalStorage(storageKeys.ORG_ID, activeOrg.id.toString()); } - const roles: string[] = activeOrg?.userOrgRoles.map(role => role.orgRole.name) - activeOrg.roles = roles + if (activeOrg) { + + await setToLocalStorage(storageKeys.ORG_ID, activeOrg.id.toString()); + const roles: string[] = activeOrg?.userOrgRoles.map(role => role.orgRole.name) + activeOrg.roles = roles + + await setToLocalStorage(storageKeys.ORG_ROLES, roles.toString()); + } - await setToLocalStorage(storageKeys.ORG_ROLES, roles.toString()); } const redirectToCreateOrgModal = () => { window.location.href = '/organizations?orgModal=true'; - + } return ( @@ -75,8 +76,8 @@ const OrgDropDown = () => { <> { - activeOrg ? - <> + activeOrg + ? <> {activeOrg.logoUrl ? ( <CustomAvatar size="20" src={activeOrg?.logoUrl} round /> ) : ( @@ -136,8 +137,8 @@ const OrgDropDown = () => { onClick={redirectToCreateOrgModal} > <svg xmlns="http://www.w3.org/2000/svg" className='pr-2 dark:text-white' width="24" height="24" fill="none" viewBox="0 0 24 24"> - <path fill="currentColor" d="M21.89 9.89h-7.78V2.11a2.11 2.11 0 1 0-4.22 0v7.78H2.11a2.11 2.11 0 1 0 0 4.22h7.78v7.78a2.11 2.11 0 1 0 4.22 0v-7.78h7.78a2.11 2.11 0 1 0 0-4.22Z"/> -</svg> + <path fill="currentColor" d="M21.89 9.89h-7.78V2.11a2.11 2.11 0 1 0-4.22 0v7.78H2.11a2.11 2.11 0 1 0 0 4.22h7.78v7.78a2.11 2.11 0 1 0 4.22 0v-7.78h7.78a2.11 2.11 0 1 0 0-4.22Z" /> + </svg> Create Organization diff --git a/src/components/organization/OrganizationsList.tsx b/src/components/organization/OrganizationsList.tsx index f2750cbdc..a625e8dc0 100644 --- a/src/components/organization/OrganizationsList.tsx +++ b/src/components/organization/OrganizationsList.tsx @@ -193,7 +193,7 @@ const OrganizationsList = () => { return ( <span key={index} - className="m-1 bg-primary-50 text-blue-800 text-sm font-medium mr-2 px-2.5 py-0.5 rounded dark:bg-blue-900 dark:text-primary-700" + className="m-1 bg-primary-50 text-blue-800 text-sm font-medium mr-2 px-2.5 py-0.5 rounded dark:bg-blue-900 dark:text-blue-300" > {role.charAt(0).toUpperCase() + role.slice(1)} </span> diff --git a/src/components/organization/invitations/SendInvitationModal.tsx b/src/components/organization/invitations/SendInvitationModal.tsx index 658ae0405..06bc94be0 100644 --- a/src/components/organization/invitations/SendInvitationModal.tsx +++ b/src/components/organization/invitations/SendInvitationModal.tsx @@ -22,12 +22,12 @@ interface Invitations { interface RoleI { - id: number - name: string + id: number + name: string } -const SendInvitationModal = (props: { openModal: boolean; setMessage: (message: string)=> void ; setOpenModal: (flag: boolean)=> void }) => { +const SendInvitationModal = (props: { openModal: boolean; setMessage: (message: string) => void; setOpenModal: (flag: boolean) => void }) => { const [loading, setLoading] = useState<boolean>(false) @@ -47,7 +47,7 @@ const SendInvitationModal = (props: { openModal: boolean; setMessage: (message: const { data } = resRoles as AxiosResponse if (data?.statusCode === apiStatusCodes.API_STATUS_SUCCESS) { - + const roles: Array<RoleI> = data?.data.response const memberRole = roles.find(role => role.name === 'member') @@ -89,7 +89,7 @@ const SendInvitationModal = (props: { openModal: boolean; setMessage: (message: const sendInvitations = async () => { - setLoading(true) + setLoading(true) const invitationPayload = invitations.map(invitation => { return { @@ -124,13 +124,13 @@ const SendInvitationModal = (props: { openModal: boolean; setMessage: (message: }> <Modal.Header>Send Invitations</Modal.Header> <Modal.Body> - <AlertComponent + <AlertComponent message={erroMsg} type={'error'} - onAlertClose = {() => { + onAlertClose={() => { setErrMsg(null) }} - /> + /> <Formik initialValues={initialInvitationData} validationSchema={ @@ -180,12 +180,11 @@ const SendInvitationModal = (props: { openModal: boolean; setMessage: (message: <div className="w-1/3"> <Button type="submit" - color="gray" - className='mt-6 float-right text-base font-medium text-center text-white bg-primary-700 rounded-lg hover:bg-primary-800 focus:ring-4 focus:ring-primary-300 sm:w-auto dark:bg-primary-700 dark:hover:bg-primary-700 dark:focus:ring-primary-800' - ><svg className="pr-2" xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="none" viewBox="0 0 24 24"> - <path fill="#fff" d="M21.89 9.89h-7.78V2.11a2.11 2.11 0 1 0-4.22 0v7.78H2.11a2.11 2.11 0 1 0 0 4.22h7.78v7.78a2.11 2.11 0 1 0 4.22 0v-7.78h7.78a2.11 2.11 0 1 0 0-4.22Z"/> - </svg> - + className='mt-6 text-base font-medium text-center text-white bg-primary-700 rounded-lg hover:bg-primary-800 focus:ring-4 focus:ring-primary-300 sm:w-auto dark:bg-primary-600 dark:hover:bg-primary-700 dark:focus:ring-primary-800' + ><svg className="pr-2" xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="none" viewBox="0 0 24 24"> + <path fill="#fff" d="M21.89 9.89h-7.78V2.11a2.11 2.11 0 1 0-4.22 0v7.78H2.11a2.11 2.11 0 1 0 0 4.22h7.78v7.78a2.11 2.11 0 1 0 4.22 0v-7.78h7.78a2.11 2.11 0 1 0 0-4.22Z" /> + </svg> + ADD </Button> </div> @@ -197,10 +196,10 @@ const SendInvitationModal = (props: { openModal: boolean; setMessage: (message: )} </Formik> - { - invitations.length > 0 && - <div> - <div + + <div> + { + invitations.length > 0 && <div className="p-2 my-2 bg-white border border-gray-200 rounded-lg shadow-sm 2xl:col-span-2 dark:border-gray-700 sm:p-2 dark:bg-gray-800" > <ul className="divide-y divide-gray-200 dark:divide-gray-700"> @@ -248,19 +247,19 @@ const SendInvitationModal = (props: { openModal: boolean; setMessage: (message: } </ul> </div> - <div className="mt-4 flex justify-end"> - <Button - onClick={sendInvitations} - isProcessing={loading} - className='text-base font-medium text-center text-white bg-primary-700 rounded-lg hover:bg-primary-800 focus:ring-4 focus:ring-primary-300 sm:w-auto dark:bg-primary-600 dark:hover:bg-primary-700 dark:focus:ring-primary-800"' - > - Send - </Button> - </div> + } + + <div className="mt-4 flex justify-end"> + <Button + onClick={sendInvitations} + disabled={invitations.length === 0} + isProcessing={loading} + className='text-base font-medium text-center text-white bg-primary-700 rounded-lg hover:bg-primary-800 focus:ring-4 focus:ring-primary-300 sm:w-auto dark:bg-primary-600 dark:hover:bg-primary-700 dark:focus:ring-primary-800"' + > + Send + </Button> </div> - - } - + </div> </Modal.Body> diff --git a/src/components/organization/users/EditUserRolesModal.tsx b/src/components/organization/users/EditUserRolesModal.tsx index 703803aab..31a6ce71a 100644 --- a/src/components/organization/users/EditUserRolesModal.tsx +++ b/src/components/organization/users/EditUserRolesModal.tsx @@ -11,6 +11,7 @@ interface RoleI { id: number name: string, checked: boolean + disabled: boolean } @@ -34,8 +35,13 @@ const EditUserRoleModal = (props: { openModal: boolean; user: User; setMessage: const filterRole = roles.filter(role => { if (props?.user?.roles.includes(role.name)) { role.checked = true + role.disabled = false + } else if (role.name === 'member') { + role.checked = true + role.disabled = true } else { role.checked = false + role.disabled = false } return !role.name.includes("owner") && !role.name.includes("holder"); }) @@ -54,9 +60,9 @@ const EditUserRoleModal = (props: { openModal: boolean; user: User; setMessage: const editUserRole = async () => { - setLoading(true) + setLoading(true) - const roleIds = roles?.filter(role => role.checked).map(role => role.id) + const roleIds = roles?.filter(role => role.checked).map(role => role.id) const response = await editOrganizationUserRole(props.user.id, roleIds as number[]) @@ -75,25 +81,47 @@ const EditUserRoleModal = (props: { openModal: boolean; user: User; setMessage: const onRoleChanged = (event: any, id: number) => { - if ( - (event?.target?.name === 'admin' && event?.target?.checked === true) - || (event?.target?.name === 'member' && event?.target?.checked === true) + if ( + (event?.target?.name === 'issuer' && event?.target?.checked === true) || (event?.target?.name === 'verifier' && event?.target?.checked === true) + ) { const updatesRoles: RoleI[] | null = roles && roles?.map(role => { if (role.id === id) { role.checked = event?.target?.checked - } else { + + } else if (role.name === 'verifier' && role.checked) { + role.checked = true + }else if (role.name === 'issuer' && role.checked) { + role.checked = true + }else if (role.name === 'member' && role.checked) { + role.checked = true + } + else { role.checked = false + } + return role + }) + setRoles(updatesRoles) + } else if ( + (event?.target?.name === 'admin' && event?.target?.checked === true) + ) { + const updatesRoles: RoleI[] | null = roles && roles?.map(role => { + if (role.id === id) { + role.checked = event?.target?.checked } + else if (role.name === 'member' && role.checked) { + role.checked = true + } + else { + role.checked = false + } return role }) setRoles(updatesRoles) } else { const updatesRoles: RoleI[] | null = roles && roles?.map(role => { - if(role.name === 'member' || role.name === 'admin'){ - role.checked = false - } else if (role.id === id) { + if (role.id === id) { role.checked = event?.target?.checked } return role @@ -106,8 +134,7 @@ const EditUserRoleModal = (props: { openModal: boolean; user: User; setMessage: return ( <Modal show={props.openModal} - size={"5xl"} - onClose={() => { + onClose={() => { props.setOpenModal(false); }} > @@ -117,10 +144,10 @@ const EditUserRoleModal = (props: { openModal: boolean; user: User; setMessage: <div className="mb-4 bg-white border border-gray-200 rounded-lg shadow-sm dark:border-gray-700 sm:p-6 dark:bg-gray-800" > - + <div className="space-y-6"> <div> - <div className="w-full"> + <div className="w-full"> <p className="text-base font-semibold text-gray-700 leading-none truncate mb-0.5 dark:text-white" @@ -152,10 +179,11 @@ const EditUserRoleModal = (props: { openModal: boolean; user: User; setMessage: <input type="checkbox" id={`checkbox-${role.id}`} name={role.name} + disabled={role.disabled} checked={role.checked} onChange={(event: any) => onRoleChanged(event, role.id)} /> - <span className="ml-3">{TextTittlecase(role.name)}</span> + <span className={`ml-3 ${role.disabled ? 'text-gray-500' : ''}`}>{TextTittlecase(role.name)}</span> </label> </div> )) @@ -164,11 +192,11 @@ const EditUserRoleModal = (props: { openModal: boolean; user: User; setMessage: } - </div> + </div> </div> - </div> + </div> </div> <div className="flex justify-end"> diff --git a/src/components/organization/users/Members.tsx b/src/components/organization/users/Members.tsx index 04e5decc6..8f9156e86 100644 --- a/src/components/organization/users/Members.tsx +++ b/src/components/organization/users/Members.tsx @@ -186,7 +186,7 @@ const Members = () => { </div> </div> - <span className='min-w-[35%] flex items-center justify-items-start'> + <span className='min-w-[35%] flex items-center justify-items-start text-gray-900 dark:text-white'> { user.email } From 87478b0a0352ce60435fc1b4e610b5919645a066 Mon Sep 17 00:00:00 2001 From: "@nishad.shirsat" <nishad.shirsat@ayanworks.com> Date: Thu, 3 Aug 2023 16:24:27 +0530 Subject: [PATCH 2/2] fix: dark theme text color change in empty state component Signed-off-by: @nishad.shirsat <nishad.shirsat@ayanworks.com> --- src/components/EmptyListComponent/index.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/EmptyListComponent/index.tsx b/src/components/EmptyListComponent/index.tsx index 77aa4e16a..037c5fb1f 100644 --- a/src/components/EmptyListComponent/index.tsx +++ b/src/components/EmptyListComponent/index.tsx @@ -1,4 +1,4 @@ -import { ReactElement } from "react"; +import type { ReactElement } from "react"; export const EmptyListMessage = ({ message, description, buttonContent, svgComponent, onClick } : { @@ -11,12 +11,12 @@ export const EmptyListMessage = ({ message, description, buttonContent, svgCompo }) => { return ( <div className='flex mt-20 justify-start items-center flex-col'> - <p className='text-2xl font-bold mb-4'>{message}</p> - <p className='text-lg mb-4'>{description}</p> + <p className='text-2xl font-bold mb-4 text-gray-900 dark:text-white'>{message}</p> + <p className='text-lg mb-4 text-gray-900 dark:text-white'>{description}</p> { buttonContent && <button - className='group flex h-min p-3 mt-10 items-center justify-center p-0.5 font-medium focus:z-10 border border-transparent enabled:hover:bg-cyan-800 dark:enabled:hover:bg-cyan-700 text-base font- text-center text-white bg-primary-700 rounded-lg hover:bg-accent-00 focus:ring-4 focus:ring-primary-300 sm:w-auto dark:bg-primary-600 dark:hover:bg-primary-700 dark:focus:ring-primary-800"' + className='group flex h-min p-3 mt-5 items-center justify-center p-0.5 font-medium focus:z-10 border border-transparent enabled:hover:bg-cyan-800 dark:enabled:hover:bg-cyan-700 text-base font- text-center text-white bg-primary-700 rounded-lg hover:bg-accent-00 focus:ring-4 focus:ring-primary-300 sm:w-auto dark:bg-primary-600 dark:hover:bg-primary-700 dark:focus:ring-primary-800"' onClick={onClick}> {svgComponent} <span className="ml-2">{buttonContent}</span>