diff --git a/web-app/public/images/ic_zapier.svg b/web-app/public/images/ic_zapier.svg new file mode 100644 index 00000000..f2fc6327 --- /dev/null +++ b/web-app/public/images/ic_zapier.svg @@ -0,0 +1,9 @@ +<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> +<rect width="40" height="40" rx="4" fill="url(#pattern0)"/> +<defs> +<pattern id="pattern0" patternContentUnits="objectBoundingBox" width="1" height="1"> +<use xlink:href="#image0_21982_26196" transform="scale(0.00625)"/> +</pattern> +<image id="image0_21982_26196" width="160" height="160" xlink:href="data:image/png;base64,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"/> +</defs> +</svg> diff --git a/web-app/src/components/ai/chat-message.tsx b/web-app/src/components/ai/chat-message.tsx index b8d4db3c..96b65ea4 100644 --- a/web-app/src/components/ai/chat-message.tsx +++ b/web-app/src/components/ai/chat-message.tsx @@ -63,7 +63,13 @@ export function ChatMessage({ <Col className="idxflex-grow-1 mx-5" style={{ overflow: "auto" }}> <div style={{ overflowWrap: "break-word" }}> {editingMessage?.id && index === editingIndex ? ( - <Flex alignitems="center" flexdirection="row"> + <Flex + alignitems="center" + flexdirection="row" + style={{ + marginBottom: "14px", + }} + > <Input autoFocus style={{ diff --git a/web-app/src/components/base/Input/index.tsx b/web-app/src/components/base/Input/index.tsx index d867ac1c..0f78d80b 100644 --- a/web-app/src/components/base/Input/index.tsx +++ b/web-app/src/components/base/Input/index.tsx @@ -6,67 +6,84 @@ import IconVisible from "../Icon/IconVisible"; import IconInvisible from "../Icon/IconInvisible"; import Text from "../Text"; -export interface InputProps extends React.DetailedHTMLProps<React.InputHTMLAttributes<HTMLInputElement>, HTMLInputElement> { - error?: string; - inputSize?: InputSizeType; - block?: boolean; - ghost?: boolean; - addOnBefore?: React.ReactNode; - addOnAfter?: React.ReactNode; - type?: PropType<React.InputHTMLAttributes<HTMLInputElement>, "type">; +export interface InputProps + extends React.DetailedHTMLProps< + React.InputHTMLAttributes<HTMLInputElement>, + HTMLInputElement + > { + error?: string; + inputSize?: InputSizeType; + block?: boolean; + ghost?: boolean; + addOnBefore?: React.ReactNode; + addOnAfter?: React.ReactNode; + type?: PropType<React.InputHTMLAttributes<HTMLInputElement>, "type">; } -const Input = ( - { - className, - addOnBefore, - addOnAfter, - disabled, - readOnly, - type, - block = true, - inputSize = "md", - ghost = false, - error, - ...inputProps - }: InputProps, -) => { - const inputRef = useRef<HTMLInputElement>(null); - const [showPw, setShowPw] = useState(false); +const Input = ({ + className, + addOnBefore, + addOnAfter, + disabled, + readOnly, + type, + block = true, + inputSize = "md", + ghost = false, + error, + ...inputProps +}: InputProps) => { + const inputRef = useRef<HTMLInputElement>(null); + const [showPw, setShowPw] = useState(false); - const handleTogglePw = () => { - setShowPw((oldVal) => !oldVal); - }; - const renderVisible = () => (showPw ? <IconInvisible onClick={handleTogglePw} /> : <IconVisible onClick={handleTogglePw} />); + const handleTogglePw = () => { + setShowPw((oldVal) => !oldVal); + }; + const renderVisible = () => + showPw ? ( + <IconInvisible onClick={handleTogglePw} /> + ) : ( + <IconVisible onClick={handleTogglePw} /> + ); - return ( - <> - <Flex className={cc( - [ - "input", - `input-${inputSize}`, - ghost ? "input-ghost" : "", - block ? "input-block" : "", - disabled ? "input-disabled" : "", - readOnly ? "input-readonly" : "", - addOnBefore ? "input-add-on-before" : "", - addOnAfter ? "input-add-on-after" : "", - className, - ], - )}> - {addOnBefore} - <input - ref={inputRef} - {...inputProps} - disabled={disabled} - readOnly={readOnly} - type={type === "password" && showPw ? "text" : type} - className={"input__input"} /> + return ( + <> + <Flex + className={cc([ + "input", + `input-${inputSize}`, + ghost ? "input-ghost" : "", + block ? "input-block" : "", + disabled ? "input-disabled" : "", + readOnly ? "input-readonly" : "", + addOnBefore ? "input-add-on-before" : "", + addOnAfter ? "input-add-on-after" : "", + className, + ])} + > + {addOnBefore} + <input + ref={inputRef} + {...inputProps} + disabled={disabled} + readOnly={readOnly} + type={type === "password" && showPw ? "text" : type} + className={"input__input"} + style={{ + fontSize: "1.4rem", + padding: "0", + margin: "0", + }} + /> - {type === "password" ? renderVisible() : addOnAfter} - </Flex> - {error && <Text className={"mt-3"} theme="error" size={inputSize} >{error}</Text>} - </> - ); + {type === "password" ? renderVisible() : addOnAfter} + </Flex> + {error && ( + <Text className={"mt-3"} theme="error" size={inputSize}> + {error} + </Text> + )} + </> + ); }; export default Input; diff --git a/web-app/src/components/sections/IndexConversation/TabContainer/SettingsTab/SaveYourKey.tsx b/web-app/src/components/sections/IndexConversation/TabContainer/SettingsTab/SaveYourKey.tsx index 66eb51ab..af966ecd 100644 --- a/web-app/src/components/sections/IndexConversation/TabContainer/SettingsTab/SaveYourKey.tsx +++ b/web-app/src/components/sections/IndexConversation/TabContainer/SettingsTab/SaveYourKey.tsx @@ -17,7 +17,7 @@ const SaveYourKey: FC<SaveYourKeyProps> = ({ secretKey, onDone }) => ( gap: "1.5rem", }} > - <h2>Save Your Key</h2> + {/* <h2>Save Your Key</h2> */} <div style={{ display: "flex", diff --git a/web-app/src/components/sections/IndexConversation/TabContainer/SettingsTab/SettingsModal.tsx b/web-app/src/components/sections/IndexConversation/TabContainer/SettingsTab/SettingsModal.tsx index 47990974..34e497b3 100644 --- a/web-app/src/components/sections/IndexConversation/TabContainer/SettingsTab/SettingsModal.tsx +++ b/web-app/src/components/sections/IndexConversation/TabContainer/SettingsTab/SettingsModal.tsx @@ -30,7 +30,23 @@ const SettingsModal: FC<SettingsModalProps> = ({ return <></>; } }; - return visible && <Modal visible={visible} body={renderStep()} />; + + let header; + if (step === "waiting") { + header = <h2>Waiting for transaction</h2>; + } else if (step === "done") { + header = <h2>Save your key</h2>; + } + return ( + visible && ( + <Modal + onClose={onCancel} + header={header} + visible={visible} + body={renderStep()} + /> + ) + ); }; export default SettingsModal; diff --git a/web-app/src/components/sections/IndexConversation/TabContainer/SettingsTab/WaitingForTransaction.tsx b/web-app/src/components/sections/IndexConversation/TabContainer/SettingsTab/WaitingForTransaction.tsx index 59e957c5..8a7a521e 100644 --- a/web-app/src/components/sections/IndexConversation/TabContainer/SettingsTab/WaitingForTransaction.tsx +++ b/web-app/src/components/sections/IndexConversation/TabContainer/SettingsTab/WaitingForTransaction.tsx @@ -21,7 +21,7 @@ const WaitingForTransaction: FC<WaitingForTransactionProps> = ({ }} > <div className=""> - <h2>Waiting for transaction</h2> + {/* <h2>Waiting for transaction</h2> */} <p> Please wait while the transaction is being processed. This may take a few minutes. @@ -45,7 +45,7 @@ const WaitingForTransaction: FC<WaitingForTransactionProps> = ({ > <Button onClick={onCancel} - className="mt-7 pl-8 pr-8 " + className="pl-6 pr-6" size="lg" theme="clear" > diff --git a/web-app/src/components/sections/IndexConversation/TabContainer/SettingsTab/index.tsx b/web-app/src/components/sections/IndexConversation/TabContainer/SettingsTab/index.tsx index 820ea622..1377573c 100644 --- a/web-app/src/components/sections/IndexConversation/TabContainer/SettingsTab/index.tsx +++ b/web-app/src/components/sections/IndexConversation/TabContainer/SettingsTab/index.tsx @@ -7,6 +7,7 @@ import Header from "components/base/Header"; import Text from "components/base/Text"; import Col from "components/layout/base/Grid/Col"; import FlexRow from "components/layout/base/Grid/FlexRow"; +import Image from "next/image"; import React, { useCallback, useEffect, useMemo, useState } from "react"; import toast from "react-hot-toast"; import SettingsModal, { SettingsModalStep } from "./SettingsModal"; @@ -128,10 +129,15 @@ const IndexSettingsTabSection: React.FC<IndexSettingsTabSectionProps> = () => { visible={showModal} /> <FlexRow className={"mt-6"}> - <Col xs={12}> - <Header className="mb-4">API Keys</Header> + <Col + xs={12} + style={{ + marginBottom: "16px", + }} + > + <Header>API Keys</Header> </Col> - <Col className="mt-6" xs={8}> + <Col xs={8}> <div style={{ display: "flex", @@ -182,7 +188,7 @@ const IndexSettingsTabSection: React.FC<IndexSettingsTabSectionProps> = () => { border: "1px solid #E2E8F0", color: "#1E293B", padding: "0.5rem", - borderRadius: "0.125rem", + borderRadius: "2px", fontWeight: 500, width: "fit-content", }} @@ -194,6 +200,97 @@ const IndexSettingsTabSection: React.FC<IndexSettingsTabSectionProps> = () => { </div> </Col> </FlexRow> + <FlexRow className="mt-8"> + <Col + xs={12} + style={{ + marginBottom: "16px", + }} + > + <Header>Integrations</Header> + </Col> + + <Col> + <div + style={{ + display: "flex", + flexDirection: "column", + gap: "24px", + }} + > + <Text + theme={"primary"} + size="md" + style={{ + maxWidth: "80%", + }} + > + You can connect Index Network with lots of popular apps easily. + This lets you make indexing automatic. + </Text> + <div + style={{ + display: "flex", + flexDirection: "row", + justifyContent: "center", + alignItems: "center", + gap: "1.2rem", + padding: "16px", + border: "1px solid #E2E8F0", + borderRadius: "4px", + maxWidth: "500px", + }} + > + <Image + alt="Zapier" + src="/images/ic_zapier.svg" + width="40" + height="40" + /> + <div + style={{ + display: "flex", + gap: "0.25rem", + flexDirection: "column", + }} + > + <p + style={{ + margin: "0", + }} + > + <b>Zapier</b> + </p> + <p + style={{ + margin: "0", + color: "#475569", + fontSize: "12px", + }} + > + Create integrations between Index Network and your favorite + apps using Zapier!{" "} + </p> + </div> + <a + style={{ + background: "none", + border: "1px solid #E2E8F0", + color: "#1E293B", + padding: "0.5rem", + borderRadius: "2px", + fontWeight: 500, + width: "fit-content", + whiteSpace: "nowrap", + }} + href="https://www.zapier.com" + > + Configure on Zapier + </a> + </div> + </div> + </Col> + </FlexRow> </> ); }; diff --git a/web-app/src/components/sections/UserConversation.tsx b/web-app/src/components/sections/UserConversation.tsx index 51247732..55a8ede1 100644 --- a/web-app/src/components/sections/UserConversation.tsx +++ b/web-app/src/components/sections/UserConversation.tsx @@ -4,7 +4,7 @@ import { useRouteParams } from "hooks/useRouteParams"; export default function UserConversationSection() { const { id } = useRouteParams(); - const { chatID, leftSectionIndexes } = useApp(); + const { chatID } = useApp(); if (!chatID || !id) { return null; @@ -14,18 +14,27 @@ export default function UserConversationSection() { <div style={{ display: "flex", - justifyContent: "stretch", - alignItems: "start", - flex: 1, - overflowY: "auto", - maxHeight: "calc(100dvh - 12em)", + justifyContent: "center", + height: "100%", }} > - <AskIndexes - // indexIds={leftSectionIndexes.map((i) => i.id)} - chatID={chatID} - did={id} - /> + <div + style={{ + display: "flex", + justifyContent: "center", + alignItems: "start", + flex: 1, + overflowY: "auto", + maxHeight: "calc(100dvh - 12em)", + height: "100%", + }} + > + <AskIndexes + // indexIds={leftSectionIndexes.map((i) => i.id)} + chatID={chatID} + did={id} + /> + </div> </div> ); } diff --git a/web-app/src/components/site/indexes/AskIndexes/index.tsx b/web-app/src/components/site/indexes/AskIndexes/index.tsx index 742f1253..58f5cd71 100644 --- a/web-app/src/components/site/indexes/AskIndexes/index.tsx +++ b/web-app/src/components/site/indexes/AskIndexes/index.tsx @@ -180,10 +180,20 @@ const AskIndexes: FC<AskIndexesProps> = ({ chatID, did, indexIds }) => { display: "flex", flexDirection: "column", height: "100%", + width: "100%", + alignItems: "stretch", }} > <FlexRow wrap={true} align={"start"} style={{ flex: "1 1 auto" }}> - <Col className="idxflex-grow-1"> + <Col + className="idxflex-grow-1" + style={{ + display: "flex", + height: "100%", + justifyContent: "stretch", + width: "100%", + }} + > {messages.length ? ( <> <ChatList @@ -199,7 +209,15 @@ const AskIndexes: FC<AskIndexesProps> = ({ chatID, did, indexIds }) => { <ChatScrollAnchor trackVisibility={isLoading} /> </> ) : ( - <Flex className="px-8"> + <Flex + className="px-8" + style={{ + width: "100%", + height: "100%", + alignItems: "center", + justifyContent: "center", + }} + > <EmptyScreen contextMessage={getChatContextMessage()} setInput={setInput}