Skip to content

Commit 1b42c5a

Browse files
committed
feat: view selector
1 parent b52dcc9 commit 1b42c5a

2 files changed

Lines changed: 97 additions & 5 deletions

File tree

integration-tests/http/view-configurations.spec.ts

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -737,6 +737,56 @@ medusaIntegrationTestRunner({
737737
personalView.data.view_configuration.configuration
738738
)
739739
})
740+
741+
it("should allow resetting system default to code-level defaults", async () => {
742+
// Create a system default view
743+
const systemDefaultView = await api.post(
744+
"/admin/view-configurations",
745+
{
746+
entity: "orders",
747+
name: "Custom System Default",
748+
is_system_default: true,
749+
configuration: {
750+
visible_columns: ["id", "status", "total"],
751+
column_order: ["status", "total", "id"],
752+
},
753+
},
754+
adminHeaders
755+
)
756+
757+
expect(systemDefaultView.status).toEqual(201)
758+
const viewId = systemDefaultView.data.view_configuration.id
759+
760+
// Verify it exists
761+
let viewsList = await api.get(
762+
"/admin/view-configurations?entity=orders",
763+
adminHeaders
764+
)
765+
expect(viewsList.data.view_configurations.some((v: any) => v.id === viewId)).toBe(true)
766+
767+
// Delete the system default view (reset to code defaults)
768+
const deleteResponse = await api.delete(
769+
`/admin/view-configurations/${viewId}`,
770+
adminHeaders
771+
)
772+
773+
expect(deleteResponse.status).toEqual(200)
774+
expect(deleteResponse.data.deleted).toBe(true)
775+
776+
// Verify it's gone
777+
viewsList = await api.get(
778+
"/admin/view-configurations?entity=orders",
779+
adminHeaders
780+
)
781+
expect(viewsList.data.view_configurations.some((v: any) => v.id === viewId)).toBe(false)
782+
783+
// Getting active view should return null (falls back to code defaults)
784+
const activeView = await api.get(
785+
"/admin/view-configurations/active?entity=orders",
786+
adminHeaders
787+
)
788+
expect(activeView.data.view_configuration).toBeNull()
789+
})
740790
})
741791
})
742792
},

packages/admin/dashboard/src/components/table/view-selector/view-selector.tsx

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import {
1616
PencilSquare,
1717
Star,
1818
CheckCircleSolid,
19+
ArrowUturnLeft,
1920
} from "@medusajs/icons"
2021
import { useViewConfiguration } from "../../../providers/view-configuration-provider"
2122
import { ViewConfiguration } from "../../../providers/view-configuration-provider"
@@ -112,6 +113,31 @@ export const ViewSelector: React.FC<ViewSelectorProps> = ({
112113
setSaveDialogOpen(true)
113114
}
114115

116+
const handleResetSystemDefault = async (systemDefaultView: ViewConfiguration) => {
117+
const result = await prompt({
118+
title: "Reset system default",
119+
description: "This will delete the saved system default and revert to the original code-level defaults. All users will be affected. Are you sure?",
120+
confirmText: "Reset",
121+
cancelText: "Cancel",
122+
})
123+
124+
if (result) {
125+
try {
126+
await deleteViewConfiguration(systemDefaultView.id)
127+
setViews(views.filter(v => v.id !== systemDefaultView.id))
128+
if (activeView?.id === systemDefaultView.id) {
129+
setActiveViewState(null)
130+
if (onViewChange) {
131+
onViewChange(null)
132+
}
133+
}
134+
toast.success("System default reset to code-level defaults")
135+
} catch (error) {
136+
toast.error("Failed to reset system default")
137+
}
138+
}
139+
}
140+
115141
const systemDefaultView = views.find(v => v.is_system_default)
116142
const personalViews = views.filter(v => !v.is_system_default)
117143

@@ -131,15 +157,31 @@ export const ViewSelector: React.FC<ViewSelectorProps> = ({
131157
<DropdownMenu.Label>System Default</DropdownMenu.Label>
132158
<DropdownMenu.Item
133159
onClick={() => handleViewSelect(systemDefaultView.id)}
134-
className="justify-between"
160+
className="justify-between group"
135161
>
136162
<span className="flex items-center gap-2">
137163
<Star className="h-4 w-4" />
138-
{systemDefaultView.name}
164+
{systemDefaultView.name || "System Default"}
139165
</span>
140-
{activeView?.id === systemDefaultView.id && (
141-
<CheckCircleSolid className="h-4 w-4 text-ui-fg-positive" />
142-
)}
166+
<div className="flex items-center gap-1">
167+
{activeView?.id === systemDefaultView.id && (
168+
<CheckCircleSolid className="h-4 w-4 text-ui-fg-positive" />
169+
)}
170+
<div className="opacity-0 group-hover:opacity-100">
171+
<Tooltip content="Reset to code defaults">
172+
<Button
173+
variant="transparent"
174+
size="small"
175+
onClick={(e) => {
176+
e.stopPropagation()
177+
handleResetSystemDefault(systemDefaultView)
178+
}}
179+
>
180+
<ArrowUturnLeft className="h-3 w-3" />
181+
</Button>
182+
</Tooltip>
183+
</div>
184+
</div>
143185
</DropdownMenu.Item>
144186
{personalViews.length > 0 && <DropdownMenu.Separator />}
145187
</>

0 commit comments

Comments
 (0)