Skip to content

Commit

Permalink
New route + UI to soft delete a tracker
Browse files Browse the repository at this point in the history
  • Loading branch information
PopDaph committed Dec 19, 2024
1 parent 6a1c63c commit 5ec239d
Show file tree
Hide file tree
Showing 2 changed files with 118 additions and 40 deletions.
65 changes: 63 additions & 2 deletions front/components/trackers/TrackerBuilder.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
useSendNotification,
} from "@dust-tt/sparkle";
import type {
APIError,
DataSourceViewSelectionConfiguration,
DataSourceViewType,
SpaceType,
Expand All @@ -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,
Expand All @@ -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);

Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -284,7 +336,16 @@ export const TrackerBuilder = ({
<div className="mx-auto flex w-full max-w-4xl flex-col gap-16 pb-12">
<div className="flex">
<div className="flex flex-grow" />
<div className="flex flex-shrink-0 flex-col justify-end">
<div className="flex flex-shrink-0 gap-2">
{initialTrackerId && (
<Button
label={"Delete"}
variant="warning"
onClick={onDelete}
isLoading={isDeleting}
disabled={isSubmitting || isDeleting}
/>
)}
<AdvancedSettings
owner={owner}
plan={subscription.plan}
Expand Down
93 changes: 55 additions & 38 deletions front/pages/api/w/[wId]/spaces/[spaceId]/trackers/[tId]/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ import { PostTrackersRequestBodySchema } from "@app/pages/api/w/[wId]/spaces/[sp

async function handler(
req: NextApiRequest,
res: NextApiResponse<WithAPIErrorResponse<GetTrackersResponseBody>>,
res: NextApiResponse<
WithAPIErrorResponse<GetTrackersResponseBody | { success: true }>
>,
auth: Authenticator,
space: SpaceResource
): Promise<void> {
Expand Down Expand Up @@ -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, {
Expand All @@ -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,
Expand All @@ -105,7 +105,6 @@ async function handler(
}

const body = bodyValidation.right;

const updatedTrackerRes = await tracker.updateConfig(
auth,
{
Expand Down Expand Up @@ -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.",
},
});
}
Expand Down

0 comments on commit 5ec239d

Please sign in to comment.