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
2 changes: 1 addition & 1 deletion web/vtadmin/src/components/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ export const App = () => {
<Settings />
</Route>

<Redirect exact from="/" to="/tablets" />
<Redirect exact from="/" to="/schemas" />

<Route>
<Error404 />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,17 @@ import { UseQueryResult } from 'react-query';
import { Spinner } from '../Spinner';

interface Props {
query: UseQueryResult;
query?: UseQueryResult;
queries?: UseQueryResult[];
}

/**
* QueryLoadingPlaceholder is a straightforward component that displays a loading
* message when given a query from a useQueryHook. To simplify its use, this component
* takes care of hiding itself when `props.query` is in any state other than "loading".
* message when given one or more queries as returned from useQueryHook.
*
* To simplify its use, this component takes care of hiding itself when all of its
* queries have completed loading.
*
* It's perfectly fine to render it this:
*
* <QueryLoadingPlaceholder query={query} ... />
Expand All @@ -34,16 +38,22 @@ interface Props {
* {query.isLoading && <QueryLoadingPlaceholder query={query} ... />}
*/
export const QueryLoadingPlaceholder: React.FC<Props> = (props) => {
if (!props.query.isLoading) {
const queries = props.queries || [];
if (props.query) {
queries.push(props.query);
}

const anyLoading = queries.some((q) => q.isLoading);
if (!anyLoading) {
return null;
}

const maxFailureCount = Math.max(...queries.map((q) => q.failureCount));

return (
<div aria-busy="true" className="text-center my-12" role="status">
<Spinner />
<div className="my-4 text-secondary">
{props.query.failureCount > 2 ? 'Still loading...' : 'Loading...'}
</div>
<div className="my-4 text-secondary">{maxFailureCount > 2 ? 'Still loading...' : 'Loading...'}</div>
</div>
);
};
8 changes: 5 additions & 3 deletions web/vtadmin/src/components/routes/Clusters.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,15 @@ import { DataCell } from '../dataTable/DataCell';
import { ContentContainer } from '../layout/ContentContainer';
import { WorkspaceHeader } from '../layout/WorkspaceHeader';
import { WorkspaceTitle } from '../layout/WorkspaceTitle';
import { QueryLoadingPlaceholder } from '../placeholders/QueryLoadingPlaceholder';

export const Clusters = () => {
useDocumentTitle('Clusters');
const { data } = useClusters();
const clustersQuery = useClusters();

const rows = React.useMemo(() => {
return orderBy(data, ['name']);
}, [data]);
return orderBy(clustersQuery.data, ['name']);
}, [clustersQuery.data]);

const renderRows = (rows: pb.Cluster[]) =>
rows.map((cluster, idx) => (
Expand All @@ -50,6 +51,7 @@ export const Clusters = () => {
<ContentContainer>
<div className="max-w-screen-sm">
<DataTable columns={['Name', 'Id']} data={rows} renderRows={renderRows} />
<QueryLoadingPlaceholder query={clustersQuery} />
</div>
</ContentContainer>
</div>
Expand Down
8 changes: 5 additions & 3 deletions web/vtadmin/src/components/routes/Gates.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,16 @@ import { DataTable } from '../dataTable/DataTable';
import { ContentContainer } from '../layout/ContentContainer';
import { WorkspaceHeader } from '../layout/WorkspaceHeader';
import { WorkspaceTitle } from '../layout/WorkspaceTitle';
import { QueryLoadingPlaceholder } from '../placeholders/QueryLoadingPlaceholder';

export const Gates = () => {
useDocumentTitle('Gates');

const { data } = useGates();
const gatesQuery = useGates();
const { value: filter, updateValue: updateFilter } = useSyncedURLParam('filter');

const rows = React.useMemo(() => {
const mapped = (data || []).map((g) => ({
const mapped = (gatesQuery.data || []).map((g) => ({
cell: g.cell,
cluster: g.cluster?.name,
hostname: g.hostname,
Expand All @@ -43,7 +44,7 @@ export const Gates = () => {
}));
const filtered = filterNouns(filter, mapped);
return orderBy(filtered, ['cluster', 'pool', 'hostname', 'cell']);
}, [data, filter]);
}, [gatesQuery.data, filter]);

const renderRows = (gates: typeof rows) =>
gates.map((gate, idx) => (
Expand Down Expand Up @@ -72,6 +73,7 @@ export const Gates = () => {
value={filter || ''}
/>
<DataTable columns={['Pool', 'Hostname', 'Cell', 'Keyspaces']} data={rows} renderRows={renderRows} />
<QueryLoadingPlaceholder query={gatesQuery} />
</ContentContainer>
</div>
);
Expand Down
8 changes: 5 additions & 3 deletions web/vtadmin/src/components/routes/Keyspaces.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,16 @@ import KeyspaceActions from './keyspaces/KeyspaceActions';
import { ReadOnlyGate } from '../ReadOnlyGate';
import { isReadOnlyMode } from '../../util/env';
import { Link } from 'react-router-dom';
import { QueryLoadingPlaceholder } from '../placeholders/QueryLoadingPlaceholder';

export const Keyspaces = () => {
useDocumentTitle('Keyspaces');
const { value: filter, updateValue: updateFilter } = useSyncedURLParam('filter');

const { data } = useKeyspaces();
const keyspacesQuery = useKeyspaces();

const ksRows = React.useMemo(() => {
const mapped = (data || []).map((k) => {
const mapped = (keyspacesQuery.data || []).map((k) => {
const shardsByState = getShardsByState(k);

return {
Expand All @@ -54,7 +55,7 @@ export const Keyspaces = () => {
});
const filtered = filterNouns(filter, mapped);
return orderBy(filtered, ['cluster', 'name']);
}, [data, filter]);
}, [keyspacesQuery.data, filter]);

const renderRows = (rows: typeof ksRows) =>
rows.map((row, idx) => (
Expand Down Expand Up @@ -114,6 +115,7 @@ export const Keyspaces = () => {
data={ksRows}
renderRows={renderRows}
/>
<QueryLoadingPlaceholder query={keyspacesQuery} />
</div>
</ContentContainer>
</div>
Expand Down
8 changes: 5 additions & 3 deletions web/vtadmin/src/components/routes/Schemas.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import { ContentContainer } from '../layout/ContentContainer';
import { WorkspaceHeader } from '../layout/WorkspaceHeader';
import { WorkspaceTitle } from '../layout/WorkspaceTitle';
import { KeyspaceLink } from '../links/KeyspaceLink';
import { QueryLoadingPlaceholder } from '../placeholders/QueryLoadingPlaceholder';
import { HelpTooltip } from '../tooltip/HelpTooltip';

const TABLE_COLUMNS = [
Expand Down Expand Up @@ -62,11 +63,11 @@ const TABLE_COLUMNS = [
export const Schemas = () => {
useDocumentTitle('Schemas');

const { data = [] } = useSchemas();
const schemasQuery = useSchemas();
const { value: filter, updateValue: updateFilter } = useSyncedURLParam('filter');

const filteredData = React.useMemo(() => {
const tableDefinitions = getTableDefinitions(data);
const tableDefinitions = getTableDefinitions(schemasQuery.data);

const mapped = tableDefinitions.map((d) => ({
cluster: d.cluster?.name,
Expand All @@ -78,7 +79,7 @@ export const Schemas = () => {

const filtered = filterNouns(filter, mapped);
return orderBy(filtered, ['cluster', 'keyspace', 'table']);
}, [data, filter]);
}, [schemasQuery.data, filter]);

const renderRows = (rows: typeof filteredData) =>
rows.map((row, idx) => {
Expand Down Expand Up @@ -120,6 +121,7 @@ export const Schemas = () => {
value={filter || ''}
/>
<DataTable columns={TABLE_COLUMNS} data={filteredData} renderRows={renderRows} />
<QueryLoadingPlaceholder query={schemasQuery} />
</ContentContainer>
</div>
);
Expand Down
14 changes: 10 additions & 4 deletions web/vtadmin/src/components/routes/Tablets.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import { ShardLink } from '../links/ShardLink';
import InfoDropdown from './tablets/InfoDropdown';
import { isReadOnlyMode } from '../../util/env';
import { ReadOnlyGate } from '../ReadOnlyGate';
import { QueryLoadingPlaceholder } from '../placeholders/QueryLoadingPlaceholder';

const COLUMNS = ['Keyspace', 'Shard', 'Alias', 'Type', 'Tablet State', 'Hostname'];
if (!isReadOnlyMode()) {
Expand All @@ -47,12 +48,16 @@ export const Tablets = () => {
useDocumentTitle('Tablets');

const { value: filter, updateValue: updateFilter } = useSyncedURLParam('filter');
const { data = [] } = useTablets();
const { data: keyspaces = [], ...ksQuery } = useKeyspaces();

const tabletsQuery = useTablets();
const keyspacesQuery = useKeyspaces();
const queries = [tabletsQuery, keyspacesQuery];

const { data: keyspaces = [], ...ksQuery } = keyspacesQuery;

const filteredData = React.useMemo(() => {
return formatRows(data, keyspaces, filter);
}, [data, filter, keyspaces]);
return formatRows(tabletsQuery.data, keyspaces, filter);
}, [tabletsQuery.data, filter, keyspaces]);

const renderRows = React.useCallback(
(rows: typeof filteredData) => {
Expand Down Expand Up @@ -119,6 +124,7 @@ export const Tablets = () => {
value={filter || ''}
/>
<DataTable columns={COLUMNS} data={filteredData} renderRows={renderRows} />
<QueryLoadingPlaceholder queries={queries} />
</ContentContainer>
</div>
);
Expand Down
9 changes: 5 additions & 4 deletions web/vtadmin/src/components/routes/Vtctlds.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,12 @@ import { DataTable } from '../dataTable/DataTable';
import { ContentContainer } from '../layout/ContentContainer';
import { WorkspaceHeader } from '../layout/WorkspaceHeader';
import { WorkspaceTitle } from '../layout/WorkspaceTitle';
import { QueryLoadingPlaceholder } from '../placeholders/QueryLoadingPlaceholder';

export const Vtctlds = () => {
const { data: vtctlds = [], ...q } = useVtctlds();
const vtctldsQuery = useVtctlds();
const { data: vtctlds = [] } = vtctldsQuery;

const { value: filter, updateValue: updateFilter } = useSyncedURLParam('filter');

const data = useMemo(() => {
Expand Down Expand Up @@ -81,9 +84,7 @@ export const Vtctlds = () => {
value={filter || ''}
/>
<DataTable columns={['Hostname', 'Cluster']} data={data} renderRows={renderRows} />

{/* TODO skeleton placeholder */}
{!!q.isLoading && <div className="text-center">Loading</div>}
<QueryLoadingPlaceholder query={vtctldsQuery} />
</ContentContainer>
</div>
);
Expand Down
11 changes: 8 additions & 3 deletions web/vtadmin/src/components/routes/Workflows.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,17 @@ import { WorkspaceTitle } from '../layout/WorkspaceTitle';
import { DataFilter } from '../dataTable/DataFilter';
import { Tooltip } from '../tooltip/Tooltip';
import { KeyspaceLink } from '../links/KeyspaceLink';
import { QueryLoadingPlaceholder } from '../placeholders/QueryLoadingPlaceholder';
import { UseQueryResult } from 'react-query';

export const Workflows = () => {
useDocumentTitle('Workflows');
const { data } = useWorkflows();
const workflowsQuery = useWorkflows();

const { value: filter, updateValue: updateFilter } = useSyncedURLParam('filter');

const sortedData = React.useMemo(() => {
const mapped = (data || []).map((workflow) => ({
const mapped = (workflowsQuery.data || []).map((workflow) => ({
clusterID: workflow.cluster?.id,
clusterName: workflow.cluster?.name,
keyspace: workflow.keyspace,
Expand All @@ -54,7 +57,7 @@ export const Workflows = () => {
}));
const filtered = filterNouns(filter, mapped);
return orderBy(filtered, ['name', 'clusterName', 'source', 'target']);
}, [data, filter]);
}, [workflowsQuery.data, filter]);

const renderRows = (rows: typeof sortedData) =>
rows.map((row, idx) => {
Expand Down Expand Up @@ -150,6 +153,8 @@ export const Workflows = () => {
data={sortedData}
renderRows={renderRows}
/>

<QueryLoadingPlaceholder query={workflowsQuery as UseQueryResult} />
</ContentContainer>
</div>
);
Expand Down