Merge branch 'main' into hosted

This commit is contained in:
Abi Raja 2024-04-10 14:55:07 -04:00
commit 60171bcc0b
7 changed files with 5 additions and 222 deletions

View File

@ -1,21 +0,0 @@
import json
import os
import httpx
async def validate_access_token(access_code: str):
async with httpx.AsyncClient() as client:
url = (
"https://backend.buildpicoapps.com/screenshot_to_code/validate_access_token"
)
data = json.dumps(
{
"access_code": access_code,
"secret": os.environ.get("PICO_BACKEND_SECRET"),
}
)
headers = {"Content-Type": "application/json"}
response = await client.post(url, content=data, headers=headers)
response_data = response.json()
return response_data

View File

@ -16,7 +16,6 @@ from mock_llm import mock_completion
from typing import Dict, List, cast, get_args
from image_generation import create_alt_url_mapping, generate_images
from prompts import assemble_imported_code_prompt, assemble_prompt
from access_token import validate_access_token
from datetime import datetime
import json
from routes.logging_utils import PaymentMethod, send_to_saas_backend
@ -128,21 +127,7 @@ async def stream_code(websocket: WebSocket):
await throw_error("Unknown error occurred. Contact support.")
raise Exception("Unknown error occurred when checking subscription credits")
# For non-subscribers, if they have an access code, validate it
# and use the platform API key
if not openai_api_key:
accessCode = params.get("accessCode", None)
if accessCode:
print("Access code - using platform API key")
res = await validate_access_token(accessCode)
if res["success"]:
payment_method = PaymentMethod.ACCESS_CODE
openai_api_key = os.environ.get("PLATFORM_OPENAI_API_KEY")
else:
await throw_error(res["failure_reason"])
raise Exception("Invalid access code: " + accessCode)
# If we still don't have an API key, use the user's API key from client-side settings dialog
# For non-subscribers, use the user's API key from client-side settings dialog
if not openai_api_key:
openai_api_key = params.get("openAiApiKey", None)
payment_method = PaymentMethod.OPENAI_API_KEY

View File

