Skip to content
Draft
Show file tree
Hide file tree
Changes from all 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 @@ -25,7 +25,7 @@ export type ChoreoCatalogFiltersProps = {

/**
* Choreo Catalog Filters with Choreo entity kind names
* - Domain is displayed as "Organization"
* - Domain is displayed as "Namespace"
* - System is displayed as "Project"
*
* @public
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ function createProjectColumn(): TableColumn<CatalogTableRow> {
/**
* Custom catalog table columns function with Choreo naming:
* - System → Project
* - Domain → Organization (handled by entity kind picker)
* - Domain → Namespace (handled by entity kind picker)
*/
export const choreoCatalogTableColumns: CatalogTableColumnsFunc =
entityListContext => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { useUserGroups } from '../../hooks';

// Mapping of internal kind names to Choreo entity kind names
const kindDisplayNames: Record<string, string> = {
domain: 'Domain (Organization)',
domain: 'Domain (Namespace)',
system: 'System (Project)',
component: 'Component',
api: 'API',
Expand All @@ -25,7 +25,7 @@ const kindDisplayNames: Record<string, string> = {
};

// Custom order for displaying entity kinds in the dropdown
// Organization first, then Project, then Component, then others alphabetically
// Namespace first, then Project, then Component, then others alphabetically
const kindDisplayOrder: string[] = [
'domain',
'system',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,35 +60,35 @@ export const BuildTemplateParameters = ({
const discoveryApi = useApi(discoveryApiRef);
const fetchApi = useApi(fetchApiRef);

// Get the selected build template and organization from form context
// Get the selected build template and namespace from form context
const selectedTemplateName = formContext?.formData?.build_template_name;
const organizationName = formContext?.formData?.organization_name;
const namespaceName = formContext?.formData?.namespace_name;

// Fetch build templates when organization changes
// Fetch build templates when namespace changes
useEffect(() => {
let ignore = false;
const fetchBuildTemplates = async () => {
if (!organizationName) {
if (!namespaceName) {
setBuildTemplates([]);
return;
}

// Extract the actual organization name from the entity reference format
const extractOrgName = (fullOrgName: string): string => {
const parts = fullOrgName.split('/');
// Extract the actual namespace name from the entity reference format
const extractNsName = (fullNsName: string): string => {
const parts = fullNsName.split('/');
return parts[parts.length - 1];
};

const orgName = extractOrgName(organizationName);
const nsName = extractNsName(namespaceName);

setLoading(true);

try {
const baseUrl = await discoveryApi.getBaseUrl('openchoreo');
// Use fetchApi which automatically injects Backstage + IDP tokens
const response = await fetchApi.fetch(
`${baseUrl}/build-templates?organizationName=${encodeURIComponent(
orgName,
`${baseUrl}/build-templates?namespaceName=${encodeURIComponent(
nsName,
)}`,
);

Expand All @@ -109,7 +109,7 @@ export const BuildTemplateParameters = ({
return () => {
ignore = true;
};
}, [organizationName, discoveryApi, fetchApi]);
}, [namespaceName, discoveryApi, fetchApi]);

// Update parameters when template selection or templates change
useEffect(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,29 +47,29 @@ export const BuildTemplatePicker = ({
const discoveryApi = useApi(discoveryApiRef);
const fetchApi = useApi(fetchApiRef);

// Get the organization name from form context
const organizationName = formContext.formData?.organization_name;
// Get the namespace name from form context
const namespaceName = formContext.formData?.namespace_name;

useEffect(() => {
let ignore = false;
const fetchBuildTemplates = async () => {
if (!organizationName) {
if (!namespaceName) {
setBuildTemplates([]);
// Clear templates from form context when no organization
// Clear templates from form context when no namespace
if (formContext.buildTemplates) {
delete formContext.buildTemplates;
}
return;
}

// Extract the actual organization name from the entity reference format
// e.g., "domain:default/my-org" -> "my-org"
const extractOrgName = (fullOrgName: string): string => {
const parts = fullOrgName.split('/');
// Extract the actual namespace name from the entity reference format
// e.g., "domain:default/my-namespace" -> "my-namespace"
const extractNsName = (fullNsName: string): string => {
const parts = fullNsName.split('/');
return parts[parts.length - 1];
};

const orgName = extractOrgName(organizationName);
const nsName = extractNsName(namespaceName);

setLoading(true);
setError(null);
Expand All @@ -78,8 +78,8 @@ export const BuildTemplatePicker = ({
const baseUrl = await discoveryApi.getBaseUrl('openchoreo');
// Use fetchApi which automatically injects Backstage + IDP tokens
const response = await fetchApi.fetch(
`${baseUrl}/build-templates?organizationName=${encodeURIComponent(
orgName,
`${baseUrl}/build-templates?namespaceName=${encodeURIComponent(
nsName,
)}`,
);

Expand Down Expand Up @@ -108,7 +108,7 @@ export const BuildTemplatePicker = ({
return () => {
ignore = true;
};
}, [organizationName, discoveryApi, formContext, fetchApi]);
}, [namespaceName, discoveryApi, formContext, fetchApi]);

const handleChange = (event: ChangeEvent<{ value: unknown }>) => {
onChange(event.target.value as string);
Expand All @@ -132,7 +132,7 @@ export const BuildTemplatePicker = ({
labelId={`${idSchema?.$id}-label`}
value={formData || ''}
onChange={handleChange}
disabled={loading || !organizationName}
disabled={loading || !namespaceName}
>
{loading && (
<MenuItem disabled>
Expand All @@ -142,9 +142,9 @@ export const BuildTemplatePicker = ({
)}
{!loading && buildTemplates.length === 0 && !error && (
<MenuItem disabled>
{organizationName
{namespaceName
? 'No build templates available'
: 'Select an organization first'}
: 'Select a namespace first'}
</MenuItem>
)}
{!loading &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,10 @@ export const BuildWorkflowParameters = ({
const discoveryApi = useApi(discoveryApiRef);
const fetchApi = useApi(fetchApiRef);

// Get the selected workflow and organization from form data
// Get the selected workflow and namespace from form data
// The workflow_name is a sibling field in the same section
const selectedWorkflowName = formContext?.formData?.workflow_name;
const organizationName = formContext?.formData?.organization_name;
const namespaceName = formContext?.formData?.namespace_name;

// Increment resetKey only when workflow actually changes
// This forces Form remount only on workflow change, not on every render
Expand All @@ -75,19 +75,19 @@ export const BuildWorkflowParameters = ({
let ignore = false;

const fetchWorkflowSchema = async () => {
if (!selectedWorkflowName || !organizationName) {
if (!selectedWorkflowName || !namespaceName) {
setWorkflowSchema(null);
setError(null);
return;
}

// Extract the actual organization name from the entity reference format
const extractOrgName = (fullOrgName: string): string => {
const parts = fullOrgName.split('/');
// Extract the actual namespace name from the entity reference format
const extractNsName = (fullNsName: string): string => {
const parts = fullNsName.split('/');
return parts[parts.length - 1];
};

const orgName = extractOrgName(organizationName);
const nsName = extractNsName(namespaceName);

setLoading(true);
setError(null);
Expand All @@ -96,8 +96,8 @@ export const BuildWorkflowParameters = ({
const baseUrl = await discoveryApi.getBaseUrl('openchoreo-ci-backend');
// Use fetchApi which automatically injects Backstage + IDP tokens
const response = await fetchApi.fetch(
`${baseUrl}/workflow-schema?organizationName=${encodeURIComponent(
orgName,
`${baseUrl}/workflow-schema?namespaceName=${encodeURIComponent(
nsName,
)}&workflowName=${encodeURIComponent(selectedWorkflowName)}`,
);

Expand Down Expand Up @@ -154,7 +154,7 @@ export const BuildWorkflowParameters = ({
return () => {
ignore = true;
};
}, [selectedWorkflowName, organizationName, discoveryApi, fetchApi]);
}, [selectedWorkflowName, namespaceName, discoveryApi, fetchApi]);

// Sync schema to formData when workflow changes (not just when schema loads)
useEffect(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,11 @@ export const BuildWorkflowPicker = ({
const discoveryApi = useApi(discoveryApiRef);
const fetchApi = useApi(fetchApiRef);

// Get workflows from enum (if provided) or organizationName from ui:options
// Get workflows from enum (if provided) or namespaceName from ui:options
const enumWorkflows = (schema.enum as string[]) || null;
const organizationName =
typeof uiSchema?.['ui:options']?.organizationName === 'string'
? uiSchema['ui:options'].organizationName
const namespaceName =
typeof uiSchema?.['ui:options']?.namespaceName === 'string'
? uiSchema['ui:options'].namespaceName
: '';

// Fetch workflows from API if enum is not provided
Expand All @@ -65,8 +65,8 @@ export const BuildWorkflowPicker = ({
}

// Otherwise, fetch from API
if (!organizationName) {
setError('Organization name is required to fetch workflows');
if (!namespaceName) {
setError('Namespace name is required to fetch workflows');
return;
}

Expand All @@ -76,19 +76,17 @@ export const BuildWorkflowPicker = ({
try {
const baseUrl = await discoveryApi.getBaseUrl('openchoreo-ci-backend');

// Extract organization name if it's in entity reference format
const extractOrgName = (fullOrgName: string): string => {
const parts = fullOrgName.split('/');
// Extract namespace name if it's in entity reference format
const extractNsName = (fullNsName: string): string => {
const parts = fullNsName.split('/');
return parts[parts.length - 1];
};

const orgName = extractOrgName(organizationName);
const nsName = extractNsName(namespaceName);

// Use fetchApi which automatically injects Backstage + IDP tokens
const response = await fetchApi.fetch(
`${baseUrl}/workflows?organizationName=${encodeURIComponent(
orgName,
)}`,
`${baseUrl}/workflows?namespaceName=${encodeURIComponent(nsName)}`,
);

if (!response.ok) {
Expand Down Expand Up @@ -117,7 +115,7 @@ export const BuildWorkflowPicker = ({
return () => {
ignore = true;
};
}, [organizationName, enumWorkflows, discoveryApi, fetchApi]);
}, [namespaceName, enumWorkflows, discoveryApi, fetchApi]);

const handleChange = (event: ChangeEvent<{ value: unknown }>) => {
const selectedWorkflow = event.target.value as string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,13 @@ export const ComponentNamePicker = ({
const [touched, setTouched] = useState(false);
const catalogApi = useApi(catalogApiRef);

// Get the organization name from form context
const organizationName = formContext.formData?.organization_name;
// Get the namespace name from form context
const namespaceName = formContext.formData?.namespace_name;

// Extract organization name from entity reference format
const extractOrgName = useCallback((fullOrgName: string): string => {
if (!fullOrgName) return '';
const parts = fullOrgName.split('/');
// Extract namespace name from entity reference format
const extractNsName = useCallback((fullNsName: string): string => {
if (!fullNsName) return '';
const parts = fullNsName.split('/');
return parts[parts.length - 1];
}, []);

Expand Down Expand Up @@ -82,10 +82,10 @@ export const ComponentNamePicker = ({
return null;
}, []);

// Check if component already exists in the organization
// Check if component already exists in the namespace
const checkComponentExists = useCallback(
async (componentName: string, orgName: string): Promise<boolean> => {
if (!componentName || !orgName) {
async (componentName: string, nsName: string): Promise<boolean> => {
if (!componentName || !nsName) {
return false;
}

Expand All @@ -97,12 +97,11 @@ export const ComponentNamePicker = ({
},
});

// Filter components by organization annotation and check if name exists
// Filter components by namespace annotation and check if name exists
const existsInOrg = items.some(
component =>
component.metadata.annotations?.[
CHOREO_ANNOTATIONS.ORGANIZATION
] === orgName && component.metadata.name === componentName,
component.metadata.annotations?.[CHOREO_ANNOTATIONS.NAMESPACE] ===
nsName && component.metadata.name === componentName,
);

return existsInOrg;
Expand All @@ -126,13 +125,13 @@ export const ComponentNamePicker = ({
return;
}

if (!componentName || !organizationName) {
if (!componentName || !namespaceName) {
setValidationState({ error: null, isValidating: false });
return;
}

const orgName = extractOrgName(organizationName);
if (!orgName) {
const nsName = extractNsName(namespaceName);
if (!nsName) {
setValidationState({ error: null, isValidating: false });
return;
}
Expand All @@ -141,11 +140,11 @@ export const ComponentNamePicker = ({
setValidationState({ error: null, isValidating: true });

// Check if component exists
const exists = await checkComponentExists(componentName, orgName);
const exists = await checkComponentExists(componentName, nsName);

if (exists) {
setValidationState({
error: `A component named "${componentName}" already exists in organization "${orgName}"`,
error: `A component named "${componentName}" already exists in namespace "${nsName}"`,
isValidating: false,
});
} else {
Expand All @@ -159,10 +158,10 @@ export const ComponentNamePicker = ({
return () => clearTimeout(timeoutId);
}, [
formData,
organizationName,
namespaceName,
validateFormat,
checkComponentExists,
extractOrgName,
extractNsName,
]);

const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export const NoTraitsAvailableMessage = () => {
<Card variant="outlined" className={classes.card}>
<CardContent>
<Typography variant="h6" gutterBottom className={classes.heading}>
No Traits Available for This Organization
No Traits Available for This Namespace
</Typography>
<Typography variant="body2" paragraph>
Traits are cross-cutting capabilities that extend components without
Expand Down
Loading