Skip to content

Commit

Permalink
feat: Add refresh compatibility to workflow screen (all tabs)
Browse files Browse the repository at this point in the history
Signed-off-by: Noble Mittal <[email protected]>
  • Loading branch information
beingnoble03 committed Sep 30, 2024
1 parent 5e9c69c commit 23e5cc0
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 26 deletions.
4 changes: 3 additions & 1 deletion web/vtadmin/src/components/inputs/Select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ interface Props<T> {
size?: 'large';
description?: string;
required?: boolean;
disableClearSelection?: boolean;
}

/**
Expand All @@ -60,6 +61,7 @@ export const Select = <T,>({
size,
description,
required,
disableClearSelection,
}: Props<T>) => {
const _itemToString = React.useCallback(
(item: T | null): string => {
Expand Down Expand Up @@ -146,7 +148,7 @@ export const Select = <T,>({
</button>
<div className={style.dropdown} hidden={!isOpen}>
{content}
{selectedItem && (
{selectedItem && !disableClearSelection && (
<button className={style.clear} onClick={() => selectItem(null as any)} type="button">
Clear selection
</button>
Expand Down
80 changes: 63 additions & 17 deletions web/vtadmin/src/components/routes/workflow/Workflow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Link, Redirect, Route, Switch, useLocation, useParams, useRouteMatch } from 'react-router-dom';
import { Link, Redirect, Route, Switch, useParams, useRouteMatch } from 'react-router-dom';
import { useState } from 'react';

import style from './Workflow.module.scss';

Expand All @@ -31,25 +32,48 @@ import { Tab } from '../../tabs/Tab';
import { getStreams } from '../../../util/workflows';
import { Code } from '../../Code';
import { ShardLink } from '../../links/ShardLink';
import { Select } from '../../inputs/Select';
import { formatDateTimeShort } from '../../../util/time';

interface RouteParams {
clusterID: string;
keyspace: string;
name: string;
}

const REFETCH_OPTIONS = [
{
displayText: '10s',
interval: 10 * 1000,
},
{
displayText: '30s',
interval: 30 * 1000,
},
{
displayText: '1m',
interval: 60 * 1000,
},
{
displayText: '10m',
interval: 600 * 1000,
},
{
displayText: 'Never',
interval: 0,
},
];

export const Workflow = () => {
const { clusterID, keyspace, name } = useParams<RouteParams>();
const { path, url } = useRouteMatch();
const location = useLocation();

useDocumentTitle(`${name} (${keyspace})`);

const { data } = useWorkflow({ clusterID, keyspace, name });
const streams = getStreams(data);
const [refetchInterval, setRefetchInterval] = useState(60 * 1000);

const detailsURL = `${url}/details`;
const detailsTab = location.pathname === detailsURL;
const { data, ...workflowQuery } = useWorkflow({ clusterID, keyspace, name }, { refetchInterval });
const streams = getStreams(data);

let isReshard = false;
if (data && data.workflow) {
Expand All @@ -59,11 +83,33 @@ export const Workflow = () => {
return (
<div>
<WorkspaceHeader>
<NavCrumbs>
<Link to="/workflows">Workflows</Link>
</NavCrumbs>
<div className="w-full flex flex-row justify-between">
<div>
<NavCrumbs>
<Link to="/workflows">Workflows</Link>
</NavCrumbs>
<WorkspaceTitle className="font-mono">{name}</WorkspaceTitle>
</div>

<WorkspaceTitle className="font-mono">{name}</WorkspaceTitle>
<div className="float-right">
<Select
className="block w-full"
inputClassName="block w-full"
itemToString={(option) => option?.displayText || ''}
items={REFETCH_OPTIONS}
label="Refresh Interval"
onChange={(option) => setRefetchInterval(option?.interval || 0)}
renderItem={(option) => option?.displayText || ''}
placeholder={'Select Interval'}
helpText={'Automatically refreshes workflow status after selected intervals'}
selectedItem={REFETCH_OPTIONS.find((option) => option.interval === refetchInterval)}
disableClearSelection
/>
<div className="text-sm mt-2">{`Last updated: ${formatDateTimeShort(
workflowQuery.dataUpdatedAt / 1000
)}`}</div>
</div>
</div>
{isReshard && (
<div className={style.headingMetaContainer}>
<div className={style.headingMeta}>
Expand Down Expand Up @@ -112,18 +158,13 @@ export const Workflow = () => {
</KeyspaceLink>
</span>
</div>
{detailsTab && (
<div style={{ float: 'right' }}>
<a href={`#workflowStreams`}>Scroll To Streams</a>
</div>
)}
</div>
</WorkspaceHeader>

<ContentContainer>
<TabContainer>
<Tab text="Streams" to={`${url}/streams`} count={streams.length} />
<Tab text="Details" to={detailsURL} />
<Tab text="Details" to={`${url}/details`} />
<Tab text="JSON" to={`${url}/json`} />
</TabContainer>

Expand All @@ -133,7 +174,12 @@ export const Workflow = () => {
</Route>

<Route path={`${path}/details`}>
<WorkflowDetails clusterID={clusterID} keyspace={keyspace} name={name} />
<WorkflowDetails
clusterID={clusterID}
keyspace={keyspace}
name={name}
refetchInterval={refetchInterval}
/>
</Route>

<Route path={`${path}/json`}>
Expand Down
20 changes: 13 additions & 7 deletions web/vtadmin/src/components/routes/workflow/WorkflowDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ interface Props {
clusterID: string;
keyspace: string;
name: string;
refetchInterval: number;
}

const SUMMARY_COLUMNS = ['Stream Status', 'Traffic Status', 'Max VReplication Lag', 'Reverse Workflow'];
Expand All @@ -53,16 +54,21 @@ const TABLE_COPY_STATE_COLUMNS = ['Table Name', 'Total Bytes', 'Bytes Copied', '

const STREAM_COLUMNS = ['Stream', 'Source Shard', 'Target Shard', 'Message', 'Transaction Timestamp', 'Database Name'];

export const WorkflowDetails = ({ clusterID, keyspace, name }: Props) => {
export const WorkflowDetails = ({ clusterID, keyspace, name, refetchInterval }: Props) => {
const { data: workflowData } = useWorkflow({ clusterID, keyspace, name });

const { data: workflowsData = [] } = useWorkflows();
const { data: workflowsData = [] } = useWorkflows({ refetchInterval });

const { data: workflowStatus } = useWorkflowStatus({
clusterID,
keyspace,
name,
});
const { data: workflowStatus } = useWorkflowStatus(
{
clusterID,
keyspace,
name,
},
{
refetchInterval,
}
);

const reverseWorkflow = getReverseWorkflow(workflowsData, workflowData);

Expand Down
2 changes: 1 addition & 1 deletion web/vtadmin/src/hooks/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -472,7 +472,7 @@ export const useWorkflowStatus = (
params: Parameters<typeof fetchWorkflowStatus>[0],
options?: UseQueryOptions<vtctldata.WorkflowStatusResponse, Error> | undefined
) => {
return useQuery(['workflow_status', params], () => fetchWorkflowStatus(params));
return useQuery(['workflow_status', params], () => fetchWorkflowStatus(params), options);
};

/**
Expand Down

0 comments on commit 23e5cc0

Please sign in to comment.