mirror of
https://github.com/hexastack/hexabot
synced 2025-04-25 08:50:43 +00:00
feat: nlp samples bulk delete
This commit is contained in:
parent
fde4224703
commit
bf12f0de64
@ -429,4 +429,45 @@ describe('NlpSampleController', () => {
|
|||||||
expect(result).toEqual({ success: true });
|
expect(result).toEqual({ success: true });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
describe('deleteMany', () => {
|
||||||
|
it('should delete multiple nlp samples', async () => {
|
||||||
|
const samplesToDelete = [
|
||||||
|
(
|
||||||
|
await nlpSampleService.findOne({
|
||||||
|
text: 'How much does a BMW cost?',
|
||||||
|
})
|
||||||
|
).id,
|
||||||
|
(
|
||||||
|
await nlpSampleService.findOne({
|
||||||
|
text: 'text1',
|
||||||
|
})
|
||||||
|
).id,
|
||||||
|
];
|
||||||
|
|
||||||
|
const result = await nlpSampleController.deleteMany(samplesToDelete);
|
||||||
|
|
||||||
|
expect(result.deletedCount).toEqual(samplesToDelete.length);
|
||||||
|
const remainingSamples = await nlpSampleService.find({
|
||||||
|
_id: { $in: samplesToDelete },
|
||||||
|
});
|
||||||
|
expect(remainingSamples.length).toBe(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw BadRequestException when no IDs are provided', async () => {
|
||||||
|
await expect(nlpSampleController.deleteMany([])).rejects.toThrow(
|
||||||
|
BadRequestException,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw NotFoundException when provided IDs do not exist', async () => {
|
||||||
|
const nonExistentIds = [
|
||||||
|
'614c1b2f58f4f04c876d6b8d',
|
||||||
|
'614c1b2f58f4f04c876d6b8e',
|
||||||
|
];
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
nlpSampleController.deleteMany(nonExistentIds),
|
||||||
|
).rejects.toThrow(NotFoundException);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -37,6 +37,7 @@ import { LanguageService } from '@/i18n/services/language.service';
|
|||||||
import { CsrfInterceptor } from '@/interceptors/csrf.interceptor';
|
import { CsrfInterceptor } from '@/interceptors/csrf.interceptor';
|
||||||
import { LoggerService } from '@/logger/logger.service';
|
import { LoggerService } from '@/logger/logger.service';
|
||||||
import { BaseController } from '@/utils/generics/base-controller';
|
import { BaseController } from '@/utils/generics/base-controller';
|
||||||
|
import { DeleteResult } from '@/utils/generics/base-repository';
|
||||||
import { PageQueryDto } from '@/utils/pagination/pagination-query.dto';
|
import { PageQueryDto } from '@/utils/pagination/pagination-query.dto';
|
||||||
import { PageQueryPipe } from '@/utils/pagination/pagination-query.pipe';
|
import { PageQueryPipe } from '@/utils/pagination/pagination-query.pipe';
|
||||||
import { PopulatePipe } from '@/utils/pipes/populate.pipe';
|
import { PopulatePipe } from '@/utils/pipes/populate.pipe';
|
||||||
@ -321,6 +322,33 @@ export class NlpSampleController extends BaseController<
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes multiple NLP samples by their IDs.
|
||||||
|
* @param ids - IDs of NLP samples to be deleted.
|
||||||
|
* @returns A Promise that resolves to the deletion result.
|
||||||
|
*/
|
||||||
|
@CsrfCheck(true)
|
||||||
|
@Delete('')
|
||||||
|
@HttpCode(204)
|
||||||
|
async deleteMany(@Body('ids') ids: string[]): Promise<DeleteResult> {
|
||||||
|
if (!ids || ids.length === 0) {
|
||||||
|
throw new BadRequestException('No IDs provided for deletion.');
|
||||||
|
}
|
||||||
|
const deleteResult = await this.nlpSampleService.deleteMany({
|
||||||
|
_id: { $in: ids },
|
||||||
|
});
|
||||||
|
|
||||||
|
if (deleteResult.deletedCount === 0) {
|
||||||
|
this.logger.warn(
|
||||||
|
`Unable to delete NLP samples with provided IDs: ${ids}`,
|
||||||
|
);
|
||||||
|
throw new NotFoundException('NLP samples with provided IDs not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
this.logger.log(`Successfully deleted NLP samples with IDs: ${ids}`);
|
||||||
|
return deleteResult;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Imports NLP samples from a CSV file.
|
* Imports NLP samples from a CSV file.
|
||||||
*
|
*
|
||||||
|
@ -20,7 +20,7 @@ import {
|
|||||||
MenuItem,
|
MenuItem,
|
||||||
Stack,
|
Stack,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
import { GridColDef } from "@mui/x-data-grid";
|
import { GridColDef, GridRowSelectionModel } from "@mui/x-data-grid";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
|
||||||
import { DeleteDialog } from "@/app-components/dialogs";
|
import { DeleteDialog } from "@/app-components/dialogs";
|
||||||
@ -35,6 +35,7 @@ import {
|
|||||||
import { renderHeader } from "@/app-components/tables/columns/renderHeader";
|
import { renderHeader } from "@/app-components/tables/columns/renderHeader";
|
||||||
import { DataGrid } from "@/app-components/tables/DataGrid";
|
import { DataGrid } from "@/app-components/tables/DataGrid";
|
||||||
import { useDelete } from "@/hooks/crud/useDelete";
|
import { useDelete } from "@/hooks/crud/useDelete";
|
||||||
|
import { useDeleteMany } from "@/hooks/crud/useDeleteMany";
|
||||||
import { useFind } from "@/hooks/crud/useFind";
|
import { useFind } from "@/hooks/crud/useFind";
|
||||||
import { useGetFromCache } from "@/hooks/crud/useGet";
|
import { useGetFromCache } from "@/hooks/crud/useGet";
|
||||||
import { useConfig } from "@/hooks/useConfig";
|
import { useConfig } from "@/hooks/useConfig";
|
||||||
@ -91,6 +92,20 @@ export default function NlpSample() {
|
|||||||
toast.success(t("message.item_delete_success"));
|
toast.success(t("message.item_delete_success"));
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
const { mutateAsync: deleteNlpSamples } = useDeleteMany(
|
||||||
|
EntityType.NLP_SAMPLE,
|
||||||
|
{
|
||||||
|
onError: (error) => {
|
||||||
|
toast.error(error);
|
||||||
|
},
|
||||||
|
onSuccess: () => {
|
||||||
|
deleteDialogCtl.closeDialog();
|
||||||
|
setSelectedNlpSamples([]);
|
||||||
|
toast.success(t("message.item_delete_success"));
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
const [selectedNlpSamples, setSelectedNlpSamples] = useState<string[]>([]);
|
||||||
const { dataGridProps } = useFind(
|
const { dataGridProps } = useFind(
|
||||||
{ entity: EntityType.NLP_SAMPLE, format: Format.FULL },
|
{ entity: EntityType.NLP_SAMPLE, format: Format.FULL },
|
||||||
{
|
{
|
||||||
@ -242,6 +257,9 @@ export default function NlpSample() {
|
|||||||
},
|
},
|
||||||
actionColumns,
|
actionColumns,
|
||||||
];
|
];
|
||||||
|
const handleSelectionChange = (selection: GridRowSelectionModel) => {
|
||||||
|
setSelectedNlpSamples(selection as string[]);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Grid item xs={12}>
|
<Grid item xs={12}>
|
||||||
@ -249,7 +267,13 @@ export default function NlpSample() {
|
|||||||
<DeleteDialog
|
<DeleteDialog
|
||||||
{...deleteDialogCtl}
|
{...deleteDialogCtl}
|
||||||
callback={() => {
|
callback={() => {
|
||||||
if (deleteDialogCtl.data) deleteNlpSample(deleteDialogCtl.data);
|
if (selectedNlpSamples.length > 0) {
|
||||||
|
deleteNlpSamples(selectedNlpSamples);
|
||||||
|
setSelectedNlpSamples([]);
|
||||||
|
deleteDialogCtl.closeDialog();
|
||||||
|
} else if (deleteDialogCtl.data) {
|
||||||
|
deleteNlpSample(deleteDialogCtl.data);
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<NlpImportDialog {...getDisplayDialogs(importDialogCtl)} />
|
<NlpImportDialog {...getDisplayDialogs(importDialogCtl)} />
|
||||||
@ -346,12 +370,29 @@ export default function NlpSample() {
|
|||||||
{t("button.export")}
|
{t("button.export")}
|
||||||
</Button>
|
</Button>
|
||||||
) : null}
|
) : null}
|
||||||
|
{selectedNlpSamples.length > 0 && (
|
||||||
|
<Grid item>
|
||||||
|
<Button
|
||||||
|
startIcon={<DeleteIcon />}
|
||||||
|
variant="contained"
|
||||||
|
color="error"
|
||||||
|
onClick={() => deleteDialogCtl.openDialog(undefined)}
|
||||||
|
>
|
||||||
|
{t("button.delete")}
|
||||||
|
</Button>
|
||||||
|
</Grid>
|
||||||
|
)}
|
||||||
</ButtonGroup>
|
</ButtonGroup>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<Grid mt={3}>
|
<Grid mt={3}>
|
||||||
<DataGrid columns={columns} {...dataGridProps} />
|
<DataGrid
|
||||||
|
columns={columns}
|
||||||
|
{...dataGridProps}
|
||||||
|
checkboxSelection
|
||||||
|
onRowSelectionModelChange={handleSelectionChange}
|
||||||
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
);
|
);
|
||||||
|
Loading…
Reference in New Issue
Block a user