diff --git a/src/assets/scss/_recordset-table.scss b/src/assets/scss/_recordset-table.scss
index 7c9038931..9c7a86047 100644
--- a/src/assets/scss/_recordset-table.scss
+++ b/src/assets/scss/_recordset-table.scss
@@ -253,3 +253,12 @@
margin-left: 5px;
}
}
+
+.chaise-table-top-scroll-wrapper {
+ position: sticky;
+ top: 0;
+}
+.no-scroll-bar {
+ display: none !important;
+ position: absolute !important;
+}
diff --git a/src/components/record/record-main-section.tsx b/src/components/record/record-main-section.tsx
index d871d98dd..0f9fb42d6 100644
--- a/src/components/record/record-main-section.tsx
+++ b/src/components/record/record-main-section.tsx
@@ -128,6 +128,7 @@ const RecordMainSection = (): JSX.Element => {
diff --git a/src/components/record/record.tsx b/src/components/record/record.tsx
index bf9414eb7..ae5fc58c3 100644
--- a/src/components/record/record.tsx
+++ b/src/components/record/record.tsx
@@ -684,6 +684,7 @@ const RecordInner = ({
diff --git a/src/components/record/related-table.tsx b/src/components/record/related-table.tsx
index fa1f4c9c3..36b0e3053 100644
--- a/src/components/record/related-table.tsx
+++ b/src/components/record/related-table.tsx
@@ -17,14 +17,12 @@ import { RecordRelatedModel } from '@isrd-isi-edu/chaise/src/models/record';
// providers
import RecordsetProvider from '@isrd-isi-edu/chaise/src/providers/recordset';
-// services
-import $log from '@isrd-isi-edu/chaise/src/services/logger';
-
// utils
import { CLASS_NAMES } from '@isrd-isi-edu/chaise/src/utils/constants';
-import { determineScrollElement, displayCustomModeRelated } from '@isrd-isi-edu/chaise/src/utils/record-utils';
+import { displayCustomModeRelated } from '@isrd-isi-edu/chaise/src/utils/record-utils';
import { makeSafeIdAttr } from '@isrd-isi-edu/chaise/src/utils/string-utils';
+
type RelatedTableProps = {
/**
* the related model that we want to represent
@@ -34,6 +32,10 @@ type RelatedTableProps = {
* the displayname for the reference to be used in the id attached to the container
*/
displaynameForID: string
+ /**
+ * Determines if both horizontal scrollbars should always be visible, or if only one should appear at a time.
+ */
+ showSingleScrollbar?: boolean,
};
/**
@@ -44,19 +46,21 @@ type RelatedTableProps = {
const RelatedTable = ({
relatedModel,
displaynameForID,
+ showSingleScrollbar
}: RelatedTableProps): JSX.Element => {
return (
-
+
)
}
const RelatedTableInner = ({
relatedModel,
- displaynameForID
+ displaynameForID,
+ showSingleScrollbar
}: RelatedTableProps) => {
const {
page, isInitialized, hasTimeoutError, isLoading,
@@ -111,6 +115,7 @@ const RelatedTableInner = ({
diff --git a/src/components/recordedit/recordedit.tsx b/src/components/recordedit/recordedit.tsx
index 0542c5a70..8bafbb89a 100644
--- a/src/components/recordedit/recordedit.tsx
+++ b/src/components/recordedit/recordedit.tsx
@@ -804,7 +804,9 @@ const RecordeditInner = ({
}
-
+ {/* Intersecting behaviour of scroll should be visible if there are multiple tables
+ on one page which here seems to be the case when there are successful as well as failed records */}
+
{resultsetProps.failed &&
@@ -815,7 +817,7 @@ const RecordeditInner = ({
exploreLink={resultsetProps.failed.exploreLink}
/>
-
+
}
diff --git a/src/components/recordedit/resultset-table.tsx b/src/components/recordedit/resultset-table.tsx
index be3a32330..512b6dbfd 100644
--- a/src/components/recordedit/resultset-table.tsx
+++ b/src/components/recordedit/resultset-table.tsx
@@ -4,7 +4,7 @@ import RecordsetTable from '@isrd-isi-edu/chaise/src/components/recordset/record
// models
import { RecordsetConfig } from '@isrd-isi-edu/chaise/src/models/recordset'
import { RecordsetDisplayMode, RecordsetSelectMode } from '@isrd-isi-edu/chaise/src/models/recordset';
-import { LogActions, LogReloadCauses, LogStackPaths, LogStackTypes } from '@isrd-isi-edu/chaise/src/models/log';
+import { LogStackPaths } from '@isrd-isi-edu/chaise/src/models/log';
// providers
import RecordsetProvider from '@isrd-isi-edu/chaise/src/providers/recordset';
@@ -13,11 +13,16 @@ import RecordsetProvider from '@isrd-isi-edu/chaise/src/providers/recordset';
import { LogService } from '@isrd-isi-edu/chaise/src/services/log';
type ResultsetTableProps = {
- page: any
+ page: any,
+ /**
+ * Determines if both horizontal scrollbars should always be visible, or if only one should appear at a time.
+ */
+ showSingleScrollbar: boolean,
}
const ResultsetTable = ({
page,
+ showSingleScrollbar,
}: ResultsetTableProps) : JSX.Element => {
const logStack = [LogService.getStackNode(LogStackPaths.SET, page.reference.table, page.reference.filterInfo)];
@@ -47,21 +52,23 @@ const ResultsetTable = ({
}}
initialPage={page}
>
-
+
)
}
const ResultsetTableInner = ({
reference,
- config
+ config,
+ showSingleScrollbar,
}: {
config: RecordsetConfig
reference: any
+ showSingleScrollbar: boolean,
}) : JSX.Element => {
return (
-
+
)
}
diff --git a/src/components/recordset/recordset-table.tsx b/src/components/recordset/recordset-table.tsx
index 44e7d595e..9f5174904 100644
--- a/src/components/recordset/recordset-table.tsx
+++ b/src/components/recordset/recordset-table.tsx
@@ -29,12 +29,17 @@ import { addTopHorizontalScroll, fireCustomEvent } from '@isrd-isi-edu/chaise/sr
type RecordsetTableProps = {
config: RecordsetConfig,
initialSortObject: any,
+ /**
+ * Determines if both horizontal scrollbars should always be visible, or if only one should appear at a time.
+ */
+ showSingleScrollbar?: boolean,
sortCallback?: (sortColumn: SortColumn) => any
}
const RecordsetTable = ({
config,
- initialSortObject
+ initialSortObject,
+ showSingleScrollbar = false
}: RecordsetTableProps): JSX.Element => {
const {
@@ -53,6 +58,9 @@ const RecordsetTable = ({
} = useRecordset();
const tableContainer = useRef(null);
+ const stickyScrollbarRef = useRef(null);
+ const tableEndRef = useRef(null);
+
const [currSortColumn, setCurrSortColumn] = useState(
Array.isArray(initialSortObject) ? initialSortObject[0] : null
@@ -90,7 +98,7 @@ const RecordsetTable = ({
isDisabled: false,
disabledType: undefined
};
- // page.tuples.forEach((tuple: any, index: number) => {
+ // page.tuples.forEach((tuple: any, index: number) => {
if (hasSelectedRows) {
const row = selectedRows.find((obj: SelectedRow) => {
// ermrestjs always returns a string for uniqueId, but internally we don't
@@ -115,12 +123,45 @@ const RecordsetTable = ({
}
tempRowDetails[i] = rowConfig;
- // });
+ // });
}
rowDetails = tempRowDetails;
}
+ useEffect(() => {
+ //Only implement intersection observer for top scrollbar when showSingleScrollbar is true otherwise top scrollbar will be shown as sticky
+ if (!showSingleScrollbar) return;
+
+ // Create a new IntersectionObserver instance to track the visibility of the bottom scrollbar(end of table)
+ const observer = new IntersectionObserver(
+ ([entry]) => {
+ //Updating isBottomVisible when bottom scrollbar is visible in the viewport
+ if (stickyScrollbarRef.current) {
+ if (entry.isIntersecting) {
+ stickyScrollbarRef.current.classList.add('no-scroll-bar');
+ }
+ else {
+ stickyScrollbarRef.current.classList.remove('no-scroll-bar');
+ }
+ }
+ },
+ {
+ root: null, // Use viewport as the root
+ threshold: 0.1, // Triggers when 10% of the element is visible
+ }
+ );
+ //Observes when the table end is visible on viewport
+ if (tableEndRef.current) {
+ observer.observe(tableEndRef.current);
+ }
+
+ return () => {
+ observer.disconnect();
+ }
+ }, []);
+
+
/**
* add the top horizontal scroll if needed
*/
@@ -472,10 +513,10 @@ const RecordsetTable = ({
const tableSchemaNames = `s_${makeSafeIdAttr(reference.table.schema.name)} t_${makeSafeIdAttr(reference.table.name)}`;
return classNameString + ' ' + tableSchemaNames;
}
-
return (
-
+
@@ -491,6 +532,10 @@ const RecordsetTable = ({
+ {/* This div will be used as the target (end of table) for the intersection observer to hide the
+ top scrollbar when the bottom one is visible */}
+