From 315579e8da06feaef8a98ae4e28244281cdcb193 Mon Sep 17 00:00:00 2001 From: "sweep-ai[bot]" <128439645+sweep-ai[bot]@users.noreply.github.com> Date: Sat, 18 Nov 2023 20:53:23 +0000 Subject: [PATCH 01/17] Create sweep.yaml --- sweep.yaml | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 sweep.yaml diff --git a/sweep.yaml b/sweep.yaml new file mode 100644 index 0000000..ada0e25 --- /dev/null +++ b/sweep.yaml @@ -0,0 +1,42 @@ +# Sweep AI turns bugs & feature requests into code changes (https://sweep.dev) +# For details on our config file, check out our docs at https://docs.sweep.dev/usage/config + +# This setting contains a list of rules that Sweep will check for. If any of these rules are broken in a new commit, Sweep will create an pull request to fix the broken rule. +rules: + - "All docstrings and comments should be up to date." +['All new business logic should have corresponding unit tests.', 'Refactor large functions to be more modular.', 'Add docstrings to all functions and file headers.'] + +# This is the branch that Sweep will develop from and make pull requests to. Most people use 'main' or 'master' but some users also use 'dev' or 'staging'. +branch: 'main' + +# By default Sweep will read the logs and outputs from your existing Github Actions. To disable this, set this to false. +gha_enabled: True + +# This is the description of your project. It will be used by sweep when creating PRs. You can tell Sweep what's unique about your project, what frameworks you use, or anything else you want. +# +# Example: +# +# description: sweepai/sweep is a python project. The main api endpoints are in sweepai/api.py. Write code that adheres to PEP8. +description: '' + +# This sets whether to create pull requests as drafts. If this is set to True, then all pull requests will be created as drafts and GitHub Actions will not be triggered. +draft: False + +# This is a list of directories that Sweep will not be able to edit. +blocked_dirs: [] + +# This is a list of documentation links that Sweep will use to help it understand your code. You can add links to documentation for any packages you use here. +# +# Example: +# +# docs: +# - PyGitHub: ["https://pygithub.readthedocs.io/en/latest/", "We use pygithub to interact with the GitHub API"] +docs: [] + +# Sandbox executes commands in a sandboxed environment to validate code changes after every edit to guarantee pristine code. For more details, see the [Sandbox](./sandbox) page. +sandbox: + install: + - trunk init + check: + - trunk fmt {file_path} || return 0 + - trunk check --fix --print-failures {file_path} From 6e699c7f72bc47a8a0f33ed9a3d3118918ee254e Mon Sep 17 00:00:00 2001 From: "sweep-ai[bot]" <128439645+sweep-ai[bot]@users.noreply.github.com> Date: Sat, 18 Nov 2023 20:53:24 +0000 Subject: [PATCH 02/17] Create sweep template --- .github/ISSUE_TEMPLATE/sweep-template.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/sweep-template.yml diff --git a/.github/ISSUE_TEMPLATE/sweep-template.yml b/.github/ISSUE_TEMPLATE/sweep-template.yml new file mode 100644 index 0000000..44116f5 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/sweep-template.yml @@ -0,0 +1,15 @@ +name: Sweep Issue +title: 'Sweep: ' +description: For small bugs, features, refactors, and tests to be handled by Sweep, an AI-powered junior developer. +labels: sweep +body: + - type: textarea + id: description + attributes: + label: Details + description: Tell Sweep where and what to edit and provide enough context for a new developer to the codebase + placeholder: | + Unit Tests: Write unit tests for . Test each function in the file. Make sure to test edge cases. + Bugs: The bug might be in . Here are the logs: ... + Features: the new endpoint should use the ... class from because it contains ... logic. + Refactors: We are migrating this function to ... version because ... \ No newline at end of file From d177ad30c8eabf784aaa4d6880890ddc28384c64 Mon Sep 17 00:00:00 2001 From: dialmedu Date: Fri, 24 Nov 2023 01:57:29 -0500 Subject: [PATCH 03/17] small fix, check that dataUrls are valid, when there is only text on the clipboard --- frontend/src/components/ImageUpload.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/frontend/src/components/ImageUpload.tsx b/frontend/src/components/ImageUpload.tsx index 4a46d99..451bc1a 100644 --- a/frontend/src/components/ImageUpload.tsx +++ b/frontend/src/components/ImageUpload.tsx @@ -106,7 +106,9 @@ function ImageUpload({ setReferenceImages }: Props) { // Convert images to data URLs and set the prompt images state Promise.all(files.map((file) => fileToDataURL(file))) .then((dataUrls) => { - setReferenceImages(dataUrls.map((dataUrl) => dataUrl as string)); + if(dataUrls.length > 0) { + setReferenceImages(dataUrls.map((dataUrl) => dataUrl as string)); + } }) .catch((error) => { // TODO: Display error to user From 7ef6a0b205c75010621b0cdf3350c111b921da0c Mon Sep 17 00:00:00 2001 From: Abi Raja Date: Sun, 26 Nov 2023 14:54:02 -0500 Subject: [PATCH 04/17] collect emails on hosted version --- frontend/package.json | 4 +- .../src/components/TermsOfServiceDialog.tsx | 82 ++++++++--- frontend/src/components/ui/alert-dialog.tsx | 139 ++++++++++++++++++ frontend/src/components/ui/checkbox.tsx | 28 ++++ frontend/src/config.ts | 3 + frontend/yarn.lock | 30 +++- 6 files changed, 263 insertions(+), 23 deletions(-) create mode 100644 frontend/src/components/ui/alert-dialog.tsx create mode 100644 frontend/src/components/ui/checkbox.tsx diff --git a/frontend/package.json b/frontend/package.json index ef840e7..40fed34 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -11,6 +11,8 @@ }, "dependencies": { "@codemirror/lang-html": "^6.4.6", + "@radix-ui/react-alert-dialog": "^1.0.5", + "@radix-ui/react-checkbox": "^1.0.4", "@radix-ui/react-dialog": "^1.0.5", "@radix-ui/react-icons": "^1.3.0", "@radix-ui/react-label": "^2.0.2", @@ -22,8 +24,8 @@ "classnames": "^2.3.2", "clsx": "^2.0.0", "codemirror": "^6.0.1", - "html2canvas": "^1.4.1", "copy-to-clipboard": "^3.3.3", + "html2canvas": "^1.4.1", "react": "^18.2.0", "react-dom": "^18.2.0", "react-dropzone": "^14.2.3", diff --git a/frontend/src/components/TermsOfServiceDialog.tsx b/frontend/src/components/TermsOfServiceDialog.tsx index 2bd3178..b812d26 100644 --- a/frontend/src/components/TermsOfServiceDialog.tsx +++ b/frontend/src/components/TermsOfServiceDialog.tsx @@ -1,26 +1,54 @@ +import React from "react"; import { - Dialog, - DialogClose, - DialogContent, - DialogFooter, - DialogHeader, - DialogTitle, -} from "@/components/ui/dialog"; + AlertDialog, + AlertDialogAction, + AlertDialogContent, + AlertDialogFooter, + AlertDialogHeader, + AlertDialogTitle, +} from "./ui/alert-dialog"; +import { Input } from "./ui/input"; +import toast from "react-hot-toast"; +import { PICO_BACKEND_FORM_SECRET } from "../config"; const TermsOfServiceDialog: React.FC<{ open: boolean; onOpenChange: (open: boolean) => void; }> = ({ open, onOpenChange }) => { + const [email, setEmail] = React.useState(""); + + const onSubscribe = async () => { + await fetch("https://backend.buildpicoapps.com/form", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ email, secret: PICO_BACKEND_FORM_SECRET }), + }); + }; return ( - - - - Terms of Service - + + + + + Enter your email to get started + + + +
+ { + setEmail(e.target.value); + }} + /> +
- By using this website, you agree to the{" "} + By providing your email, you consent to receiving occasional product + updates, and you accept the{" "} terms of service - . This project is MIT licensed.{" "} + .
+
+ Prefer to run it yourself locally? This project is open source.{" "} - You can run this app locally by downloading the source code from - Github. + Download the code and get started on Github.
- - Agree - -
-
+ + { + if (!email.trim() || !email.trim().includes("@")) { + e.preventDefault(); + toast.error("Please enter your email"); + } else { + onSubscribe(); + } + }} + > + Agree + + + + ); }; diff --git a/frontend/src/components/ui/alert-dialog.tsx b/frontend/src/components/ui/alert-dialog.tsx new file mode 100644 index 0000000..cc49f39 --- /dev/null +++ b/frontend/src/components/ui/alert-dialog.tsx @@ -0,0 +1,139 @@ +import * as React from "react" +import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog" + +import { cn } from "@/lib/utils" +import { buttonVariants } from "@/components/ui/button" + +const AlertDialog = AlertDialogPrimitive.Root + +const AlertDialogTrigger = AlertDialogPrimitive.Trigger + +const AlertDialogPortal = AlertDialogPrimitive.Portal + +const AlertDialogOverlay = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName + +const AlertDialogContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + + +)) +AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName + +const AlertDialogHeader = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+) +AlertDialogHeader.displayName = "AlertDialogHeader" + +const AlertDialogFooter = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+) +AlertDialogFooter.displayName = "AlertDialogFooter" + +const AlertDialogTitle = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName + +const AlertDialogDescription = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AlertDialogDescription.displayName = + AlertDialogPrimitive.Description.displayName + +const AlertDialogAction = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName + +const AlertDialogCancel = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName + +export { + AlertDialog, + AlertDialogPortal, + AlertDialogOverlay, + AlertDialogTrigger, + AlertDialogContent, + AlertDialogHeader, + AlertDialogFooter, + AlertDialogTitle, + AlertDialogDescription, + AlertDialogAction, + AlertDialogCancel, +} diff --git a/frontend/src/components/ui/checkbox.tsx b/frontend/src/components/ui/checkbox.tsx new file mode 100644 index 0000000..f831532 --- /dev/null +++ b/frontend/src/components/ui/checkbox.tsx @@ -0,0 +1,28 @@ +import * as React from "react" +import * as CheckboxPrimitive from "@radix-ui/react-checkbox" +import { CheckIcon } from "@radix-ui/react-icons" + +import { cn } from "@/lib/utils" + +const Checkbox = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + + + +)) +Checkbox.displayName = CheckboxPrimitive.Root.displayName + +export { Checkbox } diff --git a/frontend/src/config.ts b/frontend/src/config.ts index 7a6251c..4f0de2f 100644 --- a/frontend/src/config.ts +++ b/frontend/src/config.ts @@ -7,3 +7,6 @@ export const WS_BACKEND_URL = export const HTTP_BACKEND_URL = import.meta.env.VITE_HTTP_BACKEND_URL || "http://127.0.0.1:7001"; + +export const PICO_BACKEND_FORM_SECRET = + import.meta.env.VITE_PICO_BACKEND_FORM_SECRET || null; diff --git a/frontend/yarn.lock b/frontend/yarn.lock index 1230589..21ea63f 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -593,6 +593,34 @@ dependencies: "@babel/runtime" "^7.13.10" +"@radix-ui/react-alert-dialog@^1.0.5": + version "1.0.5" + resolved "https://registry.yarnpkg.com/@radix-ui/react-alert-dialog/-/react-alert-dialog-1.0.5.tgz#70dd529cbf1e4bff386814d3776901fcaa131b8c" + integrity sha512-OrVIOcZL0tl6xibeuGt5/+UxoT2N27KCFOPjFyfXMnchxSHZ/OW7cCX2nGlIYJrbHK/fczPcFzAwvNBB6XBNMA== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/primitive" "1.0.1" + "@radix-ui/react-compose-refs" "1.0.1" + "@radix-ui/react-context" "1.0.1" + "@radix-ui/react-dialog" "1.0.5" + "@radix-ui/react-primitive" "1.0.3" + "@radix-ui/react-slot" "1.0.2" + +"@radix-ui/react-checkbox@^1.0.4": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@radix-ui/react-checkbox/-/react-checkbox-1.0.4.tgz#98f22c38d5010dd6df4c5744cac74087e3275f4b" + integrity sha512-CBuGQa52aAYnADZVt/KBQzXrwx6TqnlwtcIPGtVt5JkkzQwMOLJjPukimhfKEr4GQNd43C+djUh5Ikopj8pSLg== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/primitive" "1.0.1" + "@radix-ui/react-compose-refs" "1.0.1" + "@radix-ui/react-context" "1.0.1" + "@radix-ui/react-presence" "1.0.1" + "@radix-ui/react-primitive" "1.0.3" + "@radix-ui/react-use-controllable-state" "1.0.1" + "@radix-ui/react-use-previous" "1.0.1" + "@radix-ui/react-use-size" "1.0.1" + "@radix-ui/react-collection@1.0.3": version "1.0.3" resolved "https://registry.yarnpkg.com/@radix-ui/react-collection/-/react-collection-1.0.3.tgz#9595a66e09026187524a36c6e7e9c7d286469159" @@ -618,7 +646,7 @@ dependencies: "@babel/runtime" "^7.13.10" -"@radix-ui/react-dialog@^1.0.5": +"@radix-ui/react-dialog@1.0.5", "@radix-ui/react-dialog@^1.0.5": version "1.0.5" resolved "https://registry.yarnpkg.com/@radix-ui/react-dialog/-/react-dialog-1.0.5.tgz#71657b1b116de6c7a0b03242d7d43e01062c7300" integrity sha512-GjWJX/AUpB703eEBanuBnIWdIXg6NvJFCXcNlSZk4xdszCdhrJgBoUd1cGk67vFO+WdA2pfI/plOpqz/5GUP6Q== From a178e316c4afddb0178021c2fa05543c70002f20 Mon Sep 17 00:00:00 2001 From: Abi Raja Date: Sun, 26 Nov 2023 15:30:03 -0500 Subject: [PATCH 05/17] make drag and drop area more obvious --- frontend/src/components/ImageUpload.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/frontend/src/components/ImageUpload.tsx b/frontend/src/components/ImageUpload.tsx index 4a46d99..d3972ca 100644 --- a/frontend/src/components/ImageUpload.tsx +++ b/frontend/src/components/ImageUpload.tsx @@ -140,7 +140,10 @@ function ImageUpload({ setReferenceImages }: Props) { {/* eslint-disable-next-line @typescript-eslint/no-explicit-any */}
-

