-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
import { FormattedMessage } from 'react-intl'; | ||
import { ProjectModal, ProjectsListTable, SkeletonTable } from '@/components'; | ||
Check failure on line 2 in src/renderer/components/blocks/tabs/UntokenizedUnitsTab.tsx GitHub Actions / Build Windows Installer
Check failure on line 2 in src/renderer/components/blocks/tabs/UntokenizedUnitsTab.tsx GitHub Actions / Build CADT UI Web App
Check failure on line 2 in src/renderer/components/blocks/tabs/UntokenizedUnitsTab.tsx GitHub Actions / Build Linux Installer
|
||
import React, { useCallback, useEffect } from 'react'; | ||
import { useGetProjectsQuery } from '@/api'; | ||
import { useColumnOrderHandler, useQueryParamState, useWildCardUrlHash } from '@/hooks'; | ||
import { debounce } from 'lodash'; | ||
|
||
interface PageTabProps { | ||
orgUid: string; | ||
search: string; | ||
order: string; | ||
setOrder: (order: string) => void; | ||
setIsLoading: (isLoading: boolean) => void; | ||
} | ||
|
||
const UntokenizedUnitsTab: React.FC<PageTabProps> = ({ | ||
orgUid, | ||
search, | ||
order, | ||
setOrder, | ||
setIsLoading, | ||
}: PageTabProps) => { | ||
const [currentPage, setCurrentPage] = useQueryParamState('page', '1'); | ||
const handleSetOrder = useColumnOrderHandler(order, setOrder); | ||
const [projectDetailsFragment, projectDetailsModalActive, setProjectModalActive] = useWildCardUrlHash('project'); | ||
const { | ||
data: projectsData, | ||
isLoading: projectsLoading, | ||
error: projectsError, | ||
} = useGetProjectsQuery({ page: Number(currentPage), orgUid, search, order }); | ||
|
||
useEffect(() => { | ||
setIsLoading(projectsLoading); | ||
}, [projectsLoading, setIsLoading]); | ||
|
||
const handlePageChange = useCallback( | ||
debounce((page) => setCurrentPage(page), 800), | ||
[setCurrentPage], | ||
); | ||
|
||
if (projectsLoading) { | ||
return <SkeletonTable />; | ||
} | ||
|
||
if (projectsError) { | ||
return <FormattedMessage id={'unable-to-load-contents'} />; | ||
} | ||
|
||
if (!projectsData) { | ||
return <FormattedMessage id={'no-records-found'} />; | ||
} | ||
|
||
return ( | ||
<> | ||
{projectsLoading ? ( | ||
<SkeletonTable /> | ||
) : ( | ||
<ProjectsListTable | ||
data={projectsData?.data || []} | ||
rowActions="edit" | ||
isLoading={projectsLoading} | ||
currentPage={Number(currentPage)} | ||
onPageChange={handlePageChange} | ||
onRowClick={(row) => setProjectModalActive(true, row.warehouseProjectId)} | ||
setOrder={handleSetOrder} | ||
order={order} | ||
totalPages={projectsData.pageCount} | ||
totalCount={projectsData.pageCount < 10 ? projectsData.data.length : projectsData.pageCount * 10} | ||
/> | ||
)} | ||
{projectDetailsModalActive && ( | ||
<ProjectModal | ||
onClose={() => setProjectModalActive(false)} | ||
warehouseProjectId={projectDetailsFragment.replace('project-', '')} | ||
/> | ||
)} | ||
</> | ||
); | ||
}; | ||
|
||
export { UntokenizedUnitsTab }; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
export {}; | ||
export * from './UntokenizedUnitsTab'; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import { TextInput } from '@/components'; | ||
import { IoSearchSharp } from 'react-icons/io5'; | ||
import React from 'react'; | ||
import { IntlShape, useIntl } from 'react-intl'; | ||
|
||
interface SearchBoxProps { | ||
defaultValue: string; | ||
onChange: (event: any) => void; | ||
} | ||
|
||
const SearchBox: React.FC<SearchBoxProps> = ({ defaultValue, onChange }) => { | ||
const intl: IntlShape = useIntl(); | ||
|
||
return ( | ||
<div className="flex justify-center items-center w-full md:max-w-md"> | ||
<TextInput | ||
type="text" | ||
icon={IoSearchSharp} | ||
defaultValue={defaultValue || ''} | ||
onChange={onChange} | ||
placeholder={intl.formatMessage({ id: 'search' })} | ||
className="w-full" | ||
/> | ||
</div> | ||
); | ||
}; | ||
|
||
export { SearchBox }; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
export * from './ThemeModeSelector'; | ||
export * from './SearchBox'; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,69 +1,157 @@ | ||
import React, { useCallback } from 'react'; | ||
import { useGetProjectsQuery } from '@/api'; | ||
import { useColumnOrderHandler, useQueryParamState, useWildCardUrlHash } from '@/hooks'; | ||
import React, { useCallback, useEffect, useMemo, useState } from 'react'; | ||
import { useQueryParamState, useUrlHash } from '@/hooks'; | ||
import { debounce } from 'lodash'; | ||
import { IndeterminateProgressOverlay, ProjectsListTable, SampleDeepLinkedModal, SkeletonTable } from '@/components'; | ||
import { | ||
Button, | ||
UntokenizedUnitsTab, | ||
ComponentCenteredSpinner, | ||
IndeterminateProgressOverlay, | ||
SearchBox, | ||
Tabs, | ||
} from '@/components'; | ||
import { FormattedMessage } from 'react-intl'; | ||
import { Organization } from '@/schemas/Organization.schema'; | ||
import { useNavigate } from 'react-router-dom'; | ||
import { useGetOrganizationsListQuery } from '@/api'; | ||
Check failure on line 15 in src/renderer/pages/ListPageSample.tsx GitHub Actions / Build Windows Installer
Check failure on line 15 in src/renderer/pages/ListPageSample.tsx GitHub Actions / Build CADT UI Web App
Check failure on line 15 in src/renderer/pages/ListPageSample.tsx GitHub Actions / Build Linux Installer
|
||
// @ts-ignore | ||
import { useGetStagedProjectsQuery } from '@/api/cadt/v1/staging'; | ||
|
||
const ListPageSample: React.FC = () => { | ||
const [currentPage, setCurrentPage] = useQueryParamState('page', '1'); | ||
const [orgUid /* set func here */] = useQueryParamState('orgUid', undefined); | ||
const [search /* set func here */] = useQueryParamState('search', undefined); | ||
const [order, setOrder] = useQueryParamState('order', undefined); | ||
const handleSetOrder = useColumnOrderHandler(order, setOrder); | ||
const [projectDetailsFragment, projectDetailsModalActive, setProjectModalActive] = useWildCardUrlHash('project'); | ||
enum TabTypes { | ||
TOKENIZED, | ||
UNTOKENIZED, | ||
} | ||
|
||
const { | ||
data: projectsData, | ||
isLoading: projectsLoading, | ||
isFetching: projectsFetching, | ||
error: projectsError, | ||
} = useGetProjectsQuery({ page: Number(currentPage), orgUid, search, order }); | ||
interface ProcessedStagingData { | ||
staged: any[]; | ||
pending: any[]; | ||
failed: any[]; | ||
transfer: any; | ||
} | ||
|
||
const handlePageChange = useCallback( | ||
debounce((page) => setCurrentPage(page), 800), | ||
[setCurrentPage], | ||
const MyProjectsPage: React.FC = () => { | ||
const navigate = useNavigate(); | ||
const [orgUid, setOrgUid] = useQueryParamState('orgUid', undefined); | ||
const [search, setSearch] = useQueryParamState('search', undefined); | ||
const [order, setOrder] = useQueryParamState('order', undefined); | ||
// eslint-disable-next-line @typescript-eslint/no-unused-vars | ||
const [projectStagedSuccess, setProjectStagedSuccess] = useUrlHash('success-stage-project'); | ||
Check failure on line 37 in src/renderer/pages/ListPageSample.tsx GitHub Actions / Build Windows Installer
Check failure on line 37 in src/renderer/pages/ListPageSample.tsx GitHub Actions / Build Windows Installer
Check failure on line 37 in src/renderer/pages/ListPageSample.tsx GitHub Actions / Build CADT UI Web App
Check failure on line 37 in src/renderer/pages/ListPageSample.tsx GitHub Actions / Build CADT UI Web App
Check failure on line 37 in src/renderer/pages/ListPageSample.tsx GitHub Actions / Build Linux Installer
Check failure on line 37 in src/renderer/pages/ListPageSample.tsx GitHub Actions / Build Linux Installer
Check failure on line 37 in src/renderer/pages/ListPageSample.tsx GitHub Actions / Build Mac Installer
|
||
// eslint-disable-next-line @typescript-eslint/no-unused-vars | ||
const [commitModalActive, setCommitModalActive] = useUrlHash('commit-staged-items'); | ||
Check failure on line 39 in src/renderer/pages/ListPageSample.tsx GitHub Actions / Build Windows Installer
Check failure on line 39 in src/renderer/pages/ListPageSample.tsx GitHub Actions / Build CADT UI Web App
Check failure on line 39 in src/renderer/pages/ListPageSample.tsx GitHub Actions / Build Linux Installer
|
||
const [, setCreateProjectModalActive] = useUrlHash('create-project'); | ||
const [activeTab, setActiveTab] = useState<TabTypes>(TabTypes.UNTOKENIZED); | ||
const [committedDataLoading, setCommittedDataLoading] = useState<boolean>(false); | ||
const { data: unprocessedStagedProjects, isLoading: stagingDataLoading } = useGetStagedProjectsQuery(); | ||
const { data: organizationsListData, isLoading: organizationsListLoading } = useGetOrganizationsListQuery(); | ||
const myOrganization = useMemo<Organization | undefined>( | ||
() => organizationsListData?.find((org: Organization) => org.isHome), | ||
[organizationsListData], | ||
); | ||
|
||
if (projectsLoading) { | ||
return <SkeletonTable />; | ||
} | ||
const processedStagingData: ProcessedStagingData = useMemo<ProcessedStagingData>(() => { | ||
const data: ProcessedStagingData = { staged: [], pending: [], failed: [], transfer: undefined }; | ||
if (unprocessedStagedProjects?.forEach) { | ||
unprocessedStagedProjects.forEach((stagedProject: any) => { | ||
if (stagedProject?.table === 'Projects') { | ||
if (!stagedProject.commited && !stagedProject.failedCommit && !stagedProject.isTransfer) { | ||
data.staged.push(stagedProject); | ||
} else if (stagedProject.commited && !stagedProject.failedCommit && !stagedProject.isTransfer) { | ||
data.pending.push(stagedProject); | ||
} else if (!stagedProject.commited && stagedProject.failedCommit && !stagedProject.isTransfer) { | ||
data.failed.push(stagedProject); | ||
} else if (stagedProject.commited && stagedProject.isTransfer) { | ||
data.transfer = stagedProject; | ||
} | ||
} | ||
}); | ||
} | ||
return data; | ||
}, [unprocessedStagedProjects]); | ||
|
||
if (projectsError) { | ||
return <FormattedMessage id={'unable-to-load-contents'} />; | ||
} | ||
const contentsLoading = useMemo<boolean>(() => { | ||
return committedDataLoading || stagingDataLoading; | ||
}, [committedDataLoading, stagingDataLoading]); | ||
|
||
useEffect(() => { | ||
if (myOrganization) { | ||
setOrgUid(myOrganization.orgUid); | ||
} | ||
}, [myOrganization, myOrganization?.orgUid, organizationsListData, setOrgUid]); | ||
|
||
useEffect(() => { | ||
if (!myOrganization && !organizationsListLoading) { | ||
navigate('/'); | ||
} | ||
}, [myOrganization, navigate, organizationsListLoading]); | ||
|
||
const handleSearchChange = useCallback( | ||
debounce((event: any) => { | ||
setSearch(event.target.value); | ||
}, 800), | ||
[setSearch, debounce], | ||
); | ||
|
||
if (!projectsData) { | ||
return <FormattedMessage id={'no-records-found'} />; | ||
if (!myOrganization || organizationsListLoading) { | ||
return <ComponentCenteredSpinner />; | ||
} | ||
|
||
return ( | ||
<> | ||
{projectsFetching && <IndeterminateProgressOverlay />} | ||
{projectsLoading ? ( | ||
<SkeletonTable /> | ||
) : ( | ||
<ProjectsListTable | ||
data={projectsData?.data || []} | ||
rowActions="transfer" | ||
isLoading={projectsLoading} | ||
currentPage={Number(currentPage)} | ||
onPageChange={handlePageChange} | ||
onRowClick={(row) => setProjectModalActive(true, row.warehouseProjectId)} | ||
setOrder={handleSetOrder} | ||
order={order} | ||
totalPages={projectsData.pageCount} | ||
totalCount={projectsData.pageCount < 10 ? projectsData.data.length : projectsData.pageCount * 10} | ||
/> | ||
)} | ||
{projectDetailsModalActive && ( | ||
<SampleDeepLinkedModal | ||
onClose={() => setProjectModalActive(false)} | ||
urlFragmentDerivedData={projectDetailsFragment.replace('project-', '')} | ||
/> | ||
)} | ||
<div className="pt-2 pl-2 pr-2 h-full"> | ||
{contentsLoading && <IndeterminateProgressOverlay />} | ||
<div className="flex flex-col md:flex-row gap-6 my-2.5 relative z-30 items-center h-auto"> | ||
{activeTab === TabTypes.UNTOKENIZED && ( | ||
<> | ||
<Button disabled={contentsLoading} onClick={() => setCreateProjectModalActive(true)}> | ||
<FormattedMessage id="create-project" /> | ||
</Button> | ||
<SearchBox defaultValue={search} onChange={handleSearchChange} /> | ||
</> | ||
)} | ||
{activeTab === TabTypes.TOKENIZED && ( | ||
<> | ||
<Button | ||
disabled={contentsLoading || !processedStagingData.staged.length} | ||
onClick={() => setCommitModalActive(true)} | ||
> | ||
<FormattedMessage id="commit" /> | ||
</Button> | ||
</> | ||
)} | ||
</div> | ||
<div className="h-13"> | ||
<Tabs onActiveTabChange={(tab: TabTypes) => setActiveTab(tab)}> | ||
<Tabs.Item | ||
title={ | ||
<p className="capitalize"> | ||
<FormattedMessage id="untokenized-units" /> | ||
</p> | ||
} | ||
/> | ||
<Tabs.Item | ||
title={ | ||
<p className="capitalize"> | ||
<FormattedMessage id="tokenized-units" /> | ||
{' (' + String(processedStagingData.staged.length + ') ')} | ||
</p> | ||
} | ||
/> | ||
</Tabs> | ||
</div> | ||
<div id="tabs content"> | ||
{activeTab === TabTypes.UNTOKENIZED && ( | ||
<UntokenizedUnitsTab | ||
orgUid={orgUid} | ||
search={search} | ||
order={order} | ||
setOrder={setOrder} | ||
setIsLoading={setCommittedDataLoading} | ||
/> | ||
)} | ||
{activeTab === TabTypes.TOKENIZED && <div>TODO: tokenized units tab</div>} | ||
</div> | ||
</div> | ||
</> | ||
); | ||
}; | ||
|
||
export { ListPageSample }; | ||
export { MyProjectsPage }; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
export default { | ||
PROJECTS_LIST: '/projects', | ||
CREATE_TOKENS: '/create-tokens', | ||
REVERT_TOKENS: '/revert-tokens', | ||
}; |