mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
refactor: move dashboard functionality to modules/dashboard/ (#11721)
This commit is contained in:
+3
-4
@@ -170,10 +170,9 @@
|
||||
"vite-plugin-turbosnap": "1.0.2"
|
||||
},
|
||||
"browserslist": [
|
||||
"chrome 66",
|
||||
"firefox 63",
|
||||
"edge 79",
|
||||
"safari 15.4"
|
||||
"chrome 110",
|
||||
"firefox 111",
|
||||
"safari 16.0"
|
||||
],
|
||||
"resolutions": {
|
||||
"optionator": "0.9.3",
|
||||
|
||||
@@ -5,8 +5,8 @@ import {
|
||||
BrowserRouter as Router,
|
||||
Navigate,
|
||||
} from "react-router-dom";
|
||||
import { DashboardLayout } from "./modules/dashboard/DashboardLayout";
|
||||
import { RequireAuth } from "./contexts/auth/RequireAuth";
|
||||
import { DashboardLayout } from "./components/Dashboard/DashboardLayout";
|
||||
import { FullScreenLoader } from "./components/Loader/FullScreenLoader";
|
||||
import AuditPage from "./pages/AuditPage/AuditPage";
|
||||
import { DeploySettingsLayout } from "./pages/DeploySettingsPage/DeploySettingsLayout";
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { type FC } from "react";
|
||||
import type { Workspace } from "api/typesGenerated";
|
||||
import { displayDormantDeletion } from "utils/dormant";
|
||||
import { useDashboard } from "components/Dashboard/DashboardProvider";
|
||||
import { useDashboard } from "modules/dashboard/useDashboard";
|
||||
|
||||
interface DormantDeletionTextProps {
|
||||
workspace: Workspace;
|
||||
|
||||
@@ -15,7 +15,7 @@ import {
|
||||
MockAppearanceConfig,
|
||||
} from "testHelpers/entities";
|
||||
import { WorkspaceStatusBadge } from "./WorkspaceStatusBadge";
|
||||
import { DashboardProviderContext } from "components/Dashboard/DashboardProvider";
|
||||
import { DashboardContext } from "modules/dashboard/DashboardProvider";
|
||||
import type { Meta, StoryObj } from "@storybook/react";
|
||||
|
||||
const MockedAppearance = {
|
||||
@@ -29,7 +29,7 @@ const meta: Meta<typeof WorkspaceStatusBadge> = {
|
||||
component: WorkspaceStatusBadge,
|
||||
decorators: [
|
||||
(Story) => (
|
||||
<DashboardProviderContext.Provider
|
||||
<DashboardContext.Provider
|
||||
value={{
|
||||
buildInfo: MockBuildInfo,
|
||||
entitlements: MockEntitlementsWithScheduling,
|
||||
@@ -38,7 +38,7 @@ const meta: Meta<typeof WorkspaceStatusBadge> = {
|
||||
}}
|
||||
>
|
||||
<Story />
|
||||
</DashboardProviderContext.Provider>
|
||||
</DashboardContext.Provider>
|
||||
),
|
||||
],
|
||||
};
|
||||
|
||||
@@ -4,7 +4,7 @@ import { Outlet, Navigate, useLocation } from "react-router-dom";
|
||||
import { embedRedirect } from "utils/redirect";
|
||||
import { isApiError } from "api/errors";
|
||||
import { ProxyProvider } from "contexts/ProxyContext";
|
||||
import { DashboardProvider } from "components/Dashboard/DashboardProvider";
|
||||
import { DashboardProvider } from "modules/dashboard/DashboardProvider";
|
||||
import { FullScreenLoader } from "components/Loader/FullScreenLoader";
|
||||
import { useAuth } from "./useAuth";
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
export * from "./useClickable";
|
||||
export * from "./useClickableTableRow";
|
||||
export * from "./useClipboard";
|
||||
export * from "./useFeatureVisibility";
|
||||
export * from "./usePagination";
|
||||
export * from "./useTab";
|
||||
|
||||
+2
-2
@@ -4,10 +4,10 @@ import Button from "@mui/material/Button";
|
||||
import InfoOutlined from "@mui/icons-material/InfoOutlined";
|
||||
import { type FC, type HTMLAttributes, Suspense } from "react";
|
||||
import { Outlet } from "react-router-dom";
|
||||
import { LicenseBanner } from "modules/dashboard/LicenseBanner/LicenseBanner";
|
||||
import { ServiceBanner } from "modules/dashboard/ServiceBanner/ServiceBanner";
|
||||
import { usePermissions } from "contexts/auth/usePermissions";
|
||||
import { LicenseBanner } from "components/Dashboard/LicenseBanner/LicenseBanner";
|
||||
import { Loader } from "components/Loader/Loader";
|
||||
import { ServiceBanner } from "components/Dashboard/ServiceBanner/ServiceBanner";
|
||||
import { dashboardContentBottomPadding } from "theme/constants";
|
||||
import { docs } from "utils/docs";
|
||||
import { Navbar } from "./Navbar/Navbar";
|
||||
+6
-24
@@ -14,7 +14,6 @@ import {
|
||||
type PropsWithChildren,
|
||||
createContext,
|
||||
useCallback,
|
||||
useContext,
|
||||
useState,
|
||||
} from "react";
|
||||
import { appearance } from "api/queries/appearance";
|
||||
@@ -27,16 +26,16 @@ interface Appearance {
|
||||
setPreview: (config: AppearanceConfig) => void;
|
||||
}
|
||||
|
||||
interface DashboardProviderValue {
|
||||
export interface DashboardValue {
|
||||
buildInfo: BuildInfoResponse;
|
||||
entitlements: Entitlements;
|
||||
experiments: Experiments;
|
||||
appearance: Appearance;
|
||||
}
|
||||
|
||||
export const DashboardProviderContext = createContext<
|
||||
DashboardProviderValue | undefined
|
||||
>(undefined);
|
||||
export const DashboardContext = createContext<DashboardValue | undefined>(
|
||||
undefined,
|
||||
);
|
||||
|
||||
export const DashboardProvider: FC<PropsWithChildren> = ({ children }) => {
|
||||
const buildInfoQuery = useQuery(buildInfo());
|
||||
@@ -83,7 +82,7 @@ export const DashboardProvider: FC<PropsWithChildren> = ({ children }) => {
|
||||
}
|
||||
|
||||
return (
|
||||
<DashboardProviderContext.Provider
|
||||
<DashboardContext.Provider
|
||||
value={{
|
||||
buildInfo: buildInfoQuery.data,
|
||||
entitlements: entitlementsQuery.data,
|
||||
@@ -96,23 +95,6 @@ export const DashboardProvider: FC<PropsWithChildren> = ({ children }) => {
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</DashboardProviderContext.Provider>
|
||||
</DashboardContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export const useDashboard = (): DashboardProviderValue => {
|
||||
const context = useContext(DashboardProviderContext);
|
||||
|
||||
if (!context) {
|
||||
throw new Error(
|
||||
"useDashboard only can be used inside of DashboardProvider",
|
||||
);
|
||||
}
|
||||
|
||||
return context;
|
||||
};
|
||||
|
||||
export const useIsWorkspaceActionsEnabled = (): boolean => {
|
||||
const { entitlements } = useDashboard();
|
||||
return entitlements.features["advanced_template_scheduling"].enabled;
|
||||
};
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
import { type FC } from "react";
|
||||
import { useDashboard } from "components/Dashboard/DashboardProvider";
|
||||
import { useDashboard } from "modules/dashboard/useDashboard";
|
||||
import { LicenseBannerView } from "./LicenseBannerView";
|
||||
|
||||
export const LicenseBanner: FC = () => {
|
||||
+2
-2
@@ -3,8 +3,8 @@ import { useAuth } from "contexts/auth/useAuth";
|
||||
import { useMe } from "contexts/auth/useMe";
|
||||
import { usePermissions } from "contexts/auth/usePermissions";
|
||||
import { useProxy } from "contexts/ProxyContext";
|
||||
import { useDashboard } from "components/Dashboard/DashboardProvider";
|
||||
import { useFeatureVisibility } from "hooks/useFeatureVisibility";
|
||||
import { useDashboard } from "modules/dashboard/useDashboard";
|
||||
import { useFeatureVisibility } from "../useFeatureVisibility";
|
||||
import { NavbarView } from "./NavbarView";
|
||||
|
||||
export const Navbar: FC = () => {
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
import { type FC } from "react";
|
||||
import { useDashboard } from "components/Dashboard/DashboardProvider";
|
||||
import { useDashboard } from "modules/dashboard/useDashboard";
|
||||
import { ServiceBannerView } from "./ServiceBannerView";
|
||||
|
||||
export const ServiceBanner: FC = () => {
|
||||
@@ -0,0 +1,14 @@
|
||||
import { useContext } from "react";
|
||||
import { DashboardContext, type DashboardValue } from "./DashboardProvider";
|
||||
|
||||
export const useDashboard = (): DashboardValue => {
|
||||
const context = useContext(DashboardContext);
|
||||
|
||||
if (!context) {
|
||||
throw new Error(
|
||||
"useDashboard only can be used inside of DashboardProvider",
|
||||
);
|
||||
}
|
||||
|
||||
return context;
|
||||
};
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
import { FeatureName } from "api/typesGenerated";
|
||||
import { useDashboard } from "components/Dashboard/DashboardProvider";
|
||||
import { useDashboard } from "./useDashboard";
|
||||
import { selectFeatureVisibility } from "utils/entitlements";
|
||||
|
||||
export const useFeatureVisibility = (): Record<FeatureName, boolean> => {
|
||||
+2
-2
@@ -1,10 +1,10 @@
|
||||
import { act, renderHook, waitFor } from "@testing-library/react";
|
||||
import { useUpdateCheck } from "./useUpdateCheck";
|
||||
import { QueryClient, QueryClientProvider } from "react-query";
|
||||
import { type FC, type PropsWithChildren } from "react";
|
||||
import { QueryClient, QueryClientProvider } from "react-query";
|
||||
import { rest } from "msw";
|
||||
import { MockUpdateCheck } from "testHelpers/entities";
|
||||
import { server } from "testHelpers/server";
|
||||
import { useUpdateCheck } from "./useUpdateCheck";
|
||||
|
||||
const createWrapper = (): FC<PropsWithChildren> => {
|
||||
const queryClient = new QueryClient();
|
||||
@@ -1,15 +1,15 @@
|
||||
import { isNonInitialPage } from "components/PaginationWidget/utils";
|
||||
import { useFeatureVisibility } from "hooks/useFeatureVisibility";
|
||||
import { FC } from "react";
|
||||
import { type FC } from "react";
|
||||
import { Helmet } from "react-helmet-async";
|
||||
import { useSearchParams } from "react-router-dom";
|
||||
import { useFeatureVisibility } from "modules/dashboard/useFeatureVisibility";
|
||||
import { pageTitle } from "utils/page";
|
||||
import { AuditPageView } from "./AuditPageView";
|
||||
import { paginatedAudits } from "api/queries/audits";
|
||||
import { usePaginatedQuery } from "hooks/usePaginatedQuery";
|
||||
import { useUserFilterMenu } from "components/Filter/UserFilter";
|
||||
import { isNonInitialPage } from "components/PaginationWidget/utils";
|
||||
import { useFilter } from "components/Filter/filter";
|
||||
import { useActionFilterMenu, useResourceTypeFilterMenu } from "./AuditFilter";
|
||||
import { usePaginatedQuery } from "hooks/usePaginatedQuery";
|
||||
import { paginatedAudits } from "api/queries/audits";
|
||||
import { AuditPageView } from "./AuditPageView";
|
||||
|
||||
const AuditPage: FC = () => {
|
||||
const { audit_log: isAuditLogVisible } = useFeatureVisibility();
|
||||
|
||||
@@ -10,9 +10,9 @@ import {
|
||||
createTemplate,
|
||||
} from "api/queries/templates";
|
||||
import { useOrganizationId } from "contexts/auth/useOrganizationId";
|
||||
import { useDashboard } from "modules/dashboard/useDashboard";
|
||||
import { ErrorAlert } from "components/Alert/ErrorAlert";
|
||||
import { Loader } from "components/Loader/Loader";
|
||||
import { useDashboard } from "components/Dashboard/DashboardProvider";
|
||||
import { CreateTemplateForm } from "./CreateTemplateForm";
|
||||
import { firstVersionFromFile, getFormPermissions, newTemplate } from "./utils";
|
||||
|
||||
|
||||
@@ -9,9 +9,9 @@ import {
|
||||
templateVersionVariables,
|
||||
} from "api/queries/templates";
|
||||
import { useOrganizationId } from "contexts/auth/useOrganizationId";
|
||||
import { useDashboard } from "modules/dashboard/useDashboard";
|
||||
import { ErrorAlert } from "components/Alert/ErrorAlert";
|
||||
import { Loader } from "components/Loader/Loader";
|
||||
import { useDashboard } from "components/Dashboard/DashboardProvider";
|
||||
import { CreateTemplateForm } from "./CreateTemplateForm";
|
||||
import {
|
||||
firstVersionFromExample,
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
} from "api/queries/templates";
|
||||
import { uploadFile } from "api/queries/files";
|
||||
import { useOrganizationId } from "contexts/auth/useOrganizationId";
|
||||
import { useDashboard } from "components/Dashboard/DashboardProvider";
|
||||
import { useDashboard } from "modules/dashboard/useDashboard";
|
||||
import { CreateTemplateForm } from "./CreateTemplateForm";
|
||||
import { firstVersionFromFile, getFormPermissions, newTemplate } from "./utils";
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { UpdateAppearanceConfig } from "api/typesGenerated";
|
||||
import { useDashboard } from "components/Dashboard/DashboardProvider";
|
||||
import { FC } from "react";
|
||||
import { type FC } from "react";
|
||||
import { Helmet } from "react-helmet-async";
|
||||
import { pageTitle } from "utils/page";
|
||||
import { AppearanceSettingsPageView } from "./AppearanceSettingsPageView";
|
||||
import { useMutation, useQueryClient } from "react-query";
|
||||
import type { UpdateAppearanceConfig } from "api/typesGenerated";
|
||||
import { useDashboard } from "modules/dashboard/useDashboard";
|
||||
import { pageTitle } from "utils/page";
|
||||
import { updateAppearance } from "api/queries/appearance";
|
||||
import { getErrorMessage } from "api/errors";
|
||||
import { displayError, displaySuccess } from "components/GlobalSnackbar/utils";
|
||||
import { AppearanceSettingsPageView } from "./AppearanceSettingsPageView";
|
||||
|
||||
// ServiceBanner is unlike the other Deployment Settings pages because it
|
||||
// implements a form, whereas the others are read-only. We make this
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { type FC } from "react";
|
||||
import { Helmet } from "react-helmet-async";
|
||||
import { useQuery } from "react-query";
|
||||
import { getApps } from "api/queries/oauth2";
|
||||
import { useDashboard } from "components/Dashboard/DashboardProvider";
|
||||
import { FC } from "react";
|
||||
import { Helmet } from "react-helmet-async";
|
||||
import { useDashboard } from "modules/dashboard/useDashboard";
|
||||
import { pageTitle } from "utils/page";
|
||||
import OAuth2AppsSettingsPageView from "./OAuth2AppsSettingsPageView";
|
||||
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
import { type FC } from "react";
|
||||
import { Helmet } from "react-helmet-async";
|
||||
import { pageTitle } from "utils/page";
|
||||
import { useDashboard } from "components/Dashboard/DashboardProvider";
|
||||
import { useDashboard } from "modules/dashboard/useDashboard";
|
||||
import { useDeploySettings } from "../DeploySettingsLayout";
|
||||
import { ObservabilitySettingsPageView } from "./ObservabilitySettingsPageView";
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { type FC } from "react";
|
||||
import { Helmet } from "react-helmet-async";
|
||||
import { pageTitle } from "utils/page";
|
||||
import { useDashboard } from "components/Dashboard/DashboardProvider";
|
||||
import { useDashboard } from "modules/dashboard/useDashboard";
|
||||
import { SecuritySettingsPageView } from "./SecuritySettingsPageView";
|
||||
import { useDeploySettings } from "../DeploySettingsLayout";
|
||||
|
||||
|
||||
@@ -5,9 +5,9 @@ import { getErrorMessage } from "api/errors";
|
||||
import { groups } from "api/queries/groups";
|
||||
import { useOrganizationId } from "contexts/auth/useOrganizationId";
|
||||
import { usePermissions } from "contexts/auth/usePermissions";
|
||||
import { useFeatureVisibility } from "hooks/useFeatureVisibility";
|
||||
import { pageTitle } from "utils/page";
|
||||
import { useFeatureVisibility } from "modules/dashboard/useFeatureVisibility";
|
||||
import { displayError } from "components/GlobalSnackbar/utils";
|
||||
import { pageTitle } from "utils/page";
|
||||
import GroupsPageView from "./GroupsPageView";
|
||||
|
||||
export const GroupsPage: FC = () => {
|
||||
|
||||
@@ -13,4 +13,6 @@ const meta: Meta = {
|
||||
export default meta;
|
||||
type Story = StoryObj;
|
||||
|
||||
export const Default: Story = {};
|
||||
const Example: Story = {};
|
||||
|
||||
export { Example as AccessURL };
|
||||
|
||||
@@ -13,4 +13,6 @@ const meta: Meta = {
|
||||
export default meta;
|
||||
type Story = StoryObj;
|
||||
|
||||
export const Default: Story = {};
|
||||
const Example: Story = {};
|
||||
|
||||
export { Example as DERP };
|
||||
|
||||
@@ -18,4 +18,6 @@ const meta: Meta = {
|
||||
export default meta;
|
||||
type Story = StoryObj;
|
||||
|
||||
export const Default: Story = {};
|
||||
const Example: Story = {};
|
||||
|
||||
export { Example as DERPRegion };
|
||||
|
||||
@@ -13,4 +13,6 @@ const meta: Meta = {
|
||||
export default meta;
|
||||
type Story = StoryObj;
|
||||
|
||||
export const Default: Story = {};
|
||||
const Example: Story = {};
|
||||
|
||||
export { Example as Database };
|
||||
|
||||
@@ -1,24 +1,25 @@
|
||||
import { useMutation, useQuery, useQueryClient } from "react-query";
|
||||
import { Loader } from "components/Loader/Loader";
|
||||
import { Helmet } from "react-helmet-async";
|
||||
import { pageTitle } from "utils/page";
|
||||
import { createDayString } from "utils/createDayString";
|
||||
import { DashboardFullPage } from "components/Dashboard/DashboardLayout";
|
||||
import ReplayIcon from "@mui/icons-material/Replay";
|
||||
import { health, refreshHealth } from "api/queries/debug";
|
||||
import { useTheme } from "@mui/material/styles";
|
||||
import IconButton from "@mui/material/IconButton";
|
||||
import Tooltip from "@mui/material/Tooltip";
|
||||
import CircularProgress from "@mui/material/CircularProgress";
|
||||
import { NavLink, Outlet } from "react-router-dom";
|
||||
import { css } from "@emotion/css";
|
||||
import kebabCase from "lodash/fp/kebabCase";
|
||||
import { Suspense } from "react";
|
||||
import { HealthIcon } from "./Content";
|
||||
import { HealthSeverity } from "api/typesGenerated";
|
||||
import ReplayIcon from "@mui/icons-material/Replay";
|
||||
import NotificationsOffOutlined from "@mui/icons-material/NotificationsOffOutlined";
|
||||
import { cx } from "@emotion/css";
|
||||
import { useTheme } from "@emotion/react";
|
||||
import { type FC, Suspense } from "react";
|
||||
import { Helmet } from "react-helmet-async";
|
||||
import { useMutation, useQuery, useQueryClient } from "react-query";
|
||||
import { NavLink, Outlet } from "react-router-dom";
|
||||
import kebabCase from "lodash/fp/kebabCase";
|
||||
import { health, refreshHealth } from "api/queries/debug";
|
||||
import type { HealthSeverity } from "api/typesGenerated";
|
||||
import { type ClassName, useClassName } from "hooks/useClassName";
|
||||
import { pageTitle } from "utils/page";
|
||||
import { createDayString } from "utils/createDayString";
|
||||
import { DashboardFullPage } from "modules/dashboard/DashboardLayout";
|
||||
import { Loader } from "components/Loader/Loader";
|
||||
import { HealthIcon } from "./Content";
|
||||
|
||||
export function HealthLayout() {
|
||||
export const HealthLayout: FC = () => {
|
||||
const theme = useTheme();
|
||||
const queryClient = useQueryClient();
|
||||
const { data: healthStatus } = useQuery({
|
||||
@@ -38,6 +39,9 @@ export function HealthLayout() {
|
||||
} as const;
|
||||
const visibleSections = filterVisibleSections(sections);
|
||||
|
||||
const link = useClassName(classNames.link, []);
|
||||
const activeLink = useClassName(classNames.activeLink, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Helmet>
|
||||
@@ -162,31 +166,7 @@ export function HealthLayout() {
|
||||
key={key}
|
||||
to={`/health/${kebabCase(key)}`}
|
||||
className={({ isActive }) =>
|
||||
css({
|
||||
background: isActive
|
||||
? theme.palette.action.hover
|
||||
: "none",
|
||||
pointerEvents: isActive ? "none" : "auto",
|
||||
color: isActive
|
||||
? theme.palette.text.primary
|
||||
: theme.palette.text.secondary,
|
||||
border: "none",
|
||||
fontSize: 14,
|
||||
width: "100%",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
gap: 12,
|
||||
textAlign: "left",
|
||||
height: 36,
|
||||
padding: "0 24px",
|
||||
cursor: "pointer",
|
||||
textDecoration: "none",
|
||||
|
||||
"&:hover": {
|
||||
background: theme.palette.action.hover,
|
||||
color: theme.palette.text.primary,
|
||||
},
|
||||
})
|
||||
cx([link, isActive && activeLink])
|
||||
}
|
||||
>
|
||||
<HealthIcon
|
||||
@@ -221,7 +201,7 @@ export function HealthLayout() {
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const filterVisibleSections = <T extends object>(sections: T) => {
|
||||
return Object.keys(sections).reduce(
|
||||
@@ -240,3 +220,35 @@ const filterVisibleSections = <T extends object>(sections: T) => {
|
||||
{} as Partial<typeof sections>,
|
||||
);
|
||||
};
|
||||
|
||||
const classNames = {
|
||||
link: (css, theme) =>
|
||||
css({
|
||||
background: "none",
|
||||
pointerEvents: "auto",
|
||||
color: theme.palette.text.secondary,
|
||||
border: "none",
|
||||
fontSize: 14,
|
||||
width: "100%",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
gap: 12,
|
||||
textAlign: "left",
|
||||
height: 36,
|
||||
padding: "0 24px",
|
||||
cursor: "pointer",
|
||||
textDecoration: "none",
|
||||
|
||||
"&:hover": {
|
||||
background: theme.palette.action.hover,
|
||||
color: theme.palette.text.primary,
|
||||
},
|
||||
}),
|
||||
|
||||
activeLink: (css, theme) =>
|
||||
css({
|
||||
background: theme.palette.action.hover,
|
||||
pointerEvents: "none",
|
||||
color: theme.palette.text.primary,
|
||||
}),
|
||||
} satisfies Record<string, ClassName>;
|
||||
|
||||
@@ -13,4 +13,6 @@ const meta: Meta = {
|
||||
export default meta;
|
||||
type Story = StoryObj;
|
||||
|
||||
export const Default: Story = {};
|
||||
const Example: Story = {};
|
||||
|
||||
export { Example as ProvisionerDaemons };
|
||||
|
||||
@@ -13,4 +13,6 @@ const meta: Meta = {
|
||||
export default meta;
|
||||
type Story = StoryObj;
|
||||
|
||||
export const Default: Story = {};
|
||||
const Example: Story = {};
|
||||
|
||||
export { Example as Websocket };
|
||||
|
||||
@@ -13,4 +13,6 @@ const meta: Meta = {
|
||||
export default meta;
|
||||
type Story = StoryObj;
|
||||
|
||||
export const Default: Story = {};
|
||||
const Example: Story = {};
|
||||
|
||||
export { Example as WorkspaceProxy };
|
||||
|
||||
@@ -14,7 +14,7 @@ import {
|
||||
MockHealthSettings,
|
||||
} from "testHelpers/entities";
|
||||
import { HEALTH_QUERY_KEY, HEALTH_QUERY_SETTINGS_KEY } from "api/queries/debug";
|
||||
import { DashboardProvider } from "components/Dashboard/DashboardProvider";
|
||||
import { DashboardProvider } from "modules/dashboard/DashboardProvider";
|
||||
import { HealthLayout } from "./HealthLayout";
|
||||
|
||||
type MetaOptions = {
|
||||
@@ -25,7 +25,7 @@ type MetaOptions = {
|
||||
|
||||
export const generateMeta = ({ element, path, params }: MetaOptions): Meta => {
|
||||
return {
|
||||
render: HealthLayout,
|
||||
component: HealthLayout,
|
||||
parameters: {
|
||||
chromatic,
|
||||
layout: "fullscreen",
|
||||
|
||||
+2
-2
@@ -2,12 +2,12 @@ import { type FC } from "react";
|
||||
import { Helmet } from "react-helmet-async";
|
||||
import { useMutation, useQueryClient } from "react-query";
|
||||
import { useNavigate, useParams } from "react-router-dom";
|
||||
import { pageTitle } from "utils/page";
|
||||
import { updateTemplateMeta } from "api/api";
|
||||
import type { UpdateTemplateMeta } from "api/typesGenerated";
|
||||
import { templateByNameKey } from "api/queries/templates";
|
||||
import { useOrganizationId } from "contexts/auth/useOrganizationId";
|
||||
import { useDashboard } from "components/Dashboard/DashboardProvider";
|
||||
import { useDashboard } from "modules/dashboard/useDashboard";
|
||||
import { pageTitle } from "utils/page";
|
||||
import { displaySuccess } from "components/GlobalSnackbar/utils";
|
||||
import { useTemplateSettings } from "../TemplateSettingsLayout";
|
||||
import { TemplateSettingsPageView } from "./TemplateSettingsPageView";
|
||||
|
||||
+2
-4
@@ -8,16 +8,14 @@ import { setGroupRole, setUserRole, templateACL } from "api/queries/templates";
|
||||
import { Paywall } from "components/Paywall/Paywall";
|
||||
import { Stack } from "components/Stack/Stack";
|
||||
import { displaySuccess } from "components/GlobalSnackbar/utils";
|
||||
import { useFeatureVisibility } from "hooks/useFeatureVisibility";
|
||||
import { useOrganizationId } from "contexts/auth/useOrganizationId";
|
||||
import { useFeatureVisibility } from "modules/dashboard/useFeatureVisibility";
|
||||
import { pageTitle } from "utils/page";
|
||||
import { docs } from "utils/docs";
|
||||
import { useTemplateSettings } from "../TemplateSettingsLayout";
|
||||
import { TemplatePermissionsPageView } from "./TemplatePermissionsPageView";
|
||||
|
||||
export const TemplatePermissionsPage: FC<
|
||||
React.PropsWithChildren<unknown>
|
||||
> = () => {
|
||||
export const TemplatePermissionsPage: FC = () => {
|
||||
const organizationId = useOrganizationId();
|
||||
const { template, permissions } = useTemplateSettings();
|
||||
const { template_rbac: isTemplateRBACEnabled } = useFeatureVisibility();
|
||||
|
||||
@@ -2,12 +2,12 @@ import { type FC } from "react";
|
||||
import { Helmet } from "react-helmet-async";
|
||||
import { useMutation, useQueryClient } from "react-query";
|
||||
import { useNavigate, useParams } from "react-router-dom";
|
||||
import { pageTitle } from "utils/page";
|
||||
import { updateTemplateMeta } from "api/api";
|
||||
import type { UpdateTemplateMeta } from "api/typesGenerated";
|
||||
import { templateByNameKey } from "api/queries/templates";
|
||||
import { useOrganizationId } from "contexts/auth/useOrganizationId";
|
||||
import { useDashboard } from "components/Dashboard/DashboardProvider";
|
||||
import { useDashboard } from "modules/dashboard/useDashboard";
|
||||
import { pageTitle } from "utils/page";
|
||||
import { displaySuccess } from "components/GlobalSnackbar/utils";
|
||||
import { useTemplateSettings } from "../TemplateSettingsLayout";
|
||||
import { TemplateSchedulePageView } from "./TemplateSchedulePageView";
|
||||
|
||||
@@ -5,7 +5,7 @@ import { useAuth } from "contexts/auth/useAuth";
|
||||
import { useMe } from "contexts/auth/useMe";
|
||||
import { useOrganizationId } from "contexts/auth/useOrganizationId";
|
||||
import { usePermissions } from "contexts/auth/usePermissions";
|
||||
import { useDashboard } from "components/Dashboard/DashboardProvider";
|
||||
import { useDashboard } from "modules/dashboard/useDashboard";
|
||||
import { Stack } from "components/Stack/Stack";
|
||||
import { Section } from "../Section";
|
||||
import { AccountUserGroups } from "./AccountUserGroups";
|
||||
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
SidebarNavItem,
|
||||
} from "components/Sidebar/Sidebar";
|
||||
import { GitIcon } from "components/Icons/GitIcon";
|
||||
import { useDashboard } from "components/Dashboard/DashboardProvider";
|
||||
import { useDashboard } from "modules/dashboard/useDashboard";
|
||||
|
||||
interface SidebarProps {
|
||||
user: User;
|
||||
|
||||
@@ -4,10 +4,10 @@ import GroupAdd from "@mui/icons-material/GroupAddOutlined";
|
||||
import PersonAdd from "@mui/icons-material/PersonAddOutlined";
|
||||
import { type FC, Suspense } from "react";
|
||||
import { Link as RouterLink, Outlet, useNavigate } from "react-router-dom";
|
||||
import { USERS_LINK } from "components/Dashboard/Navbar/NavbarView";
|
||||
import { PageHeader, PageHeaderTitle } from "components/PageHeader/PageHeader";
|
||||
import { useFeatureVisibility } from "hooks/useFeatureVisibility";
|
||||
import { usePermissions } from "contexts/auth/usePermissions";
|
||||
import { USERS_LINK } from "modules/dashboard/Navbar/NavbarView";
|
||||
import { useFeatureVisibility } from "modules/dashboard/useFeatureVisibility";
|
||||
import { PageHeader, PageHeaderTitle } from "components/PageHeader/PageHeader";
|
||||
import { Margins } from "components/Margins/Margins";
|
||||
import { TabLink, Tabs } from "components/Tabs/Tabs";
|
||||
import { Loader } from "components/Loader/Loader";
|
||||
|
||||
@@ -2,7 +2,7 @@ import { type FC, useState } from "react";
|
||||
import { Helmet } from "react-helmet-async";
|
||||
import { useMutation, useQuery, useQueryClient } from "react-query";
|
||||
import { useSearchParams, useNavigate } from "react-router-dom";
|
||||
import { type User } from "api/typesGenerated";
|
||||
import type { User } from "api/typesGenerated";
|
||||
import { roles } from "api/queries/roles";
|
||||
import { groupsByUserId } from "api/queries/groups";
|
||||
import { getErrorMessage } from "api/errors";
|
||||
@@ -17,10 +17,10 @@ import {
|
||||
authMethods,
|
||||
} from "api/queries/users";
|
||||
import { useOrganizationId } from "contexts/auth/useOrganizationId";
|
||||
import { useMe } from "contexts/auth/useMe";
|
||||
import { usePermissions } from "contexts/auth/usePermissions";
|
||||
import { useMe } from "contexts/auth/useMe";
|
||||
import { useDashboard } from "modules/dashboard/useDashboard";
|
||||
import { useFilter } from "components/Filter/filter";
|
||||
import { useDashboard } from "components/Dashboard/DashboardProvider";
|
||||
import { DeleteDialog } from "components/Dialogs/DeleteDialog/DeleteDialog";
|
||||
import { ConfirmDialog } from "components/Dialogs/ConfirmDialog/ConfirmDialog";
|
||||
import { displayError, displaySuccess } from "components/GlobalSnackbar/utils";
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import { type Interpolation, type Theme, useTheme } from "@emotion/react";
|
||||
import { BuildAvatar } from "components/BuildAvatar/BuildAvatar";
|
||||
import { type FC } from "react";
|
||||
import { ProvisionerJobLog, WorkspaceBuild } from "api/typesGenerated";
|
||||
import type { ProvisionerJobLog, WorkspaceBuild } from "api/typesGenerated";
|
||||
import { Link } from "react-router-dom";
|
||||
import { displayWorkspaceBuildDuration } from "utils/workspace";
|
||||
import { DashboardFullPage } from "modules/dashboard/DashboardLayout";
|
||||
import { BuildAvatar } from "components/BuildAvatar/BuildAvatar";
|
||||
import { Loader } from "components/Loader/Loader";
|
||||
import { Stack } from "components/Stack/Stack";
|
||||
import { WorkspaceBuildLogs } from "components/WorkspaceBuildLogs/WorkspaceBuildLogs";
|
||||
@@ -10,16 +13,13 @@ import {
|
||||
PageHeaderTitle,
|
||||
PageHeaderSubtitle,
|
||||
} from "components/PageHeader/FullWidthPageHeader";
|
||||
import { Link } from "react-router-dom";
|
||||
import { Stats, StatsItem } from "components/Stats/Stats";
|
||||
import { displayWorkspaceBuildDuration } from "utils/workspace";
|
||||
import { Sidebar, SidebarCaption, SidebarItem } from "./Sidebar";
|
||||
import { Alert } from "components/Alert/Alert";
|
||||
import { DashboardFullPage } from "components/Dashboard/DashboardLayout";
|
||||
import {
|
||||
WorkspaceBuildData,
|
||||
WorkspaceBuildDataSkeleton,
|
||||
} from "components/WorkspaceBuild/WorkspaceBuildData";
|
||||
import { Sidebar, SidebarCaption, SidebarItem } from "./Sidebar";
|
||||
|
||||
const sortLogsByCreatedAt = (logs: ProvisionerJobLog[]) => {
|
||||
return [...logs].sort(
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { action } from "@storybook/addon-actions";
|
||||
import { Meta, StoryObj } from "@storybook/react";
|
||||
import { WatchAgentMetadataContext } from "components/Resources/AgentMetadata";
|
||||
import { ProvisionerJobLog } from "api/typesGenerated";
|
||||
import * as Mocks from "testHelpers/entities";
|
||||
import { Workspace } from "./Workspace";
|
||||
import { withReactContext } from "storybook-react-context";
|
||||
import EventSource from "eventsourcemock";
|
||||
import { withReactContext } from "storybook-react-context";
|
||||
import type { ProvisionerJobLog } from "api/typesGenerated";
|
||||
import * as Mocks from "testHelpers/entities";
|
||||
import { ProxyContext, getPreferredProxy } from "contexts/ProxyContext";
|
||||
import { DashboardProviderContext } from "components/Dashboard/DashboardProvider";
|
||||
import { WorkspaceBuildLogsSection } from "pages/WorkspacePage/WorkspaceBuildLogsSection";
|
||||
import { DashboardContext } from "modules/dashboard/DashboardProvider";
|
||||
import { WatchAgentMetadataContext } from "components/Resources/AgentMetadata";
|
||||
import { Workspace } from "./Workspace";
|
||||
import { WorkspaceBuildLogsSection } from "./WorkspaceBuildLogsSection";
|
||||
import { WorkspacePermissions } from "./permissions";
|
||||
|
||||
const MockedAppearance = {
|
||||
@@ -38,7 +38,7 @@ const meta: Meta<typeof Workspace> = {
|
||||
},
|
||||
decorators: [
|
||||
(Story) => (
|
||||
<DashboardProviderContext.Provider
|
||||
<DashboardContext.Provider
|
||||
value={{
|
||||
buildInfo: Mocks.MockBuildInfo,
|
||||
entitlements: Mocks.MockEntitlementsWithScheduling,
|
||||
@@ -66,7 +66,7 @@ const meta: Meta<typeof Workspace> = {
|
||||
>
|
||||
<Story />
|
||||
</ProxyContext.Provider>
|
||||
</DashboardProviderContext.Provider>
|
||||
</DashboardContext.Provider>
|
||||
),
|
||||
withReactContext({
|
||||
Context: WatchAgentMetadataContext,
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
import { workspaceResolveAutostart } from "api/queries/workspaceQuota";
|
||||
import { Template, TemplateVersion, Workspace } from "api/typesGenerated";
|
||||
import { FC, useEffect, useState } from "react";
|
||||
import { type Interpolation, type Theme } from "@emotion/react";
|
||||
import { type FC, useEffect, useState } from "react";
|
||||
import { useQuery } from "react-query";
|
||||
import { WorkspacePermissions } from "../permissions";
|
||||
import dayjs from "dayjs";
|
||||
import { useIsWorkspaceActionsEnabled } from "components/Dashboard/DashboardProvider";
|
||||
import { useDashboard } from "modules/dashboard/useDashboard";
|
||||
import formatDistanceToNow from "date-fns/formatDistanceToNow";
|
||||
import InfoOutlined from "@mui/icons-material/InfoOutlined";
|
||||
import WarningRounded from "@mui/icons-material/WarningRounded";
|
||||
import { MemoizedInlineMarkdown } from "components/Markdown/Markdown";
|
||||
import type { WorkspacePermissions } from "../permissions";
|
||||
import {
|
||||
NotificationActionButton,
|
||||
NotificationItem,
|
||||
Notifications,
|
||||
} from "./Notifications";
|
||||
import { Interpolation, Theme } from "@emotion/react";
|
||||
|
||||
type WorkspaceNotificationsProps = {
|
||||
workspace: Workspace;
|
||||
@@ -103,8 +103,10 @@ export const WorkspaceNotifications: FC<WorkspaceNotificationsProps> = ({
|
||||
}
|
||||
|
||||
// Dormant
|
||||
const areActionsEnabled = useIsWorkspaceActionsEnabled();
|
||||
if (areActionsEnabled && workspace.dormant_at) {
|
||||
const { entitlements } = useDashboard();
|
||||
const advancedSchedulingEnabled =
|
||||
entitlements.features["advanced_template_scheduling"].enabled;
|
||||
if (advancedSchedulingEnabled && workspace.dormant_at) {
|
||||
const formatDate = (dateStr: string, timestamp: boolean): string => {
|
||||
const date = new Date(dateStr);
|
||||
return date.toLocaleDateString(undefined, {
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
import { type FC, useEffect } from "react";
|
||||
import { useQuery, useQueryClient } from "react-query";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { useEffectEvent } from "hooks/hookPolyfills";
|
||||
import { useOrganizationId } from "contexts/auth/useOrganizationId";
|
||||
import { watchWorkspace } from "api/api";
|
||||
import type { Workspace } from "api/typesGenerated";
|
||||
import { workspaceBuildsKey } from "api/queries/workspaceBuilds";
|
||||
import { templateByName } from "api/queries/templates";
|
||||
import { workspaceByOwnerAndName } from "api/queries/workspaces";
|
||||
import { checkAuthorization } from "api/queries/authCheck";
|
||||
import { useEffectEvent } from "hooks/hookPolyfills";
|
||||
import { useOrganizationId } from "contexts/auth/useOrganizationId";
|
||||
import { Navbar } from "modules/dashboard/Navbar/Navbar";
|
||||
import { ErrorAlert } from "components/Alert/ErrorAlert";
|
||||
import { Loader } from "components/Loader/Loader";
|
||||
import { Margins } from "components/Margins/Margins";
|
||||
import { Navbar } from "components/Dashboard/Navbar/Navbar";
|
||||
import { WorkspacePermissions, workspaceChecks } from "./permissions";
|
||||
import { WorkspaceReadyPage } from "./WorkspaceReadyPage";
|
||||
|
||||
|
||||
@@ -4,21 +4,15 @@ import { Helmet } from "react-helmet-async";
|
||||
import { useMutation, useQuery, useQueryClient } from "react-query";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { MissingBuildParameters, restartWorkspace } from "api/api";
|
||||
import { useFeatureVisibility } from "hooks/useFeatureVisibility";
|
||||
import { pageTitle } from "utils/page";
|
||||
import { getErrorMessage } from "api/errors";
|
||||
import type * as TypesGen from "api/typesGenerated";
|
||||
import { templateVersion, templateVersions } from "api/queries/templates";
|
||||
import { deploymentConfig, deploymentSSHConfig } from "api/queries/deployment";
|
||||
import { useDashboard } from "components/Dashboard/DashboardProvider";
|
||||
import {
|
||||
ConfirmDialog,
|
||||
ConfirmDialogProps,
|
||||
} from "components/Dialogs/ConfirmDialog/ConfirmDialog";
|
||||
import { Alert } from "components/Alert/Alert";
|
||||
import { Stack } from "components/Stack/Stack";
|
||||
import { useMe } from "contexts/auth/useMe";
|
||||
import { useWorkspaceBuildLogs } from "hooks/useWorkspaceBuildLogs";
|
||||
import { useDashboard } from "modules/dashboard/useDashboard";
|
||||
import { useFeatureVisibility } from "modules/dashboard/useFeatureVisibility";
|
||||
import { pageTitle } from "utils/page";
|
||||
import {
|
||||
activate,
|
||||
changeVersion,
|
||||
@@ -28,9 +22,15 @@ import {
|
||||
startWorkspace,
|
||||
cancelBuild,
|
||||
} from "api/queries/workspaces";
|
||||
import { Alert } from "components/Alert/Alert";
|
||||
import { Stack } from "components/Stack/Stack";
|
||||
import {
|
||||
ConfirmDialog,
|
||||
ConfirmDialogProps,
|
||||
} from "components/Dialogs/ConfirmDialog/ConfirmDialog";
|
||||
import { displayError } from "components/GlobalSnackbar/utils";
|
||||
import { WorkspacePermissions } from "./permissions";
|
||||
import { ChangeVersionDialog } from "./ChangeVersionDialog";
|
||||
import { WorkspacePermissions } from "./permissions";
|
||||
import { UpdateBuildParametersDialog } from "./UpdateBuildParametersDialog";
|
||||
import { Workspace } from "./Workspace";
|
||||
import { WorkspaceBuildLogsSection } from "./WorkspaceBuildLogsSection";
|
||||
|
||||
@@ -1,6 +1,15 @@
|
||||
import Tooltip from "@mui/material/Tooltip";
|
||||
import Link from "@mui/material/Link";
|
||||
import MonetizationOnOutlined from "@mui/icons-material/MonetizationOnOutlined";
|
||||
import DeleteOutline from "@mui/icons-material/DeleteOutline";
|
||||
import PersonOutline from "@mui/icons-material/PersonOutline";
|
||||
import ArrowBackOutlined from "@mui/icons-material/ArrowBackOutlined";
|
||||
import ScheduleOutlined from "@mui/icons-material/ScheduleOutlined";
|
||||
import { useTheme } from "@emotion/react";
|
||||
import { type FC } from "react";
|
||||
import { useQuery } from "react-query";
|
||||
import { Link as RouterLink } from "react-router-dom";
|
||||
import type * as TypesGen from "api/typesGenerated";
|
||||
import { WorkspaceActions } from "pages/WorkspacePage/WorkspaceActions/WorkspaceActions";
|
||||
import {
|
||||
Topbar,
|
||||
TopbarAvatar,
|
||||
@@ -9,27 +18,19 @@ import {
|
||||
TopbarIcon,
|
||||
TopbarIconButton,
|
||||
} from "components/FullPageLayout/Topbar";
|
||||
import Tooltip from "@mui/material/Tooltip";
|
||||
import ArrowBackOutlined from "@mui/icons-material/ArrowBackOutlined";
|
||||
import ScheduleOutlined from "@mui/icons-material/ScheduleOutlined";
|
||||
import { WorkspaceStatusBadge } from "components/WorkspaceStatusBadge/WorkspaceStatusBadge";
|
||||
import {
|
||||
WorkspaceScheduleControls,
|
||||
shouldDisplayScheduleControls,
|
||||
} from "./WorkspaceScheduleControls";
|
||||
import { workspaceQuota } from "api/queries/workspaceQuota";
|
||||
import { useQuery } from "react-query";
|
||||
import MonetizationOnOutlined from "@mui/icons-material/MonetizationOnOutlined";
|
||||
import { useTheme } from "@mui/material/styles";
|
||||
import Link from "@mui/material/Link";
|
||||
import { useDashboard } from "components/Dashboard/DashboardProvider";
|
||||
import { useDashboard } from "modules/dashboard/useDashboard";
|
||||
import { displayDormantDeletion } from "utils/dormant";
|
||||
import DeleteOutline from "@mui/icons-material/DeleteOutline";
|
||||
import PersonOutline from "@mui/icons-material/PersonOutline";
|
||||
import { Popover, PopoverTrigger } from "components/Popover/Popover";
|
||||
import { HelpTooltipContent } from "components/HelpTooltip/HelpTooltip";
|
||||
import { AvatarData } from "components/AvatarData/AvatarData";
|
||||
import { ExternalAvatar } from "components/Avatar/Avatar";
|
||||
import { WorkspaceActions } from "./WorkspaceActions/WorkspaceActions";
|
||||
import { WorkspaceNotifications } from "./WorkspaceNotifications/WorkspaceNotifications";
|
||||
import { WorkspacePermissions } from "./permissions";
|
||||
|
||||
@@ -64,30 +65,29 @@ export interface WorkspaceProps {
|
||||
latestVersion?: TypesGen.TemplateVersion;
|
||||
}
|
||||
|
||||
export const WorkspaceTopbar = (props: WorkspaceProps) => {
|
||||
const {
|
||||
handleStart,
|
||||
handleStop,
|
||||
handleRestart,
|
||||
handleDelete,
|
||||
handleUpdate,
|
||||
handleCancel,
|
||||
handleSettings,
|
||||
handleChangeVersion,
|
||||
handleDormantActivate,
|
||||
workspace,
|
||||
isUpdating,
|
||||
isRestarting,
|
||||
canUpdateWorkspace,
|
||||
canChangeVersions,
|
||||
canRetryDebugMode,
|
||||
handleBuildRetry,
|
||||
handleBuildRetryDebug,
|
||||
isOwner,
|
||||
template,
|
||||
latestVersion,
|
||||
permissions,
|
||||
} = props;
|
||||
export const WorkspaceTopbar: FC<WorkspaceProps> = ({
|
||||
handleStart,
|
||||
handleStop,
|
||||
handleRestart,
|
||||
handleDelete,
|
||||
handleUpdate,
|
||||
handleCancel,
|
||||
handleSettings,
|
||||
handleChangeVersion,
|
||||
handleDormantActivate,
|
||||
workspace,
|
||||
isUpdating,
|
||||
isRestarting,
|
||||
canUpdateWorkspace,
|
||||
canChangeVersions,
|
||||
canRetryDebugMode,
|
||||
handleBuildRetry,
|
||||
handleBuildRetryDebug,
|
||||
isOwner,
|
||||
template,
|
||||
latestVersion,
|
||||
permissions,
|
||||
}) => {
|
||||
const theme = useTheme();
|
||||
|
||||
// Quota
|
||||
|
||||
@@ -2,16 +2,16 @@ import { type FC, useEffect, useState } from "react";
|
||||
import { Helmet } from "react-helmet-async";
|
||||
import { useQuery } from "react-query";
|
||||
import { useSearchParams } from "react-router-dom";
|
||||
import { templates } from "api/queries/templates";
|
||||
import type { Workspace } from "api/typesGenerated";
|
||||
import { templates } from "api/queries/templates";
|
||||
import { useOrganizationId } from "contexts/auth/useOrganizationId";
|
||||
import { usePermissions } from "contexts/auth/usePermissions";
|
||||
import { useEffectEvent } from "hooks/hookPolyfills";
|
||||
import { usePagination } from "hooks/usePagination";
|
||||
import { useDashboard } from "modules/dashboard/useDashboard";
|
||||
import { pageTitle } from "utils/page";
|
||||
import { useDashboard } from "components/Dashboard/DashboardProvider";
|
||||
import { useFilter } from "components/Filter/filter";
|
||||
import { useUserFilterMenu } from "components/Filter/UserFilter";
|
||||
import { useEffectEvent } from "hooks/hookPolyfills";
|
||||
import { useBatchActions } from "./batchActions";
|
||||
import { useWorkspacesData, useWorkspaceUpdate } from "./data";
|
||||
import { useTemplateFilterMenu, useStatusFilterMenu } from "./filter/menus";
|
||||
|
||||
@@ -19,7 +19,7 @@ import {
|
||||
MockTemplate,
|
||||
} from "testHelpers/entities";
|
||||
import { WorkspacesPageView } from "./WorkspacesPageView";
|
||||
import { DashboardProviderContext } from "components/Dashboard/DashboardProvider";
|
||||
import { DashboardContext } from "modules/dashboard/DashboardProvider";
|
||||
import { ComponentProps } from "react";
|
||||
import {
|
||||
MockMenu,
|
||||
@@ -141,7 +141,7 @@ const meta: Meta<typeof WorkspacesPageView> = {
|
||||
},
|
||||
decorators: [
|
||||
(Story) => (
|
||||
<DashboardProviderContext.Provider
|
||||
<DashboardContext.Provider
|
||||
value={{
|
||||
buildInfo: MockBuildInfo,
|
||||
entitlements: MockEntitlementsWithScheduling,
|
||||
@@ -150,7 +150,7 @@ const meta: Meta<typeof WorkspacesPageView> = {
|
||||
}}
|
||||
>
|
||||
<Story />
|
||||
</DashboardProviderContext.Provider>
|
||||
</DashboardContext.Provider>
|
||||
),
|
||||
],
|
||||
};
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
import { type FC } from "react";
|
||||
import { useTheme } from "@emotion/react";
|
||||
import { useIsWorkspaceActionsEnabled } from "components/Dashboard/DashboardProvider";
|
||||
import { type FC } from "react";
|
||||
import { useDashboard } from "modules/dashboard/useDashboard";
|
||||
import { Avatar, type AvatarProps } from "components/Avatar/Avatar";
|
||||
import type { TemplateFilterMenu, StatusFilterMenu } from "./menus";
|
||||
import type { TemplateOption, StatusOption } from "./options";
|
||||
import {
|
||||
Filter,
|
||||
FilterMenu,
|
||||
@@ -15,6 +13,8 @@ import {
|
||||
} from "components/Filter/filter";
|
||||
import { type UserFilterMenu, UserMenu } from "components/Filter/UserFilter";
|
||||
import { docs } from "utils/docs";
|
||||
import type { TemplateFilterMenu, StatusFilterMenu } from "./menus";
|
||||
import type { TemplateOption, StatusOption } from "./options";
|
||||
|
||||
export const workspaceFilterQuery = {
|
||||
me: "owner:me",
|
||||
@@ -74,8 +74,10 @@ export const WorkspacesFilter: FC<WorkspaceFilterProps> = ({
|
||||
error,
|
||||
menus,
|
||||
}) => {
|
||||
const actionsEnabled = useIsWorkspaceActionsEnabled();
|
||||
const presets = actionsEnabled ? PRESETS_WITH_DORMANT : PRESET_FILTERS;
|
||||
const { entitlements } = useDashboard();
|
||||
const presets = entitlements.features["advanced_template_scheduling"].enabled
|
||||
? PRESETS_WITH_DORMANT
|
||||
: PRESET_FILTERS;
|
||||
|
||||
return (
|
||||
<Filter
|
||||
|
||||
@@ -7,9 +7,9 @@ import {
|
||||
import { type ReactNode, useState } from "react";
|
||||
import { QueryClient } from "react-query";
|
||||
import { AppProviders } from "App";
|
||||
import { ThemeProvider } from "contexts/ThemeProvider";
|
||||
import { DashboardLayout } from "components/Dashboard/DashboardLayout";
|
||||
import { RequireAuth } from "contexts/auth/RequireAuth";
|
||||
import { ThemeProvider } from "contexts/ThemeProvider";
|
||||
import { DashboardLayout } from "modules/dashboard/DashboardLayout";
|
||||
import { TemplateSettingsLayout } from "pages/TemplateSettingsPage/TemplateSettingsLayout";
|
||||
import { WorkspaceSettingsLayout } from "pages/WorkspaceSettingsPage/WorkspaceSettingsLayout";
|
||||
import {
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
import { DashboardProviderContext } from "components/Dashboard/DashboardProvider";
|
||||
import { type FC } from "react";
|
||||
import type { StoryContext } from "@storybook/react";
|
||||
import { withDefaultFeatures } from "api/api";
|
||||
import type { Entitlements } from "api/typesGenerated";
|
||||
import { DashboardContext } from "modules/dashboard/DashboardProvider";
|
||||
import {
|
||||
MockAppearanceConfig,
|
||||
MockBuildInfo,
|
||||
MockEntitlements,
|
||||
} from "./entities";
|
||||
import { FC } from "react";
|
||||
import { StoryContext } from "@storybook/react";
|
||||
import * as _storybook_types from "@storybook/react";
|
||||
import { Entitlements } from "api/typesGenerated";
|
||||
import { withDefaultFeatures } from "api/api";
|
||||
|
||||
export const withDashboardProvider = (
|
||||
Story: FC,
|
||||
@@ -19,18 +18,17 @@ export const withDashboardProvider = (
|
||||
const entitlements: Entitlements = {
|
||||
...MockEntitlements,
|
||||
features: withDefaultFeatures(
|
||||
features.reduce(
|
||||
(acc, feature) => {
|
||||
acc[feature] = { enabled: true, entitlement: "entitled" };
|
||||
return acc;
|
||||
},
|
||||
{} as Entitlements["features"],
|
||||
Object.fromEntries(
|
||||
features.map((feature) => [
|
||||
feature,
|
||||
{ enabled: true, entitlement: "entitled" },
|
||||
]),
|
||||
),
|
||||
),
|
||||
};
|
||||
|
||||
return (
|
||||
<DashboardProviderContext.Provider
|
||||
<DashboardContext.Provider
|
||||
value={{
|
||||
buildInfo: MockBuildInfo,
|
||||
entitlements,
|
||||
@@ -43,6 +41,6 @@ export const withDashboardProvider = (
|
||||
}}
|
||||
>
|
||||
<Story />
|
||||
</DashboardProviderContext.Provider>
|
||||
</DashboardContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
+2
-3
@@ -84,14 +84,13 @@ export default defineConfig({
|
||||
alias: {
|
||||
api: path.resolve(__dirname, "./src/api"),
|
||||
components: path.resolve(__dirname, "./src/components"),
|
||||
hooks: path.resolve(__dirname, "./src/hooks"),
|
||||
contexts: path.resolve(__dirname, "./src/contexts"),
|
||||
i18n: path.resolve(__dirname, "./src/i18n"),
|
||||
hooks: path.resolve(__dirname, "./src/hooks"),
|
||||
modules: path.resolve(__dirname, "./src/modules"),
|
||||
pages: path.resolve(__dirname, "./src/pages"),
|
||||
testHelpers: path.resolve(__dirname, "./src/testHelpers"),
|
||||
theme: path.resolve(__dirname, "./src/theme"),
|
||||
utils: path.resolve(__dirname, "./src/utils"),
|
||||
xServices: path.resolve(__dirname, "./src/xServices"),
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user