@ -76,8 +76,7 @@ function App({ navbarComponent }: Props) {
generatedCodeConfig: Stack.HTML_TAILWIND,
codeGenerationModel: CodeGenerationModel.GPT_4_VISION,
// Only relevant for hosted version
isTermOfServiceAccepted: true,
accessCode: null,
isTermOfServiceAccepted: false,
},
"setting"
);
@ -391,7 +390,7 @@ function App({ navbarComponent }: Props) {
return (
<div className="mt-2 dark:bg-black dark:text-white">
{IS_RUNNING_ON_CLOUD && <PicoBadge settings={settings} />}
{IS_RUNNING_ON_CLOUD && <PicoBadge />}
{IS_RUNNING_ON_CLOUD && (
<TermsOfServiceDialog
open={false}
@ -424,7 +423,7 @@ function App({ navbarComponent }: Props) {
{appState !== AppState.CODE_READY && <TipLink />}
{IS_RUNNING_ON_CLOUD &&
!(settings.openAiApiKey || settings.accessCode) &&
!settings.openAiApiKey &&
subscriberTier === "free" && <OnboardingNote />}
{IS_OPENAI_DOWN && (

View File

@ -1,7 +1,6 @@
import { Settings } from "../types";
import PricingDialog from "./payments/PricingDialog";
export function PicoBadge({ settings }: { settings: Settings }) {
export function PicoBadge() {
return (
<>
<div>
@ -18,26 +17,6 @@ export function PicoBadge({ settings }: { settings: Settings }) {
feature requests
</div>
</a>
{/* {!settings.accessCode && (
<a href="https://picoapps.xyz?ref=screenshot-to-code" target="_blank">
<div
className="fixed z-50 bottom-5 right-5 rounded-md shadow text-black
bg-white px-4 text-xs py-3 cursor-pointer"
>
an open source project by Pico
</div>
</a>
)} */}
{settings.accessCode && (
<a href="mailto:support@picoapps.xyz" target="_blank">
<div
className="fixed z-50 bottom-5 right-5 rounded-md shadow text-black
bg-white px-4 text-xs py-3 cursor-pointer"
>
email support
</div>
</a>
)}
</>
);
}

View File

@ -22,7 +22,6 @@ import {
AccordionItem,
AccordionTrigger,
} from "./ui/accordion";
import AccessCodeSection from "./settings/AccessCodeSection";
interface Props {
settings: Settings;
@ -47,11 +46,6 @@ function SettingsDialog({ settings, setSettings }: Props) {
<DialogTitle className="mb-4">Settings</DialogTitle>
</DialogHeader>
{/* Access code */}
{IS_RUNNING_ON_CLOUD && (
<AccessCodeSection settings={settings} setSettings={setSettings} />
)}
<div className="flex items-center space-x-2">
<Label htmlFor="image-generation">
<div>DALL-E Placeholder Image Generation</div>

View File

@ -1,152 +0,0 @@
import { useEffect, useState } from "react";
import { Settings } from "../../types";
import { Button } from "../ui/button";
import { Input } from "../ui/input";
import { Label } from "../ui/label";
import useThrottle from "../../hooks/useThrottle";
import { Progress } from "../ui/progress";
import { PICO_BACKEND_FORM_SECRET } from "../../config";
import { useStore } from "../../store/store";
interface Props {
settings: Settings;
setSettings: React.Dispatch<React.SetStateAction<Settings>>;
}
interface UsageResponse {
used_credits: number;
total_credits: number;
is_valid: boolean;
}
enum FetchState {
EMPTY = "EMPTY",
LOADING = "LOADING",
INVALID = "INVALID",
VALID = "VALID",
}
function AccessCodeSection({ settings, setSettings }: Props) {
const [isLoading, setIsLoading] = useState(false);
const [isValid, setIsValid] = useState(false);
const [usedCredits, setUsedCredits] = useState(0);
const [totalCredits, setTotalCredits] = useState(0);
const throttledAccessCode = useThrottle(settings.accessCode || "", 500);
const setPricingDialogOpen = useStore((state) => state.setPricingDialogOpen);
const fetchState = (() => {
if (!settings.accessCode) return FetchState.EMPTY;
if (isLoading) return FetchState.LOADING;
if (!isValid) return FetchState.INVALID;
return FetchState.VALID;
})();
async function fetchUsage(accessCode: string) {
const res = await fetch(
"https://backend.buildpicoapps.com/screenshot_to_code/get_access_code_usage",
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
access_code: accessCode,
secret: PICO_BACKEND_FORM_SECRET,
}),
}
);
const usage = (await res.json()) as UsageResponse;
if (!usage.is_valid) {
setIsValid(false);
} else {
setIsValid(true);
setUsedCredits(usage.used_credits);
setTotalCredits(usage.total_credits);
}
setIsLoading(false);
}
useEffect(() => {
// Don't do anything if access code is empty
if (!throttledAccessCode) return;
setIsLoading(true);
setIsValid(true);
// Wait for 500 ms before fetching usage
setTimeout(async () => {
await fetchUsage(throttledAccessCode);
}, 500);
}, [throttledAccessCode]);
return (
<div className="flex flex-col space-y-4 bg-slate-200 p-4 rounded dark:text-white dark:bg-slate-800">
<Label htmlFor="access-code">
<div>
Access Code (monthly subscribers do not need to fill this out - it
should just work)
</div>
</Label>
<Input
id="access-code"
className="border-gray-700 dark:border-gray-700 dark:bg-gray-800 dark:text-white"
placeholder="Enter your Screenshot to Code access code"
value={settings.accessCode || ""}
onChange={(e) =>
setSettings((s) => ({
...s,
accessCode: e.target.value,
}))
}
/>
{fetchState === "EMPTY" && (
<div className="flex items-center justify-between">
<div className="text-xs">
If you already have an access code, enter it above.
</div>
<Button
size="sm"
variant="secondary"
onClick={() => setPricingDialogOpen(true)}
>
Subscribe to a plan
</Button>
</div>
)}
{fetchState === "LOADING" && (
<div className="flex items-center justify-between">
<span className="text-xs text-gray-700">Loading...</span>
</div>
)}
{fetchState === "INVALID" && (
<>
<div className="flex items-center justify-between">
<span className="text-xs text-gray-700">Invalid access code</span>
</div>
</>
)}
{fetchState === "VALID" && (
<>
<Progress value={(usedCredits / totalCredits) * 100} />
<div className="flex items-center justify-between">
<span className="text-xs text-gray-700">
{usedCredits} out of {totalCredits} credits used
</span>
<Button size="sm" onClick={() => setPricingDialogOpen(true)}>
Add credits
</Button>
</div>
</>
)}
</div>
);
}
export default AccessCodeSection;

View File

@ -16,7 +16,6 @@ export interface Settings {
codeGenerationModel: CodeGenerationModel;
// Only relevant for hosted version
isTermOfServiceAccepted: boolean;
accessCode: string | null;
}
export enum AppState {