Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 14 additions & 4 deletions ui/src/components/ContentMapper/assetMapper.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Libraries
import { useEffect, useState } from 'react';
import { useEffect, useRef, useState } from 'react';
import { useSelector } from 'react-redux';
import { useParams } from 'react-router-dom';
import {
Expand Down Expand Up @@ -37,6 +37,9 @@ import {
computeChangedUids,
} from './assetMapper.utils';

// Hooks
import { useMeasuredTableHeight } from './useMeasuredTableHeight';

// Styles and Assets
import './index.scss';

Expand Down Expand Up @@ -64,10 +67,18 @@ const AssetMapper = ({
// stranded on the full-page empty state with no way to clear the search.
const [searchText, setSearchText] = useState<string>('');

const tableWrapperRef = useRef<HTMLDivElement | null>(null);

useEffect(() => {
fetchAssets('', { seedSelection: true });
}, []);

// Responsive table height for the asset mapper β€” see useMeasuredTableHeight for the why.
const tableHeight = useMeasuredTableHeight(tableWrapperRef, [tableData?.length], {
panelSelector: '.TablePanel',
footerSelector: '.mapper-footer',
});

// Single server-paginated fetch (same pattern as entryMapper's fetchEntries). The
// Venus table drives paging by calling fetchData with { skip, limit, searchText };
// we ask the API for just that page and use the returned `count` as the grand total.
Expand Down Expand Up @@ -277,10 +288,9 @@ const AssetMapper = ({
version="v2"
testId="no-results-found-page"
/> :
<div>
<div className="asset-mapper-table" ref={tableWrapperRef}>
<InfiniteScrollTable
key={'asset-mapper-table'}
className={'asset-mapper-table'}
loading={loading}
canSearch={true}
totalCounts={Math.max(0, totalCounts)}
Expand All @@ -290,7 +300,7 @@ const AssetMapper = ({
isRowSelect={true}
fullRowSelect={true}
fetchTableData={fetchData}
tableHeight={400}
tableHeight={tableHeight}
equalWidthColumns={false}
columnSelector={false}
v2Features={{ pagination: true, isNewEmptyState: true }}
Expand Down
167 changes: 86 additions & 81 deletions ui/src/components/ContentMapper/entryMapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ import {
applyContentTypeStatus,
} from './entryMapper.utils';
import { toSelectedMap, computeChangedUids } from './assetMapper.utils';
import { useMeasuredTableHeight } from './useMeasuredTableHeight';

// Styles and Assets
import './index.scss';
Expand Down Expand Up @@ -477,13 +478,14 @@ const EntryMapper = ({ handleStepChange }: entryMapperProps) => {
),
accessor: accessorCall,
id: 'uuid',
width: '250px',
width: '340px',
},
{
disableSortBy: true,
Header: <span>{`${newMigrationData?.legacy_cms?.selectedCms?.title} UIDs:`}</span>,
accessor: accessorForCMSUid,
id: '1'
id: '1',
width: '360px',
},
{
disableSortBy: true,
Expand All @@ -493,11 +495,11 @@ const EntryMapper = ({ handleStepChange }: entryMapperProps) => {
}
];

// Must match the .Table__body height in index.scss so the react-window list is exactly
// as tall as the scroll body. Leave ~140px below for the search row, pagination bar and
// Save footer; the body scrolls internally so all rows of a page stay reachable.
const calcHeight = () => window.innerHeight - 520;
const tableHeight = calcHeight();
// Responsive table height for the entry mapper β€” see useMeasuredTableHeight for the why.
const tableHeight = useMeasuredTableHeight(tableWrapperRef, [contentTypeUid, tableData?.length], {
panelSelector: '.TablePanel',
footerSelector: '.mapper-footer',
});

return (
isLoading || newMigrationData?.isprojectMapped
Expand Down Expand Up @@ -619,82 +621,85 @@ const EntryMapper = ({ handleStepChange }: entryMapperProps) => {

{/* Entry Mapping Table */}
<div className="content-types-fields-wrapper">
<div className="table-wrapper" ref={tableWrapperRef}>
<div className={`entry-mapper-container${localeOptions?.length > 0 ? ' has-locale-select' : ''}`}>
{localeOptions?.length > 0 && (
<div className="locale-select-inline">
<Select
className="locale-select"
value={selectedLocale}
options={localeOptions}
onChange={(opt: { label: string; value: string }) => setSelectedLocale(opt)}
isSearchable={false}
isClearable={false}
placeholder="Select locale"
width="240px"
version="v2"
/>
</div>
)}
<div
className={`entry-table-wrapper entry-mapper-container${localeOptions?.length > 0 ? ' has-locale-select' : ''}`}
ref={tableWrapperRef}
>
{localeOptions?.length > 0 && (
<div className="locale-select-inline">
<Select
className="locale-select"
value={selectedLocale}
options={localeOptions}
onChange={(opt: { label: string; value: string }) => setSelectedLocale(opt)}
isSearchable={false}
isClearable={false}
placeholder="Select locale"
width="240px"
version="v2"
/>
</div>
)}
<div className="entry-mapper-table">
<InfiniteScrollTable
key={contentTypeUid || 'entry-mapper-table'}
loading={loading}
canSearch={true}
totalCounts={totalCounts ?? 0}
data={[...tableData]}
columns={columns}
uniqueKey={'id'}
isRowSelect={true}
fullRowSelect={true}
fetchTableData={fetchData}
tableHeight={tableHeight}
equalWidthColumns={true}
columnSelector={false}
v2Features={{ pagination: true, isNewEmptyState: true }}
rowPerPageOptions={[10, 30, 50, 100]}
minBatchSizeToFetch={30}
initialRowSelectedData={initialRowSelectedData}
initialSelectedRowIds={rowIds}
itemSize={70}
getSelectedRow={handleSelectedEntries}
rowSelectCheckboxProp={{ key: '_canSelect', value: true }}
name={{
singular: '',
plural: `${totalCounts === 0 ? 'Count' : ''}`
}}
customEmptyState={
<EmptyState
forPage="list"
heading={MAPPER_SEARCH_EMPTY_STATE.NO_MATCH_HEADING}
description={MAPPER_SEARCH_EMPTY_STATE.NO_MATCH_DESCRIPTION}
moduleIcon={MAPPER_SEARCH_EMPTY_STATE.NO_MATCH_ICON}
type="secondary"
className="custom-empty-state"
/>
}
/>
{(totalCounts > 0 || (tableData?.length ?? 0) > 0) && (
<div className="mapper-footer">
<div>
{/* Total Entries: <strong>{totalCounts}</strong> */}
</div>
<Button
className="saveButton"
onClick={handleSaveContentType}
version="v2"
// Lock the Save button only while a migration is actively in flight.
// Using migrationStarted alone would permanently lock revisits on delta
// iterations since migrationStarted stays true after completion.
disabled={
!!newMigrationData?.migration_execution?.migrationStarted &&
!newMigrationData?.migration_execution?.migrationCompleted
}
isLoading={isLoadingSaveButton}
>
Save
</Button>
key={contentTypeUid || 'entry-mapper-table'}
loading={loading}
canSearch={true}
totalCounts={totalCounts ?? 0}
data={[...tableData]}
columns={columns}
uniqueKey={'id'}
isRowSelect={true}
fullRowSelect={true}
fetchTableData={fetchData}
tableHeight={tableHeight}
equalWidthColumns={false}
Comment thread
yashin4112 marked this conversation as resolved.
Comment thread
yashin4112 marked this conversation as resolved.
columnSelector={false}
v2Features={{ pagination: true, isNewEmptyState: true }}
rowPerPageOptions={[10, 30, 50, 100]}
minBatchSizeToFetch={30}
initialRowSelectedData={initialRowSelectedData}
initialSelectedRowIds={rowIds}
itemSize={70}
getSelectedRow={handleSelectedEntries}
rowSelectCheckboxProp={{ key: '_canSelect', value: true }}
name={{
singular: '',
plural: `${totalCounts === 0 ? 'Count' : ''}`
}}
customEmptyState={
<EmptyState
forPage="list"
heading={MAPPER_SEARCH_EMPTY_STATE.NO_MATCH_HEADING}
description={MAPPER_SEARCH_EMPTY_STATE.NO_MATCH_DESCRIPTION}
moduleIcon={MAPPER_SEARCH_EMPTY_STATE.NO_MATCH_ICON}
type="secondary"
className="custom-empty-state"
/>
}
/>
{(totalCounts > 0 || (tableData?.length ?? 0) > 0) && (
<div className="mapper-footer">
<div>
{/* Total Entries: <strong>{totalCounts}</strong> */}
</div>
)}
<Button
className="saveButton"
onClick={handleSaveContentType}
version="v2"
// Lock the Save button only while a migration is actively in flight.
// Using migrationStarted alone would permanently lock revisits on delta
// iterations since migrationStarted stays true after completion.
disabled={
!!newMigrationData?.migration_execution?.migrationStarted &&
!newMigrationData?.migration_execution?.migrationCompleted
}
isLoading={isLoadingSaveButton}
>
Save
</Button>
</div>
)}
</div>
</div>
</div>
Expand Down
Loading
Loading