Drop a screenshot here, paste from clipboard, or click to select

+

+ Drag & drop a screenshot here, or paste from clipboard, or click to + upload +

); From e8f4bf1deab670637d18ccda4a84725b3a4df0fe Mon Sep 17 00:00:00 2001 From: Abi Raja Date: Sun, 26 Nov 2023 15:31:59 -0500 Subject: [PATCH 06/17] style fix --- frontend/src/components/ImageUpload.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/components/ImageUpload.tsx b/frontend/src/components/ImageUpload.tsx index f024e2e..bc17d5f 100644 --- a/frontend/src/components/ImageUpload.tsx +++ b/frontend/src/components/ImageUpload.tsx @@ -106,7 +106,7 @@ function ImageUpload({ setReferenceImages }: Props) { // Convert images to data URLs and set the prompt images state Promise.all(files.map((file) => fileToDataURL(file))) .then((dataUrls) => { - if(dataUrls.length > 0) { + if (dataUrls.length > 0) { setReferenceImages(dataUrls.map((dataUrl) => dataUrl as string)); } }) From 0d542e18cc5f56a53070ed1da482a5e98d2973fd Mon Sep 17 00:00:00 2001 From: Abi Raja Date: Sun, 26 Nov 2023 15:35:22 -0500 Subject: [PATCH 07/17] Reset any existing state before running create --- frontend/src/App.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 4c843d6..529283c 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -116,6 +116,9 @@ function App() { // Initial version creation function doCreate(referenceImages: string[]) { + // Reset any existing state + reset(); + setReferenceImages(referenceImages); if (referenceImages.length > 0) { doGenerateCode({ From 8184f833fff91879f620d8385b09dc43143788d3 Mon Sep 17 00:00:00 2001 From: Abi Raja Date: Sun, 26 Nov 2023 15:44:58 -0500 Subject: [PATCH 08/17] Delete sweep-template.yml --- .github/ISSUE_TEMPLATE/sweep-template.yml | 15 --------------- 1 file changed, 15 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/sweep-template.yml diff --git a/.github/ISSUE_TEMPLATE/sweep-template.yml b/.github/ISSUE_TEMPLATE/sweep-template.yml deleted file mode 100644 index 44116f5..0000000 --- a/.github/ISSUE_TEMPLATE/sweep-template.yml +++ /dev/null @@ -1,15 +0,0 @@ -name: Sweep Issue -title: 'Sweep: ' -description: For small bugs, features, refactors, and tests to be handled by Sweep, an AI-powered junior developer. -labels: sweep -body: - - type: textarea - id: description - attributes: - label: Details - description: Tell Sweep where and what to edit and provide enough context for a new developer to the codebase - placeholder: | - Unit Tests: Write unit tests for . Test each function in the file. Make sure to test edge cases. - Bugs: The bug might be in . Here are the logs: ... - Features: the new endpoint should use the ... class from because it contains ... logic. - Refactors: We are migrating this function to ... version because ... \ No newline at end of file From f9a30be761f57d362fd9f5c2328619d02b864fff Mon Sep 17 00:00:00 2001 From: Abi Raja Date: Sun, 26 Nov 2023 18:49:33 -0500 Subject: [PATCH 09/17] update copy on URL input section --- frontend/src/components/UrlInputSection.tsx | 27 +++++++-------------- 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/frontend/src/components/UrlInputSection.tsx b/frontend/src/components/UrlInputSection.tsx index 20e9c54..abf50a9 100644 --- a/frontend/src/components/UrlInputSection.tsx +++ b/frontend/src/components/UrlInputSection.tsx @@ -12,11 +12,13 @@ interface Props { export function UrlInputSection({ doCreate, screenshotOneApiKey }: Props) { const [isLoading, setIsLoading] = useState(false); const [referenceUrl, setReferenceUrl] = useState(""); - const isDisabled = !screenshotOneApiKey; async function takeScreenshot() { if (!screenshotOneApiKey) { - toast.error("Please add a Screenshot API key in the settings dialog"); + toast.error( + "Please add a ScreenshotOne API key in the Settings dialog. This is optional - you can also drag/drop and upload images directly.", + { duration: 8000 } + ); return; } @@ -64,24 +66,13 @@ export function UrlInputSection({ doCreate, screenshotOneApiKey }: Props) { onChange={(e) => setReferenceUrl(e.target.value)} value={referenceUrl} /> - - {isDisabled && ( -
- - To screenshot a URL, add a{" "} - - ScreenshotOne API key - {" "} - in the settings dialog. - -
- )}
); } From e5ca11daef57666d59db62518e1153b177dde0c5 Mon Sep 17 00:00:00 2001 From: Abi Raja Date: Sun, 26 Nov 2023 18:51:18 -0500 Subject: [PATCH 10/17] update copy on Settings Dialog for screenshotting a URL --- frontend/src/components/SettingsDialog.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/frontend/src/components/SettingsDialog.tsx b/frontend/src/components/SettingsDialog.tsx index 121c17c..397ce02 100644 --- a/frontend/src/components/SettingsDialog.tsx +++ b/frontend/src/components/SettingsDialog.tsx @@ -77,7 +77,10 @@ function SettingsDialog({ settings, setSettings }: Props) { />
+ ); +} + +export default CodeTab;