chore(site): remove new filter from experimental (#8112)

This commit is contained in:
Bruno Quaresma
2023-06-21 10:20:37 -03:00
committed by GitHub
parent cc17d2feea
commit bce8a983fe
21 changed files with 120 additions and 501 deletions
+2 -4
View File
@@ -7355,13 +7355,11 @@ const docTemplate = `{
"type": "string",
"enum": [
"moons",
"workspace_actions",
"workspace_filter"
"workspace_actions"
],
"x-enum-varnames": [
"ExperimentMoons",
"ExperimentWorkspaceActions",
"ExperimentWorkspaceFilter"
"ExperimentWorkspaceActions"
]
},
"codersdk.Feature": {
+2 -6
View File
@@ -6582,12 +6582,8 @@
},
"codersdk.Experiment": {
"type": "string",
"enum": ["moons", "workspace_actions", "workspace_filter"],
"x-enum-varnames": [
"ExperimentMoons",
"ExperimentWorkspaceActions",
"ExperimentWorkspaceFilter"
]
"enum": ["moons", "workspace_actions"],
"x-enum-varnames": ["ExperimentMoons", "ExperimentWorkspaceActions"]
},
"codersdk.Feature": {
"type": "object",
+1 -6
View File
@@ -1704,9 +1704,6 @@ const (
// https://github.com/coder/coder/milestone/19
ExperimentWorkspaceActions Experiment = "workspace_actions"
// New workspace filter
ExperimentWorkspaceFilter Experiment = "workspace_filter"
// Add new experiments here!
// ExperimentExample Experiment = "example"
)
@@ -1715,9 +1712,7 @@ const (
// users to opt-in to via --experimental='*'.
// Experiments that are not ready for consumption by all users should
// not be included here and will be essentially hidden.
var ExperimentsAll = Experiments{
ExperimentWorkspaceFilter,
}
var ExperimentsAll = Experiments{}
// Experiments is a list of experiments that are enabled for the deployment.
// Multiple experiments may be enabled at the same time.
-1
View File
@@ -2490,7 +2490,6 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in
| ------------------- |
| `moons` |
| `workspace_actions` |
| `workspace_filter` |
## codersdk.Feature
+2 -6
View File
@@ -1344,12 +1344,8 @@ export const Entitlements: Entitlement[] = [
]
// From codersdk/deployment.go
export type Experiment = "moons" | "workspace_actions" | "workspace_filter"
export const Experiments: Experiment[] = [
"moons",
"workspace_actions",
"workspace_filter",
]
export type Experiment = "moons" | "workspace_actions"
export const Experiments: Experiment[] = ["moons", "workspace_actions"]
// From codersdk/deployment.go
export type FeatureName =
+2
View File
@@ -74,6 +74,8 @@ export const useFilter = ({
}
}
export type UseFilterResult = ReturnType<typeof useFilter>
const parseFilterQuery = (filterQuery: string): FilterValues => {
if (filterQuery === "") {
return {}
+2
View File
@@ -101,3 +101,5 @@ export const useFilterMenu = <TOption extends BaseOption = BaseOption>({
isSearching: searchOptionsQuery.isFetching,
}
}
export type UseFilterMenuResult = ReturnType<typeof useFilterMenu>
@@ -0,0 +1,34 @@
import { action } from "@storybook/addon-actions"
import { UseFilterResult } from "./filter"
import { UseFilterMenuResult } from "./menu"
export const MockMenu: UseFilterMenuResult = {
initialOption: undefined,
isInitializing: false,
isSearching: false,
query: "",
searchOptions: [],
selectedOption: undefined,
selectOption: action("selectOption"),
setQuery: action("updateQuery"),
}
export const getDefaultFilterProps = <TFilterProps>({
query = "",
values,
menus,
}: {
query?: string
values: Record<string, string | undefined>
menus: Record<string, UseFilterMenuResult>
}) =>
({
filter: {
query,
update: () => action("update"),
debounceUpdate: action("debounce") as UseFilterResult["debounceUpdate"],
used: false,
values,
},
menus,
} as TFilterProps)
@@ -1,47 +0,0 @@
import { Story } from "@storybook/react"
import { userFilterQuery, workspaceFilterQuery } from "../../utils/filters"
import {
SearchBarWithFilter,
SearchBarWithFilterProps,
} from "./SearchBarWithFilter"
import { mockApiError } from "testHelpers/entities"
export default {
title: "components/SearchBarWithFilter",
component: SearchBarWithFilter,
args: {
filter: workspaceFilterQuery.me,
},
}
const Template: Story<SearchBarWithFilterProps> = (args) => (
<SearchBarWithFilter {...args} />
)
export const WithoutPresetFilters = Template.bind({})
export const WithPresetFilters = Template.bind({})
WithPresetFilters.args = {
presetFilters: [
{ query: workspaceFilterQuery.me, name: "Your workspaces" },
{ query: "random query", name: "Random query" },
],
}
export const WithError = Template.bind({})
WithError.args = {
filter: "status:inactive",
presetFilters: [
{ query: userFilterQuery.active, name: "Active users" },
{ query: "random query", name: "Random query" },
],
error: mockApiError({
message: "Invalid user search query.",
validations: [
{
field: "status",
detail: `Query param "status" has invalid value: "inactive" is not a valid user status`,
},
],
}),
}
@@ -1,26 +0,0 @@
import { screen } from "@testing-library/react"
import userEvent from "@testing-library/user-event"
import { render } from "../../testHelpers/renderHelpers"
import { SearchBarWithFilter } from "./SearchBarWithFilter"
// mock the debounce utility
jest.mock("just-debounce-it", () =>
jest.fn((fn) => {
fn.cancel = jest.fn()
return fn
}),
)
describe("SearchBarWithFilter", () => {
it("calls the onFilter handler on keystroke", async () => {
// When
const onFilter = jest.fn()
render(<SearchBarWithFilter onFilter={onFilter} />)
const searchInput = screen.getByRole("textbox")
await userEvent.type(searchInput, "workspace") // 9 characters
// Then
expect(onFilter).toBeCalledTimes(9) // 9 characters
})
})
@@ -1,212 +0,0 @@
import Button from "@mui/material/Button"
import Fade from "@mui/material/Fade"
import InputAdornment from "@mui/material/InputAdornment"
import Menu from "@mui/material/Menu"
import MenuItem from "@mui/material/MenuItem"
import OutlinedInput from "@mui/material/OutlinedInput"
import { makeStyles } from "@mui/styles"
import { Theme } from "@mui/material/styles"
import SearchIcon from "@mui/icons-material/Search"
import debounce from "just-debounce-it"
import { useCallback, useEffect, useRef, useState } from "react"
import { getValidationErrorMessage } from "../../api/errors"
import { CloseDropdown, OpenDropdown } from "../DropdownArrows/DropdownArrows"
import { Stack } from "../Stack/Stack"
export const Language = {
filterName: "Filters",
}
export interface SearchBarWithFilterProps {
filter?: string
onFilter: (query: string) => void
presetFilters?: PresetFilter[]
error?: unknown
docs?: string
}
export interface PresetFilter {
name: string
query: string
}
export const SearchBarWithFilter: React.FC<
React.PropsWithChildren<SearchBarWithFilterProps>
> = ({ filter, onFilter, presetFilters, error, docs }) => {
const styles = useStyles({ error: Boolean(error) })
const searchInputRef = useRef<HTMLInputElement>(null)
const [value, setValue] = useState(filter)
useEffect(() => {
setValue(filter)
}, [filter])
// debounce query string entry by user
// we want the dependency array empty here
// as we don't need to redefine the function
// eslint-disable-next-line react-hooks/exhaustive-deps -- see above
const debouncedOnFilter = useCallback(
debounce((debouncedQueryString: string) => {
onFilter(debouncedQueryString)
}, 300),
[],
)
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null)
const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
setAnchorEl(event.currentTarget)
}
const handleClose = () => {
setAnchorEl(null)
}
const setPresetFilter = (query: string) => () => {
if (!searchInputRef.current) {
throw new Error("Search input not found.")
}
onFilter(query)
// Update this to the input directly instead of create a new state and
// re-render the component since the onFilter is already calling the
// filtering process
searchInputRef.current.value = query
handleClose()
}
const errorMessage = getValidationErrorMessage(error)
return (
<Stack spacing={1} className={styles.root}>
<Stack direction="row" spacing={0}>
{presetFilters && presetFilters.length > 0 && (
<Button
aria-controls="filter-menu"
aria-haspopup="true"
size="large"
onClick={handleClick}
className={styles.buttonRoot}
>
{Language.filterName}{" "}
{anchorEl ? <CloseDropdown /> : <OpenDropdown />}
</Button>
)}
<div role="form" className={styles.filterForm}>
<OutlinedInput
id="query"
name="query"
error={Boolean(error)}
value={value}
className={styles.inputStyles}
onChange={(event) => {
setValue(event.currentTarget.value)
debouncedOnFilter(event.currentTarget.value)
}}
inputRef={searchInputRef}
inputProps={{
"aria-label": "Filter",
}}
startAdornment={
<InputAdornment position="start" className={styles.searchIcon}>
<SearchIcon fontSize="small" />
</InputAdornment>
}
/>
</div>
{presetFilters && presetFilters.length > 0 ? (
<Menu
id="filter-menu"
anchorEl={anchorEl}
keepMounted
open={Boolean(anchorEl)}
onClose={handleClose}
TransitionComponent={Fade}
anchorOrigin={{
vertical: "bottom",
horizontal: "left",
}}
transformOrigin={{
vertical: "top",
horizontal: "left",
}}
>
{presetFilters.map((presetFilter) => (
<MenuItem
key={presetFilter.name}
onClick={setPresetFilter(presetFilter.query)}
>
{presetFilter.name}
</MenuItem>
))}
{docs && (
<MenuItem component="a" href={docs} target="_blank">
View advanced filtering
</MenuItem>
)}
</Menu>
) : null}
</Stack>
{errorMessage && (
<Stack className={styles.errorRoot}>{errorMessage}</Stack>
)}
</Stack>
)
}
interface StyleProps {
error?: boolean
}
const useStyles = makeStyles<Theme, StyleProps>((theme) => ({
root: {
marginBottom: theme.spacing(2),
"&:has(button) .MuiInputBase-root": {
borderTopLeftRadius: 0,
borderBottomLeftRadius: 0,
},
},
// necessary to expand the textField
// the length of the page (within the bordered filterContainer)
filterForm: {
width: "100%",
},
buttonRoot: {
border: `1px solid ${theme.palette.divider}`,
borderRadius: `${theme.shape.borderRadius}px 0px 0px ${theme.shape.borderRadius}px`,
flexShrink: 0,
marginRight: -1,
"&:hover": {
zIndex: 1,
},
},
errorRoot: {
color: theme.palette.error.main,
whiteSpace: "pre-wrap",
},
inputStyles: {
height: "100%",
width: "100%",
color: theme.palette.primary.contrastText,
backgroundColor: theme.palette.background.paper,
"& fieldset": {
borderColor: theme.palette.divider,
"&MuiOutlinedInput-root:hover, &MuiOutlinedInput-notchedOutline": {
borderColor: (props) => props.error && theme.palette.error.contrastText,
},
},
"& .MuiInputBase-input": {
paddingTop: "inherit",
paddingBottom: "inherit",
// The same as the button
minHeight: 40,
},
},
searchIcon: {
color: theme.palette.text.secondary,
},
}))
+9 -18
View File
@@ -7,14 +7,12 @@ import { pageTitle } from "utils/page"
import { AuditPageView } from "./AuditPageView"
import { useUserFilterMenu } from "components/Filter/UserFilter"
import { useFilter } from "components/Filter/filter"
import { useDashboard } from "components/Dashboard/DashboardProvider"
import { usePagination } from "hooks"
import { useQuery } from "@tanstack/react-query"
import { getAuditLogs } from "api/api"
import { useActionFilterMenu, useResourceTypeFilterMenu } from "./AuditFilter"
const AuditPage: FC = () => {
const dashboard = useDashboard()
const searchParamsResult = useSearchParams()
const pagination = usePagination({ searchParamsResult })
const filter = useFilter({
@@ -73,22 +71,15 @@ const AuditPage: FC = () => {
isNonInitialPage={nonInitialPage(searchParamsResult[0])}
isAuditLogVisible={isAuditLogVisible}
error={error}
filterProps={
dashboard.experiments.includes("workspace_filter")
? {
filter,
error,
menus: {
user: userMenu,
action: actionMenu,
resourceType: resourceTypeMenu,
},
}
: {
filter: filter.query,
onFilter: filter.update,
}
}
filterProps={{
filter,
error,
menus: {
user: userMenu,
action: actionMenu,
resourceType: resourceTypeMenu,
},
}}
/>
</>
)
@@ -1,41 +1,25 @@
/* eslint-disable eslint-comments/disable-enable-pair -- ignore */
/* eslint-disable @typescript-eslint/no-explicit-any -- We don't care about any here */
import { Meta, StoryObj } from "@storybook/react"
import { MockAuditLog, MockAuditLog2, MockUser } from "testHelpers/entities"
import { AuditPageView } from "./AuditPageView"
import { action } from "@storybook/addon-actions"
import { WorkspacesPageView } from "pages/WorkspacesPage/WorkspacesPageView"
import { ComponentProps } from "react"
import { MockMenu, getDefaultFilterProps } from "components/Filter/storyHelpers"
const mockMenu = {
initialOption: undefined,
isInitializing: false,
isSearching: false,
query: "",
searchOptions: [],
selectedOption: undefined,
selectOption: action("selectOption"),
setQuery: action("updateQuery"),
}
type FilterProps = ComponentProps<typeof AuditPageView>["filterProps"]
const defaultFilterProps = {
filter: {
query: `owner:me`,
update: () => action("update"),
debounceUpdate: action("debounce") as any,
used: false,
values: {
username: MockUser.username,
action: undefined,
resource_type: undefined,
},
const defaultFilterProps = getDefaultFilterProps<FilterProps>({
query: `owner:me`,
values: {
username: MockUser.username,
action: undefined,
resource_type: undefined,
},
menus: {
user: mockMenu,
action: mockMenu,
resourceType: mockMenu,
user: MockMenu,
action: MockMenu,
resourceType: MockMenu,
},
} as ComponentProps<typeof AuditPageView>["filterProps"]
})
const meta: Meta<typeof AuditPageView> = {
title: "pages/AuditPageView",
+2 -31
View File
@@ -13,7 +13,6 @@ import {
PageHeaderSubtitle,
PageHeaderTitle,
} from "components/PageHeader/PageHeader"
import { SearchBarWithFilter } from "components/SearchBarWithFilter/SearchBarWithFilter"
import { Stack } from "components/Stack/Stack"
import { TableLoader } from "components/TableLoader/TableLoader"
import { Timeline } from "components/Timeline/Timeline"
@@ -30,23 +29,6 @@ export const Language = {
subtitle: "View events in your audit log.",
}
const presetFilters = [
{
query: "resource_type:workspace action:create",
name: "Created workspaces",
},
{ query: "resource_type:template action:create", name: "Added templates" },
{ query: "resource_type:user action:delete", name: "Deleted users" },
{
query: "resource_type:workspace_build action:start build_reason:initiator",
name: "Builds started by a user",
},
{
query: "resource_type:api_key action:login",
name: "User logins",
},
]
export interface AuditPageViewProps {
auditLogs?: AuditLog[]
count?: number
@@ -56,9 +38,7 @@ export interface AuditPageViewProps {
isNonInitialPage: boolean
isAuditLogVisible: boolean
error?: Error | unknown
filterProps:
| ComponentProps<typeof SearchBarWithFilter>
| ComponentProps<typeof AuditFilter>
filterProps: ComponentProps<typeof AuditFilter>
}
export const AuditPageView: FC<AuditPageViewProps> = ({
@@ -91,16 +71,7 @@ export const AuditPageView: FC<AuditPageViewProps> = ({
<ChooseOne>
<Cond condition={isAuditLogVisible}>
{"onFilter" in filterProps ? (
<SearchBarWithFilter
{...filterProps}
docs="https://coder.com/docs/coder-oss/latest/admin/audit-logs#filtering-logs"
presetFilters={presetFilters}
error={error}
/>
) : (
<AuditFilter {...filterProps} />
)}
<AuditFilter {...filterProps} />
<PaginationStatus
isLoading={Boolean(isLoading)}
+7 -20
View File
@@ -18,7 +18,6 @@ import { ResetPasswordDialog } from "../../components/Dialogs/ResetPasswordDialo
import { pageTitle } from "../../utils/page"
import { UsersPageView } from "./UsersPageView"
import { useStatusFilterMenu } from "./UsersFilter"
import { useDashboard } from "components/Dashboard/DashboardProvider"
import { useFilter } from "components/Filter/filter"
export const Language = {
@@ -77,8 +76,6 @@ export const UsersPage: FC<{ children?: ReactNode }> = () => {
const me = useMe()
// New filter
const dashboard = useDashboard()
const useFilterResult = useFilter({
searchParamsResult,
onUpdate: () => {
@@ -148,29 +145,19 @@ export const UsersPage: FC<{ children?: ReactNode }> = () => {
roles,
})
}}
error={getUsersError}
isUpdatingUserRoles={usersState.matches("updatingUserRoles")}
isLoading={isLoading}
canEditUsers={canEditUsers}
paginationRef={paginationRef}
isNonInitialPage={nonInitialPage(searchParams)}
actorID={me.id}
filterProps={
dashboard.experiments.includes("workspace_filter")
? {
filter: useFilterResult,
error: getUsersError,
menus: {
status: statusMenu,
},
}
: {
filter: usersState.context.filter,
onFilter: (query) => {
usersSend({ type: "UPDATE_FILTER", query })
},
}
}
filterProps={{
filter: useFilterResult,
error: getUsersError,
menus: {
status: statusMenu,
},
}}
/>
<DeleteDialog
@@ -7,7 +7,20 @@ import {
mockApiError,
} from "testHelpers/entities"
import { UsersPageView } from "./UsersPageView"
import { action } from "@storybook/addon-actions"
import { ComponentProps } from "react"
import { MockMenu, getDefaultFilterProps } from "components/Filter/storyHelpers"
type FilterProps = ComponentProps<typeof UsersPageView>["filterProps"]
const defaultFilterProps = getDefaultFilterProps<FilterProps>({
query: "owner:me",
menus: {
status: MockMenu,
},
values: {
status: "active",
},
})
const meta: Meta<typeof UsersPageView> = {
title: "pages/UsersPageView",
@@ -19,10 +32,7 @@ const meta: Meta<typeof UsersPageView> = {
roles: MockAssignableSiteRoles,
count: 2,
canEditUsers: true,
filterProps: {
onFilter: action("onFilter"),
filter: "",
},
filterProps: defaultFilterProps,
},
}
@@ -56,14 +66,18 @@ export const EmptyPage = {
export const Error = {
args: {
users: undefined,
error: mockApiError({
message: "Invalid user search query.",
validations: [
{
field: "status",
detail: `Query param "status" has invalid value: "inactive" is not a valid user status`,
},
],
}),
count: 0,
filterProps: {
...defaultFilterProps,
error: mockApiError({
message: "Invalid user search query.",
validations: [
{
field: "status",
detail: `Query param "status" has invalid value: "inactive" is not a valid user status`,
},
],
}),
},
},
}
+2 -21
View File
@@ -2,9 +2,7 @@ import { PaginationWidget } from "components/PaginationWidget/PaginationWidget"
import { ComponentProps, FC } from "react"
import { PaginationMachineRef } from "xServices/pagination/paginationXService"
import * as TypesGen from "../../api/typesGenerated"
import { SearchBarWithFilter } from "../../components/SearchBarWithFilter/SearchBarWithFilter"
import { UsersTable } from "../../components/UsersTable/UsersTable"
import { userFilterQuery } from "../../utils/filters"
import { UsersFilter } from "./UsersFilter"
import { PaginationStatus } from "components/PaginationStatus/PaginationStatus"
@@ -16,7 +14,6 @@ export interface UsersPageViewProps {
users?: TypesGen.User[]
count?: number
roles?: TypesGen.AssignableRoles[]
error?: unknown
isUpdatingUserRoles?: boolean
canEditUsers?: boolean
isLoading?: boolean
@@ -30,9 +27,7 @@ export interface UsersPageViewProps {
user: TypesGen.User,
roles: TypesGen.Role["name"][],
) => void
filterProps:
| ComponentProps<typeof SearchBarWithFilter>
| ComponentProps<typeof UsersFilter>
filterProps: ComponentProps<typeof UsersFilter>
paginationRef: PaginationMachineRef
isNonInitialPage: boolean
actorID: string
@@ -49,7 +44,6 @@ export const UsersPageView: FC<React.PropsWithChildren<UsersPageViewProps>> = ({
onActivateUser,
onResetUserPassword,
onUpdateUserRoles,
error,
isUpdatingUserRoles,
canEditUsers,
isLoading,
@@ -58,22 +52,9 @@ export const UsersPageView: FC<React.PropsWithChildren<UsersPageViewProps>> = ({
isNonInitialPage,
actorID,
}) => {
const presetFilters = [
{ query: userFilterQuery.active, name: Language.activeUsersFilterName },
{ query: userFilterQuery.all, name: Language.allUsersFilterName },
]
return (
<>
{"onFilter" in filterProps ? (
<SearchBarWithFilter
{...filterProps}
presetFilters={presetFilters}
error={error}
/>
) : (
<UsersFilter {...filterProps} />
)}
<UsersFilter {...filterProps} />
<PaginationStatus
isLoading={Boolean(isLoading)}
@@ -7,7 +7,6 @@ import { WorkspacesPageView } from "./WorkspacesPageView"
import { useOrganizationId, usePermissions } from "hooks"
import { useTemplateFilterMenu, useStatusFilterMenu } from "./filter/menus"
import { useSearchParams } from "react-router-dom"
import { useDashboard } from "components/Dashboard/DashboardProvider"
import { useFilter } from "components/Filter/filter"
import { useUserFilterMenu } from "components/Filter/UserFilter"
@@ -49,7 +48,6 @@ const WorkspacesPage: FC = () => {
onChange: (option) =>
filter.update({ ...filter.values, status: option?.value }),
})
const dashboard = useDashboard()
return (
<>
@@ -58,7 +56,6 @@ const WorkspacesPage: FC = () => {
</Helmet>
<WorkspacesPageView
useNewFilter={dashboard.experiments.includes("workspace_filter")}
workspaces={data?.workspaces}
error={error}
count={data?.count}
@@ -1,5 +1,3 @@
/* eslint-disable eslint-comments/disable-enable-pair -- ignore */
/* eslint-disable @typescript-eslint/no-explicit-any -- We don't care about any here */
import { Meta, StoryObj } from "@storybook/react"
import { DEFAULT_RECORDS_PER_PAGE } from "components/PaginationWidget/utils"
import dayjs from "dayjs"
@@ -15,13 +13,13 @@ import {
MockBuildInfo,
MockEntitlementsWithScheduling,
MockExperiments,
MockUser,
mockApiError,
MockUser,
} from "testHelpers/entities"
import { WorkspacesPageView } from "./WorkspacesPageView"
import { DashboardProviderContext } from "components/Dashboard/DashboardProvider"
import { action } from "@storybook/addon-actions"
import { ComponentProps } from "react"
import { MockMenu, getDefaultFilterProps } from "components/Filter/storyHelpers"
const createWorkspace = (
status: WorkspaceStatus,
@@ -71,35 +69,21 @@ const MockedAppearance = {
save: () => null,
}
const mockMenu = {
initialOption: undefined,
isInitializing: false,
isSearching: false,
query: "",
searchOptions: [],
selectedOption: undefined,
selectOption: action("selectOption"),
setQuery: action("updateQuery"),
}
type FilterProps = ComponentProps<typeof WorkspacesPageView>["filterProps"]
const defaultFilterProps = {
filter: {
query: `owner:me`,
update: () => action("update"),
debounceUpdate: action("debounce") as any,
used: false,
values: {
owner: MockUser.username,
template: undefined,
status: undefined,
},
},
const defaultFilterProps = getDefaultFilterProps<FilterProps>({
query: "owner:me",
menus: {
user: mockMenu,
template: mockMenu,
status: mockMenu,
user: MockMenu,
template: MockMenu,
status: MockMenu,
},
} as ComponentProps<typeof WorkspacesPageView>["filterProps"]
values: {
owner: MockUser.username,
template: undefined,
status: undefined,
},
})
const meta: Meta<typeof WorkspacesPageView> = {
title: "pages/WorkspacesPageView",
@@ -19,8 +19,6 @@ import { ImpendingDeletionBanner, Count } from "components/WorkspaceDeletion"
import { ErrorAlert } from "components/Alert/ErrorAlert"
import { WorkspacesFilter } from "./filter/filter"
import { hasError, isApiValidationError } from "api/errors"
import { workspaceFilterQuery } from "utils/filters"
import { SearchBarWithFilter } from "components/SearchBarWithFilter/SearchBarWithFilter"
import { PaginationStatus } from "components/PaginationStatus/PaginationStatus"
export const Language = {
@@ -32,24 +30,10 @@ export const Language = {
template: "Template",
}
const presetFilters = [
{ query: workspaceFilterQuery.me, name: Language.yourWorkspacesButton },
{ query: workspaceFilterQuery.all, name: Language.allWorkspacesButton },
{
query: workspaceFilterQuery.running,
name: Language.runningWorkspacesButton,
},
{
query: workspaceFilterQuery.failed,
name: "Failed workspaces",
},
]
export interface WorkspacesPageViewProps {
error: unknown
workspaces?: Workspace[]
count?: number
useNewFilter?: boolean
filterProps: ComponentProps<typeof WorkspacesFilter>
page: number
limit: number
@@ -67,7 +51,6 @@ export const WorkspacesPageView: FC<
filterProps,
onPageChange,
onUpdateWorkspace,
useNewFilter,
page,
}) => {
const { saveLocal, getLocal } = useLocalStorage()
@@ -133,16 +116,7 @@ export const WorkspacesPageView: FC<
count={Count.Multiple}
/>
{useNewFilter ? (
<WorkspacesFilter error={error} {...filterProps} />
) : (
<SearchBarWithFilter
filter={filterProps.filter.query}
onFilter={filterProps.filter.debounceUpdate}
presetFilters={presetFilters}
error={error}
/>
)}
<WorkspacesFilter error={error} {...filterProps} />
</Stack>
<PaginationStatus
-1
View File
@@ -1405,7 +1405,6 @@ export const MockEntitlementsWithScheduling: TypesGen.Entitlements = {
export const MockExperiments: TypesGen.Experiment[] = [
"workspace_actions",
"moons",
"workspace_filter",
]
export const MockAuditLog: TypesGen.AuditLog = {