Skip to content

Commit

Permalink
feat: review instructions
Browse files Browse the repository at this point in the history
ability to add review instructions
  • Loading branch information
marcelovicentegc committed Mar 3, 2024
1 parent 46fa01f commit 1b4ed68
Show file tree
Hide file tree
Showing 4 changed files with 165 additions and 19 deletions.
74 changes: 72 additions & 2 deletions app/api/vendors/route.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import crypto from "crypto";
import { NextResponse } from "next/server";
import { authOptions } from "../auth/[...nextauth]/route";
import { saveApiKeys } from "@/lib/db/writes";
import { saveApiKeys, updateApiKey } from "@/lib/db/writes";
import { encrypt } from "@/lib/encryption";
import { getServerSession } from "next-auth/next";

Expand All @@ -13,7 +13,8 @@ export async function POST(req) {
}

try {
const { vendorName, vendorUrl, vendorCallbackUrl } = await req.json();
const { vendorName, vendorUrl, vendorCallbackUrl, reviewInstructions } =
await req.json();

if (!vendorUrl) {
throw new Error("You must enter a vendor URL.");
Expand Down Expand Up @@ -49,6 +50,7 @@ export async function POST(req) {
vendorName,
vendorUrl,
vendorCallbackUrl,
reviewInstructions,
createdBy: session.user.email,
};

Expand All @@ -73,3 +75,71 @@ export async function POST(req) {
});
}
}

export async function PATCH(req) {
const session = await getServerSession(authOptions);

if (!session) {
return new NextResponse(JSON.stringify([]), { status: 401 });
}

try {
const {
vendorName,
vendorUrl,
vendorCallbackUrl,
reviewInstructions,
_id,
} = await req.json();

if (!_id) {
throw new Error("An object ID must be present.");
}

if (!vendorUrl) {
throw new Error("You must enter a vendor URL.");
}

if (!vendorName) {
throw new Error("You must enter a vendor name.");
}

if (!vendorCallbackUrl) {
throw new Error("You must enter a vendor callback URL.");
}

// Validate URL
new URL(vendorUrl);

// Validate callback URL
new URL(vendorCallbackUrl);

const data = {
_id,
vendorName,
vendorUrl,
vendorCallbackUrl,
reviewInstructions,
};

const result = await updateApiKey(data);

if (!result?.modifiedCount) {
console.error("Failed to update API key");

return new NextResponse("Error", {
status: 500,
});
}

return new NextResponse("Success", {
status: 201,
});
} catch (error) {
console.error(error);

return new NextResponse("Error", {
status: 500,
});
}
}
85 changes: 70 additions & 15 deletions containers/api-management.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
Text,
TextInput,
} from "grommet";
import { useState } from "react";
import { useEffect, useState } from "react";
import { StatusGood, More } from "grommet-icons";
import { useRefreshData } from "@/lib/hooks";

