diff --git a/web/src/OverviewTable.tsx b/web/src/OverviewTable.tsx
index c1a580b55d..cbbdaa0868 100644
--- a/web/src/OverviewTable.tsx
+++ b/web/src/OverviewTable.tsx
@@ -3,7 +3,7 @@ import {
AccordionDetails,
AccordionSummary,
} from "@material-ui/core"
-import React, { ChangeEvent, useMemo, useState } from "react"
+import React, { ChangeEvent, MouseEvent, useMemo, useState } from "react"
import {
HeaderGroup,
Row,
@@ -11,13 +11,19 @@ import {
TableHeaderProps,
TableOptions,
TableState,
+ usePagination,
useSortBy,
+ UseSortByState,
useTable,
} from "react-table"
import styled from "styled-components"
import { buildAlerts, runtimeAlerts } from "./alerts"
import { AnalyticsType } from "./analytics"
import { ApiButtonType, buttonsForComponent } from "./ApiButton"
+import {
+ DEFAULT_RESOURCE_LIST_LIMIT,
+ RESOURCE_LIST_MULTIPLIER,
+} from "./constants"
import Features, { Flag, useFeatures } from "./feature"
import { Hold } from "./Hold"
import {
@@ -57,6 +63,7 @@ import {
resourceTargetType,
} from "./ResourceStatus"
import { TableGroupStatusSummary } from "./ResourceStatusSummary"
+import { ShowMoreButton } from "./ShowMoreButton"
import { buildStatus, runtimeStatus } from "./status"
import { Color, Font, FontSize, SizeUnit, Width } from "./style-helpers"
import { isZeroTime, timeDiff } from "./time"
@@ -168,7 +175,12 @@ export const ResourceTableData = styled.td`
&.isSorted {
background-color: ${Color.gray};
}
+
+ &.alignRight {
+ text-align: right;
+ }
`
+
export const ResourceTableHeader = styled(ResourceTableData)`
color: ${Color.gray7};
font-size: ${FontSize.small};
@@ -539,21 +551,63 @@ export function ResourceTableHeadRow({
)
}
+function ShowMoreResourcesRow({
+ colSpan,
+ itemCount,
+ pageSize,
+ onClick,
+}: {
+ colSpan: number
+ itemCount: number
+ pageSize: number
+ onClick: (e: MouseEvent) => void
+}) {
+ if (itemCount <= pageSize) {
+ return null
+ }
+
+ return (
+
+
+
+
+
+
+ )
+}
+
export function Table(props: TableProps) {
if (props.data.length === 0) {
return null
}
- const { getTableProps, getTableBodyProps, headerGroups, rows, prepareRow } =
- useTable(
- {
- columns: props.columns,
- data: props.data,
- autoResetSortBy: false,
- useControlledState: props.useControlledState,
- },
- useSortBy
- )
+ const {
+ getTableProps,
+ getTableBodyProps,
+ headerGroups,
+ rows,
+ page,
+ prepareRow,
+ state: { pageSize },
+ setPageSize,
+ } = useTable(
+ {
+ columns: props.columns,
+ data: props.data,
+ autoResetSortBy: false,
+ useControlledState: props.useControlledState,
+ initialState: { pageSize: DEFAULT_RESOURCE_LIST_LIMIT },
+ },
+ useSortBy,
+ usePagination
+ )
+
+ const showMoreOnClick = () => setPageSize(pageSize * RESOURCE_LIST_MULTIPLIER)
// TODO (lizz): Consider adding `aria-sort` markup to table headings
return (
@@ -568,7 +622,7 @@ export function Table(props: TableProps) {
))}
- {rows.map((row: Row) => {
+ {page.map((row: Row) => {
prepareRow(row)
return (
)
})}
+
)
@@ -640,7 +700,7 @@ export function TableGroupedByLabels({
// tables by the same column
// See: https://react-table.tanstack.com/docs/faq#how-can-i-manually-control-the-table-state
const [globalTableSettings, setGlobalTableSettings] =
- useState>()
+ useState>()
const useControlledState = (state: TableState) =>
useMemo(() => {
diff --git a/web/src/ShowMoreButton.tsx b/web/src/ShowMoreButton.tsx
new file mode 100644
index 0000000000..670e6bc2bb
--- /dev/null
+++ b/web/src/ShowMoreButton.tsx
@@ -0,0 +1,65 @@
+import React, { MouseEventHandler } from "react"
+import styled from "styled-components"
+import { Tags } from "./analytics"
+import { InstrumentedButton } from "./instrumentedComponents"
+import {
+ AnimDuration,
+ Color,
+ Font,
+ FontSize,
+ mixinResetButtonStyle,
+} from "./style-helpers"
+
+const ShowMoreButtonRoot = styled(InstrumentedButton)`
+ ${mixinResetButtonStyle};
+ color: ${Color.gray6};
+ font-family: ${Font.sansSerif};
+ font-size: ${FontSize.small};
+ padding: 0 0.5em;
+ transition: color ${AnimDuration.default} ease;
+
+ &:hover,
+ &:focus,
+ &:active {
+ color: ${Color.blue};
+ }
+`
+
+const ShowMoreCount = styled.span`
+ color: ${Color.gray7};
+ font-family: ${Font.sansSerif};
+ font-size: ${FontSize.small};
+`
+
+export function ShowMoreButton({
+ itemCount,
+ currentListSize,
+ onClick,
+ analyticsTags,
+}: {
+ itemCount: number
+ currentListSize: number
+ analyticsTags: Tags
+ onClick: MouseEventHandler
+}) {
+ if (itemCount <= currentListSize) {
+ return null
+ }
+
+ const remainingCount = itemCount - currentListSize
+
+ return (
+ <>
+
+ …Show more
+
+
+ ({remainingCount})
+
+ >
+ )
+}
diff --git a/web/src/SidebarResources.tsx b/web/src/SidebarResources.tsx
index aa6e2cd96a..11e504f25e 100644
--- a/web/src/SidebarResources.tsx
+++ b/web/src/SidebarResources.tsx
@@ -5,9 +5,12 @@ import {
} from "@material-ui/core"
import React, { ChangeEvent, useCallback, useMemo, useState } from "react"
import styled from "styled-components"
-import { AnalyticsType, emptyTags } from "./analytics"
+import { AnalyticsType } from "./analytics"
+import {
+ DEFAULT_RESOURCE_LIST_LIMIT,
+ RESOURCE_LIST_MULTIPLIER,
+} from "./constants"
import { FeaturesContext, Flag, useFeatures } from "./feature"
-import { InstrumentedButton } from "./instrumentedComponents"
import {
GroupByLabelView,
orderLabels,
@@ -28,20 +31,14 @@ import { useResourceGroups } from "./ResourceGroupsContext"
import { ResourceListOptions } from "./ResourceListOptionsContext"
import { matchesResourceName } from "./ResourceNameFilter"
import { SidebarGroupStatusSummary } from "./ResourceStatusSummary"
+import { ShowMoreButton } from "./ShowMoreButton"
import SidebarItem from "./SidebarItem"
import SidebarItemView, {
sidebarItemIsDisabled,
SidebarItemRoot,
} from "./SidebarItemView"
import SidebarKeyboardShortcuts from "./SidebarKeyboardShortcuts"
-import {
- AnimDuration,
- Color,
- Font,
- FontSize,
- mixinResetButtonStyle,
- SizeUnit,
-} from "./style-helpers"
+import { Color, Font, FontSize, SizeUnit } from "./style-helpers"
import { triggerUpdate } from "./trigger"
import { ResourceStatus, ResourceView } from "./types"
@@ -199,58 +196,35 @@ export function SidebarListSection(props: SidebarSectionProps): JSX.Element {
)
}
-const defaultMaxItems = 20
-
const ShowMoreRow = styled.li`
margin: ${SizeUnit(0.5)} ${SizeUnit(0.5)} 0 ${SizeUnit(0.5)};
- color: ${Color.gray7};
- font-size: ${FontSize.small};
display: flex;
align-items: center;
justify-content: right;
- font-family: ${Font.sansSerif};
-`
-
-const ShowMoreButton = styled(InstrumentedButton)`
- ${mixinResetButtonStyle};
- font-size: ${FontSize.small};
- color: ${Color.gray6};
- transition: color ${AnimDuration.default} ease;
- cursor: pointer;
- padding: 0 0.5em;
-
- &:hover {
- color: ${Color.blue};
- }
`
function SidebarListSectionItems(props: SidebarSectionProps) {
- let [maxItems, setMaxItems] = useState(defaultMaxItems)
+ let [maxItems, setMaxItems] = useState(DEFAULT_RESOURCE_LIST_LIMIT)
let displayItems = props.items
- let remaining = 0
let moreItems = Math.max(displayItems.length - maxItems, 0)
if (moreItems) {
- remaining = displayItems.length - maxItems
displayItems = displayItems.slice(0, maxItems)
}
let showMore = useCallback(() => {
- setMaxItems(maxItems * 2)
+ setMaxItems(maxItems * RESOURCE_LIST_MULTIPLIER)
}, [maxItems, setMaxItems])
let showMoreItemsButton = null
if (moreItems > 0) {
- let text = ` (${remaining})`
showMoreItemsButton = (
- …Show More
-
- {`(${remaining})`}
+ analyticsTags={{ type: AnalyticsType.Detail }}
+ currentListSize={maxItems}
+ itemCount={props.items.length}
+ />
)
}
diff --git a/web/src/constants.ts b/web/src/constants.ts
index baf60cdc20..fd4d4ba351 100644
--- a/web/src/constants.ts
+++ b/web/src/constants.ts
@@ -44,3 +44,6 @@ export function linkToTiltDocs(page?: TiltDocsPage, anchor?: string) {
return `${TILT_DOCS_LINK}/${page}${anchor ?? ""}`
}
+
+export const DEFAULT_RESOURCE_LIST_LIMIT = 20
+export const RESOURCE_LIST_MULTIPLIER = 2
diff --git a/web/src/react-table-config.d.ts b/web/src/react-table-config.d.ts
index 949d7f0b07..f680cea73b 100644
--- a/web/src/react-table-config.d.ts
+++ b/web/src/react-table-config.d.ts
@@ -1,6 +1,9 @@
// From https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/react-table
import {
+ UsePaginationInstanceProps,
+ UsePaginationOptions,
+ UsePaginationState,
UseSortByColumnOptions,
UseSortByColumnProps,
UseSortByHooks,
@@ -13,12 +16,12 @@ declare module "react-table" {
// take this file as-is, or comment out the sections that don't apply to your plugin configuration
export interface TableOptions>
- extends UseSortByOptions {
+ extends UseSortByOptions,
+ UsePaginationOptions {
// UseExpandedOptions,
// UseFiltersOptions,
// UseGlobalFiltersOptions,
// UseGroupByOptions,
- // UsePaginationOptions,
// UseResizeColumnsOptions,
// UseRowSelectOptions,
// UseRowStateOptions,
@@ -39,13 +42,13 @@ declare module "react-table" {
export interface TableInstance<
D extends Record = Record
- > extends UseSortByInstanceProps {
+ > extends UseSortByInstanceProps,
+ UsePaginationInstanceProps {
// UseColumnOrderInstanceProps,
// UseExpandedInstanceProps,
// UseFiltersInstanceProps,
// UseGlobalFiltersInstanceProps,
// UseGroupByInstanceProps,
- // UsePaginationInstanceProps,
// UseRowSelectInstanceProps,
// UseRowStateInstanceProps,
// UseSortByInstanceProps
@@ -53,13 +56,13 @@ declare module "react-table" {
export interface TableState<
D extends Record = Record
- > extends UseSortByState {
+ > extends UseSortByState,
+ UsePaginationState {
// UseColumnOrderState,
// UseExpandedState,
// UseFiltersState,
// UseGlobalFiltersState,
// UseGroupByState,
- // UsePaginationState,
// UseResizeColumnsState,
// UseRowSelectState,
// UseRowStateState,