diff --git a/front/components/trackers/TrackerBuilder.tsx b/front/components/trackers/TrackerBuilder.tsx
index 2e8406877b8ac..faf9e0890c644 100644
--- a/front/components/trackers/TrackerBuilder.tsx
+++ b/front/components/trackers/TrackerBuilder.tsx
@@ -11,6 +11,7 @@ import {
useSendNotification,
} from "@dust-tt/sparkle";
import type {
+ APIError,
DataSourceViewSelectionConfiguration,
DataSourceViewType,
SpaceType,
@@ -24,9 +25,10 @@ import {
TRACKER_FREQUENCIES,
} from "@dust-tt/types";
import { useRouter } from "next/router";
-import { useMemo, useState } from "react";
+import { useContext, useMemo, useState } from "react";
import { AdvancedSettings } from "@app/components/assistant_builder/InstructionScreen";
+import { ConfirmContext } from "@app/components/Confirm";
import AppLayout from "@app/components/sparkle/AppLayout";
import {
AppLayoutSimpleCloseTitle,
@@ -53,10 +55,12 @@ export const TrackerBuilder = ({
initialTrackerId: string | null;
}) => {
const router = useRouter();
+ const confirm = useContext(ConfirmContext);
const sendNotification = useSendNotification();
const [edited, setEdited] = useState(false);
const [isSubmitting, setIsSubmitting] = useState(false);
+ const [isDeleting, setIsDeleting] = useState(false);
const [showMaintainedDsModal, setShowMaintainedDsModal] = useState(false);
const [showWatchedDsModal, setShowWatchedDataSourcesModal] = useState(false);
@@ -205,6 +209,54 @@ export const TrackerBuilder = ({
});
};
+ const onDelete = async () => {
+ if (!initialTrackerId) {
+ // Should never happen.
+ sendNotification({
+ title: "Failed to delete tracker",
+ description: "Can't delete a tracker that hasn't been created yet.",
+ type: "error",
+ });
+ return;
+ }
+
+ if (
+ await confirm({
+ title: "This can't be undone",
+ message: "Are you sure you want to delete this tracker?",
+ validateVariant: "warning",
+ })
+ ) {
+ setIsDeleting(true);
+ const res = await fetch(
+ `/api/w/${owner.sId}/spaces/${globalSpace.sId}/trackers/${initialTrackerId}`,
+ {
+ method: "DELETE",
+ }
+ );
+ if (res.ok) {
+ setIsDeleting(false);
+ void router.push(`/w/${owner.sId}/assistant/labs/trackers`);
+ sendNotification({
+ title: "Tracker deleted",
+ description: "Tracker successfully deleted.",
+ type: "success",
+ });
+ } else {
+ setIsDeleting(false);
+ const err = (await res.json()) as { error: APIError };
+ sendNotification({
+ title: "Failed to delete tracker",
+ description: err.error.message,
+ type: "error",
+ });
+ }
+ return true;
+ } else {
+ return false;
+ }
+ };
+
const trackableDataSourcesViews = useMemo(
() =>
dataSourceViews.filter(
@@ -284,7 +336,16 @@ export const TrackerBuilder = ({
-
+
+ {initialTrackerId && (
+
+ )}
>,
+ res: NextApiResponse<
+ WithAPIErrorResponse
+ >,
auth: Authenticator,
space: SpaceResource
): Promise {
@@ -45,29 +47,42 @@ async function handler(
},
});
}
+
+ if (!space.canWrite(auth)) {
+ return apiError(req, res, {
+ status_code: 403,
+ api_error: {
+ type: "workspace_auth_error",
+ message: "Missing permission to edit the space's trackers.",
+ },
+ });
+ }
+
+ if (typeof req.query.tId !== "string") {
+ return apiError(req, res, {
+ status_code: 400,
+ api_error: {
+ type: "invalid_request_error",
+ message: "Invalid tracker id provided.",
+ },
+ });
+ }
+ const trackerId = req.query.tId;
+ const tracker = await TrackerConfigurationResource.fetchById(auth, trackerId);
+
+ if (!tracker) {
+ return apiError(req, res, {
+ status_code: 404,
+ api_error: {
+ type: "invalid_request_error",
+ message: "Tracker not found.",
+ },
+ });
+ }
+
switch (req.method) {
case "PATCH":
- if (!space.canWrite(auth)) {
- return apiError(req, res, {
- status_code: 403,
- api_error: {
- type: "workspace_auth_error",
- message: "Missing permission to edit the space's trackers.",
- },
- });
- }
- if (typeof req.query.tId !== "string") {
- return apiError(req, res, {
- status_code: 400,
- api_error: {
- type: "invalid_request_error",
- message: "Invalid tracker id provided.",
- },
- });
- }
- const trackerId = req.query.tId;
const bodyValidation = PostTrackersRequestBodySchema.decode(req.body);
-
if (isLeft(bodyValidation)) {
const pathError = reporter.formatValidationErrors(bodyValidation.left);
return apiError(req, res, {
@@ -79,21 +94,6 @@ async function handler(
});
}
- const tracker = await TrackerConfigurationResource.fetchById(
- auth,
- trackerId
- );
-
- if (!tracker) {
- return apiError(req, res, {
- status_code: 404,
- api_error: {
- type: "invalid_request_error",
- message: "Tracker not found.",
- },
- });
- }
-
if (!tracker.canWrite(auth)) {
return apiError(req, res, {
status_code: 403,
@@ -105,7 +105,6 @@ async function handler(
}
const body = bodyValidation.right;
-
const updatedTrackerRes = await tracker.updateConfig(
auth,
{
@@ -136,12 +135,30 @@ async function handler(
},
});
+ case "DELETE":
+ const deletedTrackerRes = await tracker.delete(auth, {
+ hardDelete: false,
+ });
+ if (deletedTrackerRes.isOk()) {
+ return res.status(201).json({
+ success: true,
+ });
+ }
+ return apiError(req, res, {
+ status_code: 500,
+ api_error: {
+ type: "internal_server_error",
+ message: "Failed to delete tracker.",
+ },
+ });
+
default:
return apiError(req, res, {
status_code: 405,
api_error: {
type: "method_not_supported_error",
- message: "The method passed is not supported, PATCH is expected.",
+ message:
+ "The method passed is not supported, PATCH or DELETE is expected.",
},
});
}