feat(web): migrate dashboard to WidgetGrid with layout persistence (#497)
All checks were successful
ci/woodpecker/push/web Pipeline was successful
All checks were successful
ci/woodpecker/push/web Pipeline was successful
Co-authored-by: Jason Woltje <jason@diversecanvas.com> Co-committed-by: Jason Woltje <jason@diversecanvas.com>
This commit was merged in pull request #497.
This commit is contained in:
@@ -37,16 +37,31 @@ export function BaseWidget({
|
||||
return (
|
||||
<div
|
||||
data-widget-id={id}
|
||||
className={cn(
|
||||
"flex flex-col h-full bg-white rounded-lg border border-gray-200 shadow-sm overflow-hidden",
|
||||
className
|
||||
)}
|
||||
className={cn("flex flex-col h-full overflow-hidden", className)}
|
||||
style={{
|
||||
background: "var(--surface)",
|
||||
border: "1px solid var(--border)",
|
||||
borderRadius: "var(--r-lg)",
|
||||
boxShadow: "var(--shadow-sm)",
|
||||
}}
|
||||
>
|
||||
{/* Widget Header */}
|
||||
<div className="flex items-center justify-between px-4 py-3 border-b border-gray-100 bg-gray-50">
|
||||
<div
|
||||
className="flex items-center justify-between px-4 py-3"
|
||||
style={{
|
||||
borderBottom: "1px solid var(--border)",
|
||||
background: "var(--surface-2)",
|
||||
}}
|
||||
>
|
||||
<div className="flex-1 min-w-0">
|
||||
<h3 className="text-sm font-semibold text-gray-900 truncate">{title}</h3>
|
||||
{description && <p className="text-xs text-gray-500 truncate mt-0.5">{description}</p>}
|
||||
<h3 className="text-sm font-semibold truncate" style={{ color: "var(--text)" }}>
|
||||
{title}
|
||||
</h3>
|
||||
{description && (
|
||||
<p className="text-xs truncate mt-0.5" style={{ color: "var(--muted)" }}>
|
||||
{description}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Control buttons - only show if handlers provided */}
|
||||
@@ -56,7 +71,8 @@ export function BaseWidget({
|
||||
<button
|
||||
onClick={onEdit}
|
||||
aria-label="Edit widget"
|
||||
className="p-1 text-gray-400 hover:text-gray-600 hover:bg-gray-100 rounded transition-colors"
|
||||
className="p-1 rounded transition-colors"
|
||||
style={{ color: "var(--muted)" }}
|
||||
title="Edit widget"
|
||||
>
|
||||
<Settings className="w-4 h-4" />
|
||||
@@ -66,7 +82,8 @@ export function BaseWidget({
|
||||
<button
|
||||
onClick={onRemove}
|
||||
aria-label="Remove widget"
|
||||
className="p-1 text-gray-400 hover:text-red-600 hover:bg-red-50 rounded transition-colors"
|
||||
className="p-1 rounded transition-colors"
|
||||
style={{ color: "var(--muted)" }}
|
||||
title="Remove widget"
|
||||
>
|
||||
<X className="w-4 h-4" />
|
||||
@@ -81,15 +98,24 @@ export function BaseWidget({
|
||||
{isLoading ? (
|
||||
<div className="flex items-center justify-center h-full">
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<div className="w-8 h-8 border-2 border-blue-500 border-t-transparent rounded-full animate-spin" />
|
||||
<span className="text-sm text-gray-500">Loading...</span>
|
||||
<div
|
||||
className="w-8 h-8 border-2 border-t-transparent rounded-full animate-spin"
|
||||
style={{ borderColor: "var(--primary)", borderTopColor: "transparent" }}
|
||||
/>
|
||||
<span className="text-sm" style={{ color: "var(--muted)" }}>
|
||||
Loading...
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
) : error ? (
|
||||
<div className="flex items-center justify-center h-full">
|
||||
<div className="text-center">
|
||||
<div className="text-red-500 text-sm font-medium mb-1">Error</div>
|
||||
<div className="text-xs text-gray-600">{error}</div>
|
||||
<div className="text-sm font-medium mb-1" style={{ color: "var(--danger)" }}>
|
||||
Error
|
||||
</div>
|
||||
<div className="text-xs" style={{ color: "var(--muted)" }}>
|
||||
{error}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
|
||||
Reference in New Issue
Block a user