Expand All @@ -28,43 +28,64 @@ export default function ApiManagementContainer(props) {
const { refresh } = useRefreshData();

const [open, setOpen] = useState(false);
const [editMode, setEditMode] = useState(false);
const [submitting, setSubmitting] = useState(false);

const onOpen = () => setOpen(true);
const onClose = () => setOpen(false);

useEffect(() => {
if (editMode) {
setOpen(true);
}
}, [editMode]);

useEffect(() => {
if (!open) {
setEditMode(false);
}
}, [open]);

const onSubmit = async (event) => {
setSubmitting(true);
const {
value: { vendorName, vendorUrl, vendorCallbackUrl },
value: { vendorName, vendorUrl, vendorCallbackUrl, reviewInstructions },
} = event;

const formattedUrl = new URL(vendorUrl);

const data = {
_id: editMode?._id,
vendorName,
vendorUrl: formattedUrl.origin,
vendorCallbackUrl,
reviewInstructions,
};

const response = await fetch("/api/vendors", {
method: "POST",
method: editMode ? "PATCH" : "POST",
body: JSON.stringify(data),
});

if (response.ok) {
onClose();
if (!editMode) {
onClose();

const data = await response.json();
const data = await response.json();

prompt(
`
prompt(
`
This is the only time you will see this API key,
so make sure you copy it and store it somewhere safe.`,
JSON.stringify(data),
);
JSON.stringify(data),
);

refresh();
refresh();
} else {
onClose();
alert("Updated successfully");
refresh();
}
}

setSubmitting(false);
Expand Down Expand Up @@ -114,7 +135,20 @@ export default function ApiManagementContainer(props) {
key={index}
icon={<More />}
hoverIndicator
items={[{ label: "Delete" }]}
items={[
{
label: "Delete",
onClick: () => {
// @todo delete vendor
},
},
{
label: "Edit",
onClick: () => {
setEditMode(item);
},
},
]}
/>
)}
/>
Expand All @@ -123,13 +157,14 @@ export default function ApiManagementContainer(props) {
onClose={onClose}
onSubmit={onSubmit}
submitting={submitting}
editMode={editMode}
/>
</>
);
}

function Form(props) {
const { onClose, open, onSubmit, submitting } = props;
const { onClose, open, onSubmit, submitting, editMode } = props;

return (
<FormPopUp
Expand Down Expand Up @@ -161,7 +196,7 @@ function Form(props) {
},
]}
>
<TextInput name="vendorName" />
<TextInput name="vendorName" value={editMode?.name} />
</FormField>
<FormField
label="Vendor URL"
Expand All @@ -188,7 +223,12 @@ function Form(props) {
},
]}
>
<TextInput name="vendorUrl" aria-label="url" type="url" />
<TextInput
name="vendorUrl"
aria-label="url"
type="url"
value={editMode?.url}
/>
</FormField>
<FormField
label="Callback URL"
Expand All @@ -215,7 +255,22 @@ function Form(props) {
},
]}
>
<TextInput name="vendorCallbackUrl" aria-label="url" type="url" />
<TextInput
name="vendorCallbackUrl"
aria-label="url"
type="url"
value={editMode?.callbackUrl}
/>
</FormField>
<FormField
label="Instructions for review"
name="reviewInstructions"
required
>
<TextInput
name="reviewInstructions"
value={editMode?.reviewInstructions}
/>
</FormField>
</FormPopUp>
);
Expand Down
5 changes: 4 additions & 1 deletion lib/db/reads.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export async function getApiKey(vendorId) {
/**
* Gets a shallow version of all API keys.
*
* @returns {Promise<{ name: string, callbackUrl: string }[]>
* @returns {Promise<{ name: string, callbackUrl: string, reviewInstructions: string }[]>
*/
export async function getApiKeys() {
const collection = await getApiKeysCollection();
Expand All @@ -75,8 +75,11 @@ export async function getApiKeys() {
await cursor.close();

const vendors = result.map((apiKey) => ({
_id: apiKey._id?.toString(),
name: apiKey.vendorName,
callbackUrl: apiKey.vendorCallbackUrl,
url: apiKey.vendorUrl,
reviewInstructions: apiKey?.reviewInstructions,
}));

return vendors;
Expand Down
20 changes: 19 additions & 1 deletion lib/db/writes.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ export async function saveCompletion(completionData) {
/**
* Inserts an API key created from the API Management page into the database.
*
* @param data The API key data to save.
* @param data The API key data to save.
*/
export async function saveApiKeys(data) {
const collection = await getApiKeysCollection();
Expand All @@ -128,3 +128,21 @@ export async function saveApiKeys(data) {

return result;
}

/**
* Updates an API key in the database.
*
* @param data
*/
export async function updateApiKey(data) {
const collection = await getApiKeysCollection();

const { _id, ...rest } = data;

const result = await collection.updateOne(
{ _id: new ObjectId(_id) },
{ $set: { ...rest, updatedAt: new Date().toISOString() } },
);

return result;
}

0 comments on commit 1b4ed68

Please sign in to comment.