;
- /**
- * Maximum number of rows user can have in the grid.
- * @defaultValue unlimited
- */
- maxRows?: number;
- /**
- * Custom style for grid.
- */
- style?: React.CSSProperties;
- /**
- * Compaction type of widgets in the grid. This controls where widgets are moved in case
- * they are overlapping in the grid.
- */
- compactType?: 'vertical' | 'horizontal' | null;
- /**
- * Controls if widgets can overlap in the grid. If true, grid can be placed one over the other.
- * @defaultValue false
- */
- allowOverlap?: boolean;
- /**
- * Controls if widgets can collide with each other. If true, grid items won't change position when being dragged over.
- * @defaultValue false
- */
- preventCollision?: boolean;
-};
-
/**
* A component that allows customizing components in home grid layout.
*
@@ -318,6 +246,9 @@ export const CustomHomepageGrid = (props: CustomHomepageGridProps) => {
isDraggable: editMode,
},
settings: {},
+ movable: widget.movable,
+ deletable: widget.deletable,
+ resizable: widget.resizable,
},
]);
setAddWidgetDialogOpen(false);
@@ -348,9 +279,11 @@ export const CustomHomepageGrid = (props: CustomHomepageGridProps) => {
setEditMode(mode);
setWidgets(
widgets.map(w => {
+ const resizable = w.resizable === false ? false : mode;
+ const movable = w.movable === false ? false : mode;
return {
...w,
- layout: { ...w.layout, isDraggable: mode, isResizable: mode },
+ layout: { ...w.layout, isDraggable: movable, isResizable: resizable },
};
}),
);
@@ -370,7 +303,20 @@ export const CustomHomepageGrid = (props: CustomHomepageGridProps) => {
};
const handleRestoreDefaultConfig = () => {
- setWidgets(defaultLayout);
+ setWidgets(
+ defaultLayout.map(w => {
+ const resizable = w.resizable === false ? false : editMode;
+ const movable = w.movable === false ? false : editMode;
+ return {
+ ...w,
+ layout: {
+ ...w.layout,
+ isDraggable: movable,
+ isResizable: resizable,
+ },
+ };
+ }),
+ );
};
return (
@@ -404,7 +350,7 @@ export const CustomHomepageGrid = (props: CustomHomepageGridProps) => {
style={props.style}
allowOverlap={props.allowOverlap}
preventCollision={props.preventCollision}
- draggableCancel=".overlayGridItem,.widgetSettingsDialog"
+ draggableCancel=".overlayGridItem,.widgetSettingsDialog,.disabled"
containerPadding={props.containerPadding}
margin={props.containerMargin}
breakpoints={
@@ -435,7 +381,9 @@ export const CustomHomepageGrid = (props: CustomHomepageGridProps) => {
return (
@@ -447,6 +395,7 @@ export const CustomHomepageGrid = (props: CustomHomepageGridProps) => {
handleRemove={handleRemove}
handleSettingsSave={handleSettingsSave}
settings={w.settings}
+ deletable={w.deletable}
/>
)}
diff --git a/plugins/home/src/components/CustomHomepage/WidgetSettingsOverlay.tsx b/plugins/home/src/components/CustomHomepage/WidgetSettingsOverlay.tsx
index 261dabb833..2c3a1d9ab9 100644
--- a/plugins/home/src/components/CustomHomepage/WidgetSettingsOverlay.tsx
+++ b/plugins/home/src/components/CustomHomepage/WidgetSettingsOverlay.tsx
@@ -58,10 +58,12 @@ interface WidgetSettingsOverlayProps {
handleRemove: (id: string) => void;
handleSettingsSave: (id: string, settings: Record) => void;
settings?: Record;
+ deletable?: boolean;
}
export const WidgetSettingsOverlay = (props: WidgetSettingsOverlayProps) => {
- const { id, widget, settings, handleRemove, handleSettingsSave } = props;
+ const { id, widget, settings, handleRemove, handleSettingsSave, deletable } =
+ props;
const [settingsDialogOpen, setSettingsDialogOpen] = React.useState(false);
const styles = useStyles();
@@ -110,13 +112,15 @@ export const WidgetSettingsOverlay = (props: WidgetSettingsOverlayProps) => {
)}
-
-
- handleRemove(id)}>
-
-
-
-
+ {deletable !== false && (
+
+
+ handleRemove(id)}>
+
+
+
+
+ )}
);
diff --git a/plugins/home/src/components/CustomHomepage/index.ts b/plugins/home/src/components/CustomHomepage/index.ts
index eed597cca3..380fdb4b25 100644
--- a/plugins/home/src/components/CustomHomepage/index.ts
+++ b/plugins/home/src/components/CustomHomepage/index.ts
@@ -14,5 +14,8 @@
* limitations under the License.
*/
export { CustomHomepageGrid } from './CustomHomepageGrid';
-export type { CustomHomepageGridProps, Breakpoint } from './CustomHomepageGrid';
-export type { LayoutConfiguration } from './types';
+export type {
+ CustomHomepageGridProps,
+ Breakpoint,
+ LayoutConfiguration,
+} from './types';
diff --git a/plugins/home/src/components/CustomHomepage/types.ts b/plugins/home/src/components/CustomHomepage/types.ts
index 8e9c6f403e..79e94c5f03 100644
--- a/plugins/home/src/components/CustomHomepage/types.ts
+++ b/plugins/home/src/components/CustomHomepage/types.ts
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-import { ReactElement } from 'react';
+import React, { ReactElement, ReactNode } from 'react';
import { Layout } from 'react-grid-layout';
import { z } from 'zod';
import { RJSFSchema, UiSchema } from '@rjsf/utils';
@@ -24,12 +24,91 @@ const RSJFTypeUiSchema: z.ZodType = z.any();
const ReactElementSchema: z.ZodType = z.any();
const LayoutSchema: z.ZodType = z.any();
+/**
+ * Breakpoint options for
+ *
+ * @public
+ */
+export type Breakpoint = 'xxs' | 'xs' | 'sm' | 'md' | 'lg' | 'xl';
+
+/**
+ * Props customizing the component.
+ *
+ * @public
+ */
+export type CustomHomepageGridProps = {
+ /**
+ * Children contain all widgets user can configure on their own homepage.
+ */
+ children?: ReactNode;
+ /**
+ * Default layout for the homepage before users have modified it.
+ */
+ config?: LayoutConfiguration[];
+ /**
+ * Height of grid row in pixels.
+ * @defaultValue 60
+ */
+ rowHeight?: number;
+ /**
+ * Screen width in pixels for different breakpoints.
+ * @defaultValue theme breakpoints
+ */
+ breakpoints?: Record;
+ /**
+ * Number of grid columns for different breakpoints.
+ * @defaultValue \{ lg: 12, md: 10, sm: 6, xs: 4, xxs: 2 \}
+ */
+ cols?: Record;
+ /**
+ * Grid container padding (x, y) in pixels for all or specific breakpoints.
+ * @defaultValue [0, 0]
+ * @example [10, 10]
+ * @example \{ lg: [10, 10] \}
+ */
+ containerPadding?: [number, number] | Record;
+ /**
+ * Grid container margin (x, y) in pixels for all or specific breakpoints.
+ * @defaultValue [0, 0]
+ * @example [10, 10]
+ * @example \{ lg: [10, 10] \}
+ */
+ containerMargin?: [number, number] | Record;
+ /**
+ * Maximum number of rows user can have in the grid.
+ * @defaultValue unlimited
+ */
+ maxRows?: number;
+ /**
+ * Custom style for grid.
+ */
+ style?: React.CSSProperties;
+ /**
+ * Compaction type of widgets in the grid. This controls where widgets are moved in case
+ * they are overlapping in the grid.
+ */
+ compactType?: 'vertical' | 'horizontal' | null;
+ /**
+ * Controls if widgets can overlap in the grid. If true, grid can be placed one over the other.
+ * @defaultValue false
+ */
+ allowOverlap?: boolean;
+ /**
+ * Controls if widgets can collide with each other. If true, grid items won't change position when being dragged over.
+ * @defaultValue false
+ */
+ preventCollision?: boolean;
+};
+
export const LayoutConfigurationSchema = z.object({
component: ReactElementSchema,
x: z.number().nonnegative('x must be positive number'),
y: z.number().nonnegative('y must be positive number'),
width: z.number().positive('width must be positive number'),
height: z.number().positive('height must be positive number'),
+ movable: z.boolean().optional(),
+ deletable: z.boolean().optional(),
+ resizable: z.boolean().optional(),
});
/**
@@ -43,6 +122,9 @@ export type LayoutConfiguration = {
y: number;
width: number;
height: number;
+ movable?: boolean;
+ deletable?: boolean;
+ resizable?: boolean;
};
export const WidgetSchema = z.object({
@@ -64,6 +146,9 @@ export const WidgetSchema = z.object({
.optional(),
settingsSchema: RSJFTypeSchema.optional(),
uiSchema: RSJFTypeUiSchema.optional(),
+ movable: z.boolean().optional(),
+ deletable: z.boolean().optional(),
+ resizable: z.boolean().optional(),
});
export type Widget = z.infer;
@@ -72,6 +157,9 @@ const GridWidgetSchema = z.object({
id: z.string(),
layout: LayoutSchema,
settings: z.record(z.string(), z.any()),
+ movable: z.boolean().optional(),
+ deletable: z.boolean().optional(),
+ resizable: z.boolean().optional(),
});
export type GridWidget = z.infer;