Skip to content
Merged
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
21 changes: 17 additions & 4 deletions src/components/component-definitions/CapabilityCreateForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,8 @@ const capability = ref({
// controlImplementations: [],
});

const { data: newCapability, execute } = useDataApi<Capability>(
`/api/oscal/component-definitions/${props.componentDefinitionId}/capability`,
const { execute } = useDataApi<Capability[]>(
`/api/oscal/component-definitions/${props.componentDefinitionId}/capabilities`,
{
method: 'POST',
transformRequest: [decamelizeKeys],
Expand Down Expand Up @@ -139,10 +139,23 @@ async function createCapability(): Promise<void> {
// Skip incorporatesComponents, controlImplementations - they may not exist in DB schema
};

await execute({
const response = await execute({
data: capabilityData,
});
emit('created', newCapability.value!);

// Use response data directly to avoid race condition with data ref updates
if (!response.data.value?.data || response.data.value.data.length === 0) {
throw new Error('No capability was created. Please try again.');
}

const createdCapabilityData = response.data.value.data[0];

// Validate that the created capability has a UUID
if (!createdCapabilityData.uuid) {
throw new Error('Created capability is missing UUID. Please try again.');
}

emit('created', createdCapabilityData);
} catch (error) {
toast.add({
severity: 'error',
Expand Down
38 changes: 29 additions & 9 deletions src/components/component-definitions/ComponentCreateForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,7 @@ import { BIconArrowRepeat } from 'bootstrap-icons-vue';
import { v4 as uuidv4 } from 'uuid';
import { useToast } from 'primevue/usetoast';
import { useDataApi, decamelizeKeys } from '@/composables/axios';
import type { AxiosError } from 'axios';
import type { ErrorBody, ErrorResponse } from '@/stores/types';
import { AxiosError } from 'axios';

const toast = useToast();

Expand All @@ -116,7 +115,7 @@ const component = ref({
// controlImplementations: [],
});

const { data: createdComponent, execute } = useDataApi<DefinedComponent>(
const { execute } = useDataApi<DefinedComponent[]>(
`/api/oscal/component-definitions/${props.componentDefinitionId}/components`,
{ method: 'POST', transformRequest: [decamelizeKeys] },
{ immediate: false },
Expand Down Expand Up @@ -155,21 +154,42 @@ async function createComponent(): Promise<void> {
// Skip responsibleRoles, protocols, controlImplementations - they don't exist in DB schema
};

await execute({
const response = await execute({
data: [componentData],
});

// Use response data directly to avoid race condition with data ref updates
if (!response.data.value?.data || response.data.value.data.length === 0) {
throw new Error('No component was created. Please try again.');
}

const createdComponentData = response.data.value.data[0];

// Validate that the created component has a UUID
if (!createdComponentData.uuid) {
throw new Error('Created component is missing UUID. Please try again.');
}

toast.add({
severity: 'success',
summary: 'Component created successfully',
detail: `Component ${component.value.title} has been created.`,
life: 3000,
});
emit('created', createdComponent.value!);
emit('created', createdComponentData);
} catch (error) {
const errorResponse = error as AxiosError<ErrorResponse<ErrorBody>>;
const errorText =
errorResponse.response?.data.errors.body ||
'An error occurred while creating the component.';
let errorText = 'An error occurred while creating the component.';

if (error instanceof AxiosError) {
const axiosError = error as AxiosError<{ errors?: { body?: string } }>;
const bodyMessage = axiosError.response?.data?.errors?.body;
if (typeof bodyMessage === 'string' && bodyMessage.trim().length > 0) {
errorText = bodyMessage;
}
} else if (error instanceof Error) {
errorText = error.message;
}

toast.add({
severity: 'error',
summary: 'Error creating component',
Expand Down
2 changes: 1 addition & 1 deletion src/stores/component-definitions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ export const useComponentDefinitionStore = defineStore(
const config = await configStore.getConfig();
const payload = decamelizeKeys(capability, { separator: '-' });
const response = await fetch(
`${config.API_URL}/api/oscal/component-definitions/${id}/capability`,
`${config.API_URL}/api/oscal/component-definitions/${id}/capabilities`,
{
method: 'POST',
headers: {
Expand Down