1- import { useState , type ReactNode } from "react" ;
1+ import { type ReactNode } from "react" ;
22import { useMutation , useQueryClient } from "@tanstack/react-query" ;
33import {
44 useProjectContext ,
55 useMCPClient ,
66 SELF_MCP_ALIAS_ID ,
77} from "@decocms/mesh-sdk" ;
88import { KEYS } from "@/web/lib/query-keys" ;
9- import { Button } from "@deco/ui/components/button.tsx" ;
109import { Switch } from "@deco/ui/components/switch.tsx" ;
1110import { toast } from "sonner" ;
1211import { Container } from "@untitledui/icons" ;
@@ -113,51 +112,8 @@ export function ProjectPluginsForm() {
113112 orgId : org . id ,
114113 } ) ;
115114
116- // Track only pending changes (pluginId -> intended state)
117- const [ pendingChanges , setPendingChanges ] = useState < Record < string , boolean > > (
118- { } ,
119- ) ;
120- const [ isSaving , setIsSaving ] = useState ( false ) ;
121-
122115 const serverPlugins = project . enabledPlugins ?? [ ] ;
123116
124- // Derive whether a plugin is enabled: pending changes override server state
125- const isPluginEnabled = ( pluginId : string ) : boolean => {
126- const pending = pendingChanges [ pluginId ] ;
127- if ( pending !== undefined ) {
128- return pending ;
129- }
130- return serverPlugins . includes ( pluginId ) ;
131- } ;
132-
133- // Compute the full list of enabled plugins for saving
134- const getEnabledPluginsList = ( ) : string [ ] => {
135- const result = new Set ( serverPlugins ) ;
136- for ( const [ pluginId , enabled ] of Object . entries ( pendingChanges ) ) {
137- if ( enabled ) {
138- result . add ( pluginId ) ;
139- } else {
140- result . delete ( pluginId ) ;
141- }
142- }
143- return Array . from ( result ) ;
144- } ;
145-
146- const hasChanges = Object . keys ( pendingChanges ) . length > 0 ;
147-
148- const handleTogglePlugin = ( pluginId : string , enabled : boolean ) => {
149- const serverEnabled = serverPlugins . includes ( pluginId ) ;
150-
151- if ( enabled === serverEnabled ) {
152- setPendingChanges ( ( prev ) => {
153- const { [ pluginId ] : _ , ...rest } = prev ;
154- return rest ;
155- } ) ;
156- } else {
157- setPendingChanges ( ( prev ) => ( { ...prev , [ pluginId ] : enabled } ) ) ;
158- }
159- } ;
160-
161117 const mutation = useMutation ( {
162118 mutationFn : async ( input : { enabledPlugins : string [ ] } ) => {
163119 const result = await client . callTool ( {
@@ -187,28 +143,20 @@ export function ProjectPluginsForm() {
187143 queryClient . invalidateQueries ( {
188144 queryKey : KEYS . organizationSettings ( org . id ) ,
189145 } ) ;
190-
191- setPendingChanges ( { } ) ;
192- toast . success ( "Plugins updated successfully" ) ;
193146 } ,
194147 onError : ( error ) => {
195148 toast . error (
196149 "Failed to update plugins: " +
197150 ( error instanceof Error ? error . message : "Unknown error" ) ,
198151 ) ;
199152 } ,
200- onSettled : ( ) => {
201- setIsSaving ( false ) ;
202- } ,
203153 } ) ;
204154
205- const handleSave = ( ) => {
206- setIsSaving ( true ) ;
207- mutation . mutate ( { enabledPlugins : getEnabledPluginsList ( ) } ) ;
208- } ;
209-
210- const handleCancel = ( ) => {
211- setPendingChanges ( { } ) ;
155+ const handleTogglePlugin = ( pluginId : string , enabled : boolean ) => {
156+ const updated = enabled
157+ ? [ ...serverPlugins , pluginId ]
158+ : serverPlugins . filter ( ( id ) => id !== pluginId ) ;
159+ mutation . mutate ( { enabledPlugins : updated } ) ;
212160 } ;
213161
214162 // Get plugin metadata from sidebar groups
@@ -231,44 +179,25 @@ export function ProjectPluginsForm() {
231179 }
232180
233181 return (
234- < div className = "space-y-4" >
235- < div className = "flex flex-col" >
236- { sourcePlugins . map ( ( plugin ) => {
237- const meta = getPluginMeta ( plugin . id ) ;
238- const description = getPluginDescription ( plugin . id ) ;
239- const isEnabled = isPluginEnabled ( plugin . id ) ;
240-
241- return (
242- < PluginRow
243- key = { plugin . id }
244- plugin = { plugin }
245- isEnabled = { isEnabled }
246- isSaving = { isSaving }
247- description = { description }
248- label = { meta ?. label ?? plugin . id }
249- icon = { meta ?. icon ?? < Container size = { 14 } /> }
250- onToggle = { handleTogglePlugin }
251- />
252- ) ;
253- } ) }
254- </ div >
255-
256- < div className = "flex items-center gap-3 pt-4" >
257- < Button
258- variant = "outline"
259- onClick = { handleCancel }
260- disabled = { ! hasChanges || isSaving }
261- >
262- Cancel
263- </ Button >
264- < Button
265- onClick = { handleSave }
266- disabled = { ! hasChanges || isSaving }
267- className = "min-w-24"
268- >
269- { isSaving ? "Saving..." : "Save Changes" }
270- </ Button >
271- </ div >
182+ < div className = "flex flex-col" >
183+ { sourcePlugins . map ( ( plugin ) => {
184+ const meta = getPluginMeta ( plugin . id ) ;
185+ const description = getPluginDescription ( plugin . id ) ;
186+ const isEnabled = serverPlugins . includes ( plugin . id ) ;
187+
188+ return (
189+ < PluginRow
190+ key = { plugin . id }
191+ plugin = { plugin }
192+ isEnabled = { isEnabled }
193+ isSaving = { mutation . isPending }
194+ description = { description }
195+ label = { meta ?. label ?? plugin . id }
196+ icon = { meta ?. icon ?? < Container size = { 14 } /> }
197+ onToggle = { handleTogglePlugin }
198+ />
199+ ) ;
200+ } ) }
272201 </ div >
273202 ) ;
274203}
0 commit comments