Skip to content
This repository has been archived by the owner on Mar 12, 2024. It is now read-only.

Commit

Permalink
Feature/granular settings (#402)
Browse files Browse the repository at this point in the history
  • Loading branch information
EstebanDalelR authored Dec 13, 2023
1 parent 9ded9eb commit d46c305
Show file tree
Hide file tree
Showing 6 changed files with 208 additions and 161 deletions.
206 changes: 112 additions & 94 deletions app/(loggedIn)/settings/form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,130 +3,148 @@
import { useEffect, useState } from "react";
import getUserSettings from "../../../utils/api/getUserSettings";

let defaultState = {
AISummary: 1,
CodeComments: 1,
Badges: 1,
SearchAmount: 3,
ResponseTexts: 1,
};
export default function form({ userEmail }) {
const [saveDisabled, setSaveDisabled] = useState(false);
const [formState, setFormState] = useState(defaultState);

useEffect(() => {
setUserSettingsState(userEmail);
}, [userEmail]);

const setUserSettingsState = async (userEmail) => {
let settings = await getUserSettings(userEmail);
setFormState(settings);
};
const services = [
{
valueLabel: "JiraTickets",
label: "Jira Tickets",
},
{
valueLabel: "SlackMessages",
label: "Slack Messages",
},
{
valueLabel: "GitHubPRs",
label: "GitHub PRs",
},
{
valueLabel: "NotionPages",
label: "Notion Pages",
},
{
valueLabel: "LinearTickets",
label: "Linear Tickets",
},
{
valueLabel: "ConfluenceDocs",
label: "Confluence Docs",
},
{
valueLabel: "AsanaTasks",
label: "Asana Tasks",
},
];
let defaultState = {
AISummary: 1,
const setDefault = () => {
setFormState(defaultState);
};
services.map((service) => (defaultState[service.valueLabel] = 3));
const [formState, setFormState] = useState(defaultState);
const handleSubmit = async () => {
const handleSubmit = async (e) => {
setSaveDisabled(true);
e.preventDefault();

try {
const response = await fetch("/api/user/updateSettings", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ userSettings: formState, email: userEmail }),
body: JSON.stringify({
userSettings: formState,
email: userEmail,
}),
}).then((res) => setUserSettingsState(userEmail));
} catch (error) {
console.error("An error occurred while saving the form", error);
} finally {
setSaveDisabled(false);
}
};
useEffect(() => {
setUserSettingsState(userEmail);
}, [userEmail]);

function SettingsSelector({ label, valueLabel }) {
return (
<div style={{ display: "flex", alignItems: "center" }}>
{" "}
<span style={{ width: "100px" }}>{label}</span>{" "}
<select
className="form-select mt-2"
aria-label={label}
defaultValue={formState[valueLabel]}
onChange={(e) =>
setFormState({
...formState,
[valueLabel]: parseInt(e.target.value),
})
}
value={formState[valueLabel]}
>
{" "}
{Array.from({ length: 5 }, (_, index) => (
<option key={index} value={index + 1}>
{" "}
{index + 1}{" "}
</option>
))}{" "}
</select>{" "}
</div>
);
}
return (
<form>
{services.map((service) => (
<SettingsSelector
key={service.valueLabel}
valueLabel={service.valueLabel}
label={service.label}
/>
))}
<div style={{ display: "flex", alignItems: "center" }}>
<span>AI Summary: </span>
const handleChange = (e) => {
setFormState({ ...formState, [e.target.name]: e.target.value });
};
const ActivationDropdown = ({ name, ariaLabel, formStateName }) => (
<div>
<label htmlFor={`name`} className="d-flex flex-items-center">
{ariaLabel}:
<select
className="form-select ml-3 mt-2"
aria-label="AI Summary"
value={formState.AISummary}
onChange={(e) =>
setFormState({
...formState,
AISummary: parseInt(e.target.value),
})
}
aria-label={ariaLabel}
id={name}
onChange={handleChange}
value={formState[formStateName]}
name={name}
>
<option value={1}>Active</option>
<option value={0}>Inactive</option>
</select>
</label>
</div>
);

return (
<form onSubmit={handleSubmit}>
<div>
<div
className="Subhead"
title="This is a tooltip that if hovered will explain what it does"
>
<h3 className="Subhead-heading">Watermelon AI</h3>
</div>
<div style={{ display: "flex", alignItems: "center" }}>
<div className="form-group-header">
<h4>PR Comment</h4>
</div>
</div>
<ActivationDropdown
name="AISummary"
ariaLabel="AI Summary"
formStateName="AISummary"
/>
<ActivationDropdown
name="CodeComments"
ariaLabel="Code Comments"
formStateName="CodeComments"
/>
<ActivationDropdown
name="Badges"
ariaLabel="Badges"
formStateName="Badges"
/>
</div>
<button
className="btn btn-primary"
type="button"
disabled={saveDisabled}
onClick={handleSubmit}
<div>
<div
className="Subhead"
title="This is a tooltip that if hovered will explain what it does"
>
<h3 className="Subhead-heading">Search results</h3>
</div>
<label htmlFor={`SearchAmount`} className="d-flex flex-items-center">
Number of results per platform:
<select
className="form-select select-sm mt-2"
onChange={handleChange}
value={formState.SearchAmount}
name={`SearchAmount`}
id={`SearchAmount`}
style={{ width: "15ch" }}
>
{Array.from({ length: 5 }, (_, index) => (
<option key={index} value={index + 1}>
{index + 1}
</option>
))}
</select>
</label>

<ActivationDropdown
name="ResponseTexts"
ariaLabel="Response Texts"
formStateName="ResponseTexts"
/>
</div>

<div
className="d-flex flex-row-reverse"
style={{ bottom: "1rem", right: "1rem", position: "sticky", zIndex: 3 }}
>
{saveDisabled ? "Saving..." : "Save"}
</button>
<button
className="btn btn-primary"
type="submit"
disabled={saveDisabled}
>
{saveDisabled ? "Saving..." : "Save"}
</button>
<button type="button" className="btn mx-2" onClick={setDefault}>
Reset to default
</button>
</div>
</form>
);
}
62 changes: 38 additions & 24 deletions app/api/actions/github/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@ import randomText from "../../../../utils/actions/markdownHelpers/randomText";
import createTeamAndMatchUser from "../../../../utils/db/teams/createTeamAndMatchUser";
import sendUninstall from "../../../../utils/sendgrid/sendUninstall";



const app = new App({
appId: process.env.GITHUB_APP_ID!,
privateKey: process.env.GITHUB_PRIVATE_KEY!,
Expand Down Expand Up @@ -70,7 +68,7 @@ export async function POST(request: Request) {

if (pull_request.user.type === "Bot") {
return new Response("We don't comment on bot PRs", {
status: 400
status: 400,
});
}

Expand Down Expand Up @@ -313,6 +311,9 @@ export async function POST(request: Request) {
watermelon_user,
AISummary,
user_email,
ResponseTexts,
CodeComments,
Badges,
} = serviceAnswers;
if (error) {
return failedToFetchResponse({
Expand Down Expand Up @@ -381,42 +382,49 @@ export async function POST(request: Request) {
textToWrite += generalMarkdownHelper({
value: github,
userLogin,
ResponseTexts,
systemName: "GitHub",
systemResponseName: "GitHub PRs",
});
textToWrite += generalMarkdownHelper({
value: jira,
userLogin,
ResponseTexts,
systemName: "Jira",
systemResponseName: "Jira Tickets",
});
textToWrite += generalMarkdownHelper({
value: confluence,
userLogin,
ResponseTexts,
systemName: "Confluence",
systemResponseName: "Confluence Docs",
});
textToWrite += generalMarkdownHelper({
value: slack,
userLogin,
ResponseTexts,
systemName: "Slack",
systemResponseName: "Slack Threads",
});
textToWrite += generalMarkdownHelper({
value: notion,
userLogin,
ResponseTexts,
systemName: "Notion",
systemResponseName: "Notion Pages",
});
textToWrite += generalMarkdownHelper({
value: linear,
userLogin,
ResponseTexts,
systemName: "Linear",
systemResponseName: "Linear Tickets",
});
textToWrite += generalMarkdownHelper({
value: asana,
userLogin,
ResponseTexts,
systemName: "Asana",
systemResponseName: "Asana Tasks",
});
Expand All @@ -428,27 +436,31 @@ export async function POST(request: Request) {
textToWrite += randomText();
Promise.all([
// Detect console.logs and its equivalent in other languages
detectConsoleLogs({
prTitle: title,
businessLogicSummary,
repo,
owner,
issue_number: number,
installationId,
reqUrl: request.url,
reqEmail: req.email,
}),
CodeComments
? detectConsoleLogs({
prTitle: title,
businessLogicSummary,
repo,
owner,
issue_number: number,
installationId,
reqUrl: request.url,
reqEmail: req.email,
})
: null,
// Make Watermelon Review the PR's business logic here by comparing the title with the AI-generated summary
labelPullRequest({
prTitle: title,
businessLogicSummary,
repo,
owner,
issue_number: number,
installationId,
reqUrl: request.url,
reqEmail: req.email,
}),
Badges
? labelPullRequest({
prTitle: title,
businessLogicSummary,
repo,
owner,
issue_number: number,
installationId,
reqUrl: request.url,
reqEmail: req.email,
})
: null,
addActionLog({
randomWords,
github,
Expand Down Expand Up @@ -557,7 +569,9 @@ export async function POST(request: Request) {

// Find our bot's comment
let botComment = comments.data.find((comment) => {
return comment?.user?.login.includes("watermelon-copilot-for-code-review");
return comment?.user?.login.includes(
"watermelon-copilot-for-code-review"
);
});

// Update the existing comment
Expand Down
Loading

0 comments on commit d46c305

Please sign in to comment.