Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,18 @@ interface AgentSecretShowModalProps extends IdentifiableComponentInterface {
* The secret associated with the agent.
*/
agentSecret?: string;
/**
* The client ID of the application created alongside the agent.
*/
applicationClientId?: string;
/**
* Whether this is a user-serving agent (has an associated OAuth application).
*/
isUserServingAgent?: boolean;
/**
* Whether the application client ID is currently being fetched.
*/
isFetchingClientId?: boolean;
/**
* Flag indicating whether the modal is open.
*/
Expand All @@ -64,6 +76,9 @@ export function AgentSecretShowModal({
title,
agentId,
agentSecret,
applicationClientId,
isUserServingAgent,
isFetchingClientId,
isOpen,
onClose,
isForSecretRegeneration,
Expand Down Expand Up @@ -171,6 +186,20 @@ export function AgentSecretShowModal({
data-componentid={ "agent-secret-readonly-input" }
/>
</div>
{ !isForSecretRegeneration && isUserServingAgent && (
<>
<div style={ { marginTop: "2%" } }></div>
<label>OAuth Client ID</label>
<div style={ { marginTop: "1%" } }>
{/* Show loading state while fetching the client ID from the backend */}
<CopyInputField
className="agent-application-client-id-input"
value={ isFetchingClientId ? "Loading..." : (applicationClientId || "") }
data-componentid="agent-application-client-id-readonly-input"
/>
</div>
</>
) }
</>)
}
</Modal.Content>
Expand Down
250 changes: 165 additions & 85 deletions features/admin.agents.v1/components/wizards/add-agent-wizard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { AuthenticatedUserInfo } from "@asgardeo/auth-react";
import { AppState } from "@wso2is/admin.core.v1/store";
import { AlertLevels, IdentifiableComponentInterface } from "@wso2is/core/models";
import { addAlert } from "@wso2is/core/store";
import { FinalForm, FinalFormField, FormRenderProps, TextFieldAdapter } from "@wso2is/form/src";
import { FinalForm, FinalFormField, FormRenderProps, TextFieldAdapter, CheckboxFieldAdapter } from "@wso2is/form/src";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check if importing from `@wso2is/form/src` is a pattern used elsewhere
rg "from ['\"]@wso2is/form" --type ts --type tsx -A 0 | head -50

Repository: wso2/identity-apps

Length of output: 89


🏁 Script executed:

#!/bin/bash
# Search for `@wso2is/form` imports without file type restrictions
rg "@wso2is/form" --glob "*.ts" --glob "*.tsx" -A 0 | head -100

Repository: wso2/identity-apps

Length of output: 13171


🏁 Script executed:

#!/bin/bash
# Check the exact file mentioned in the review comment
head -30 features/admin.agents.v1/components/wizards/add-agent-wizard.tsx | grep -n "import"

Repository: wso2/identity-apps

Length of output: 752


Change import path from @wso2is/form/src to @wso2is/form.

Importing from /src bypasses the package's public exports and can cause issues in production builds. Use the public entry point instead.

- import { FinalForm, FinalFormField, FormRenderProps, TextFieldAdapter, CheckboxFieldAdapter } from "@wso2is/form/src";
+ import { FinalForm, FinalFormField, FormRenderProps, TextFieldAdapter, CheckboxFieldAdapter } from "@wso2is/form";
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@features/admin.agents.v1/components/wizards/add-agent-wizard.tsx` at line 23,
The import currently pulls FinalForm, FinalFormField, FormRenderProps,
TextFieldAdapter, and CheckboxFieldAdapter from the package's internal path
"@wso2is/form/src"; change the import to use the package's public entry
"@wso2is/form" so the components use the official public exports and avoid
production build issues—update the import statement that references FinalForm,
FinalFormField, FormRenderProps, TextFieldAdapter, CheckboxFieldAdapter
accordingly.

import { Button } from "@wso2is/react-components";
import React, { useState } from "react";
import { useDispatch, useSelector } from "react-redux";
Expand All @@ -42,6 +42,68 @@ export default function AddAgentWizard({

const authenticatedUserInfo: AuthenticatedUserInfo = useSelector((state: AppState) => state?.auth);
const [ isNewAgentFormSubmitting, setIsNewAgentFormSubmitting ] = useState<boolean>(false);
const [ currentStep, setCurrentStep ] = useState<number>(0);
const [ stepOneValues, setStepOneValues ] = useState<{ name?: string; description?: string }>({});
const [ stepOneErrors, setStepOneErrors ] = useState<{ name?: string }>({});

const handleClose = () => {
setCurrentStep(0);
setStepOneValues({});
setStepOneErrors({});
onClose(null);
};

const handleNext = (values: any) => {
if (!values?.name) {
setStepOneErrors({ name: "Agent name is required." });

return;
}

setStepOneErrors({});
setStepOneValues({ description: values?.description, name: values?.name });
setCurrentStep(1);
};

const handleBack = () => {
setCurrentStep(0);
};

const handleCreate = (values: any) => {
setIsNewAgentFormSubmitting(true);

// Capture the checkbox value here — the backend response does NOT return
// IsUserServingAgent, so we must carry this value forward ourselves.
const isUserServing: boolean = values?.isUserServingAgent || false;

const addAgentPayload: AgentScimSchema = {
"urn:scim:wso2:agent:schema": {
Description: stepOneValues?.description,
DisplayName: stepOneValues?.name,
IsUserServingAgent: isUserServing,
Owner: authenticatedUserInfo?.username
}
};

addAgent(addAgentPayload)
.then((response: AgentScimSchema) => {
// Attach isUserServingAgent to the response so the parent (agents.tsx)
// knows which value the user selected, without relying on the backend
// to echo it back.
onClose({ ...response, isUserServingAgent: isUserServing });
})
.catch((_err: unknown) => {
dispatch(
addAlert({
description: "Creating agent failed",
level: AlertLevels.ERROR,
message: "Something went wrong"
})
);
}).finally(() => {
setIsNewAgentFormSubmitting(false);
});
};

return (
<Modal
Expand All @@ -51,97 +113,115 @@ export default function AddAgentWizard({
className="wizard"
dimmer="blurring"
size="tiny"
onClose={ onClose }
onClose={ handleClose }
closeOnDimmerClick={ false }
closeOnEscape
>
<Modal.Header>New Agent</Modal.Header>
<Modal.Content>
<FinalForm
onSubmit={ (values: any) => {
if (!values?.name) {
return;
}

setIsNewAgentFormSubmitting(true);

const addAgentPayload: AgentScimSchema = {
"urn:scim:wso2:agent:schema": {
Description: values?.description,
DisplayName: values?.name,
Owner: authenticatedUserInfo?.username
}
};

addAgent(addAgentPayload)
.then((response: AgentScimSchema) => {
onClose(response);
})
.catch((_err: unknown) => {
dispatch(
addAlert({
description: "Creating agent failed",
level: AlertLevels.ERROR,
message: "Something went wrong"
})

{ currentStep === 0 && (
<>
<Modal.Content>
<FinalForm
onSubmit={ handleNext }
initialValues={ stepOneValues }
render={ ({ handleSubmit }: FormRenderProps) => {
return (
<form id="addAgentStepOneForm" onSubmit={ handleSubmit }>
<FinalFormField
name="name"
label="Name"
required={ true }
autoComplete="new-password"
component={ TextFieldAdapter }
error={ stepOneErrors?.name }
/>
<FinalFormField
label="Description"
name="description"
className="mt-3"
multiline
rows={ 4 }
maxRows={ 4 }
autoComplete="new-password"
placeholder="Enter a description for the agent"
component={ TextFieldAdapter }
/>
</form>
);
}).finally(() => {
setIsNewAgentFormSubmitting(false);
});
} }
render={ ({ handleSubmit }: FormRenderProps) => {
return (
<form id="addAgentForm" onSubmit={ handleSubmit }>
<FinalFormField
name="name"
label="Name"
required={ true }
autoComplete="new-password"
component={ TextFieldAdapter }
/>
<FinalFormField
label="Description"
name="description"
className="mt-3"
multiline
rows={ 4 }
maxRows={ 4 }
autoComplete="new-password"
placeholder="Enter a description for the agent"
component={ TextFieldAdapter }
/>
</form>
);
} }
/>

</Modal.Content>

<Modal.Actions>
<Button
className="link-button"
basic
primary
onClick={ () => onClose(null) }
data-testid={ `${componentId}-confirmation-modal-actions-cancel-button` }
>
} }
/>
</Modal.Content>
<Modal.Actions>
<Button
className="link-button"
basic
primary
onClick={ handleClose }
data-testid={ `${componentId}-step-one-cancel-button` }
>
Cancel
</Button>
<Button
primary={ true }
type="submit"
disabled={ isNewAgentFormSubmitting }
loading={ isNewAgentFormSubmitting }
onClick={ () => {
document
.getElementById("addAgentForm")
.dispatchEvent(new Event("submit", { bubbles: true, cancelable: true }));
} }
data-testid={ `${componentId}-confirmation-modal-actions-continue-button` }
>
</Button>
<Button
primary={ true }
onClick={ () => {
document
.getElementById("addAgentStepOneForm")
.dispatchEvent(new Event("submit", { bubbles: true, cancelable: true }));
} }
data-testid={ `${componentId}-step-one-next-button` }
>
Next
</Button>
</Modal.Actions>
</>
) }

{ currentStep === 1 && (
<>
<Modal.Content>
<FinalForm
onSubmit={ handleCreate }
render={ ({ handleSubmit }: FormRenderProps) => {
return (
<form id="addAgentStepTwoForm" onSubmit={ handleSubmit }>
<FinalFormField
name="isUserServingAgent"
label="Is this a user-serving agent?"
component={ CheckboxFieldAdapter }
/>
</form>
);
} }
/>
</Modal.Content>
<Modal.Actions>
<Button
className="link-button"
basic
primary
onClick={ handleBack }
data-testid={ `${componentId}-step-two-back-button` }
>
Back
</Button>
<Button
primary={ true }
type="submit"
disabled={ isNewAgentFormSubmitting }
loading={ isNewAgentFormSubmitting }
onClick={ () => {
document
.getElementById("addAgentStepTwoForm")
.dispatchEvent(new Event("submit", { bubbles: true, cancelable: true }));
} }
data-testid={ `${componentId}-step-two-create-button` }
>
Create
</Button>
</Modal.Actions>
</Button>
</Modal.Actions>
</>
) }
</Modal>
);
}
2 changes: 2 additions & 0 deletions features/admin.agents.v1/models/agents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,14 @@ export interface AgentSchema {
Url?: string;
Description?: string;
DisplayName?: string;
IsUserServingAgent?: boolean;
[key: string]: any;
}

export interface AgentScimSchema {
id?: string;
userName?: string;
password?: string;
applicationClientId?: string;
"urn:scim:wso2:agent:schema"?: AgentSchema;
}
Loading