diff --git a/ui/app/mirrors/edit/[mirrorId]/cdc.tsx b/ui/app/mirrors/edit/[mirrorId]/cdc.tsx
index caa5226663..d70ba3b4fa 100644
--- a/ui/app/mirrors/edit/[mirrorId]/cdc.tsx
+++ b/ui/app/mirrors/edit/[mirrorId]/cdc.tsx
@@ -14,8 +14,8 @@ import { SearchField } from '@/lib/SearchField';
import { Table, TableCell, TableRow } from '@/lib/Table';
import * as Tabs from '@radix-ui/react-tabs';
import moment, { Duration, Moment } from 'moment';
+import { useQueryState } from 'next-usequerystate';
import Link from 'next/link';
-import { useState } from 'react';
import styled from 'styled-components';
import CDCDetails from './cdcDetails';
@@ -150,7 +150,9 @@ const SnapshotStatusTable = ({ status }: SnapshotStatusProps) => (
{clone.completedNumRows}
-
+
))}
@@ -175,7 +177,10 @@ type CDCMirrorStatusProps = {
syncStatusChild?: React.ReactNode;
};
export function CDCMirror({ cdc, syncStatusChild }: CDCMirrorStatusProps) {
- const [selectedTab, setSelectedTab] = useState('tab1');
+ const [selectedTab, setSelectedTab] = useQueryState('tab', {
+ history: 'push',
+ defaultValue: 'tab1',
+ });
let snapshot = <>>;
if (cdc.snapshotStatus) {
diff --git a/ui/app/mirrors/edit/[mirrorId]/syncStatusTable.tsx b/ui/app/mirrors/edit/[mirrorId]/syncStatusTable.tsx
index 64c319a4f9..06abcc67ce 100644
--- a/ui/app/mirrors/edit/[mirrorId]/syncStatusTable.tsx
+++ b/ui/app/mirrors/edit/[mirrorId]/syncStatusTable.tsx
@@ -32,7 +32,7 @@ function TimeWithDurationOrRunning({
return (
);
} else {
diff --git a/ui/app/mirrors/status/qrep/[mirrorId]/qrepStatusTable.tsx b/ui/app/mirrors/status/qrep/[mirrorId]/qrepStatusTable.tsx
index 55ee7d5819..c50c145de1 100644
--- a/ui/app/mirrors/status/qrep/[mirrorId]/qrepStatusTable.tsx
+++ b/ui/app/mirrors/status/qrep/[mirrorId]/qrepStatusTable.tsx
@@ -35,6 +35,13 @@ function RowPerPartition({
endTime,
numRows,
}: QRepPartitionStatus) {
+ let duration = 'N/A';
+ if (startTime && endTime) {
+ duration = moment
+ .duration(moment(endTime).diff(moment(startTime)))
+ .humanize({ ss: 1 });
+ }
+
return (
@@ -46,6 +53,9 @@ function RowPerPartition({
+
+
+
@@ -132,6 +142,7 @@ export default function QRepStatusTable({
Partition UUID
Run UUID
+ Duration
Start Time
End Time
Num Rows Synced
diff --git a/ui/package.json b/ui/package.json
index c22337cf24..1e8741fe25 100644
--- a/ui/package.json
+++ b/ui/package.json
@@ -41,6 +41,7 @@
"material-symbols": "0.11.0",
"moment": "^2.29.4",
"next": "13.5.5",
+ "next-usequerystate": "^1.8.4",
"prop-types": "^15.8.1",
"protobufjs": "^7.2.5",
"react": "18.2.0",
diff --git a/ui/yarn.lock b/ui/yarn.lock
index e7347d113c..2ad970d16d 100644
--- a/ui/yarn.lock
+++ b/ui/yarn.lock
@@ -8014,6 +8014,11 @@ minizlib@^2.1.1:
minipass "^3.0.0"
yallist "^4.0.0"
+mitt@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/mitt/-/mitt-3.0.1.tgz#ea36cf0cc30403601ae074c8f77b7092cdab36d1"
+ integrity sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==
+
mkdirp-classic@^0.5.2:
version "0.5.3"
resolved "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz"
@@ -8094,6 +8099,13 @@ neo-async@^2.5.0, neo-async@^2.6.1, neo-async@^2.6.2:
resolved "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz"
integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==
+next-usequerystate@^1.8.4:
+ version "1.8.4"
+ resolved "https://registry.yarnpkg.com/next-usequerystate/-/next-usequerystate-1.8.4.tgz#81125aa3dd5a0c6afbc21da8c1f663ee2e0a0350"
+ integrity sha512-V4xMh87cu950Zy1Jpw/H8GwWxAeAmqnLNJ8hAl5bdEWpyZV4UIKdkJePKMCUy1+h254EXGmY83BuCGJOASJRVg==
+ dependencies:
+ mitt "^3.0.1"
+
next@13.5.5:
version "13.5.5"
resolved "https://registry.yarnpkg.com/next/-/next-13.5.5.tgz#65addd98a1ae42845d455e08bc491448bb34929b"