+
+
+
Connections
+
+ Connect the workbench to any MySQL or PostgreSQL compatible database.
+ Use or to unlock version control
+ features.
+
+
+
+
+
+
+
+
+
+
+
- {props.connections.map(conn => (
+ {props.connections.map((conn, i) => (
))}
-
-
+
);
}
+
+function getBorderLineClassName(n: number, ind: number): string {
+ if (n % 2 === 0) {
+ return ind < n / 2 ? "roundedTop" : "roundedBottom";
+ }
+ if (ind < Math.floor(n / 2)) {
+ return "roundedTop";
+ }
+ if (ind > Math.floor(n / 2)) {
+ return "roundedBottom";
+ }
+ return "straightLine";
+}
diff --git a/web/renderer/components/pageComponents/ConnectionsPage/NewConnection/About.tsx b/web/renderer/components/pageComponents/ConnectionsPage/NewConnection/About.tsx
new file mode 100644
index 00000000..c241e480
--- /dev/null
+++ b/web/renderer/components/pageComponents/ConnectionsPage/NewConnection/About.tsx
@@ -0,0 +1,58 @@
+import {
+ Button,
+ FormInput,
+ FormSelect,
+ useTabsContext,
+} from "@dolthub/react-components";
+import { DatabaseType } from "@gen/graphql-types";
+import { useConfigContext } from "./context/config";
+import css from "./index.module.css";
+
+export default function About() {
+ const { state, setState } = useConfigContext();
+ const { activeTabIndex, setActiveTabIndex } = useTabsContext();
+
+ const onNext = () => {
+ setActiveTabIndex(activeTabIndex + 1);
+ };
+
+ return (
+
+ );
+}
diff --git a/web/renderer/components/pageComponents/ConnectionsPage/NewConnection/Advanced.tsx b/web/renderer/components/pageComponents/ConnectionsPage/NewConnection/Advanced.tsx
new file mode 100644
index 00000000..d8d609bd
--- /dev/null
+++ b/web/renderer/components/pageComponents/ConnectionsPage/NewConnection/Advanced.tsx
@@ -0,0 +1,50 @@
+import {
+ Button,
+ Checkbox,
+ ErrorMsg,
+ SmallLoader,
+ Tooltip,
+} from "@dolthub/react-components";
+import css from "./index.module.css";
+import { useConfigContext } from "./context/config";
+import { getCanSubmit } from "./context/utils";
+
+export default function Advanced() {
+ const { state, setState, error, onSubmit } = useConfigContext();
+ const { canSubmit, message } = getCanSubmit(state);
+
+ return (
+
+ );
+}
diff --git a/web/renderer/components/pageComponents/ConnectionsPage/NewConnection/Connection.tsx b/web/renderer/components/pageComponents/ConnectionsPage/NewConnection/Connection.tsx
new file mode 100644
index 00000000..da34066b
--- /dev/null
+++ b/web/renderer/components/pageComponents/ConnectionsPage/NewConnection/Connection.tsx
@@ -0,0 +1,85 @@
+import { Button, FormInput, useTabsContext } from "@dolthub/react-components";
+import { DatabaseType } from "@gen/graphql-types";
+import { SyntheticEvent } from "react";
+import css from "./index.module.css";
+import { useConfigContext } from "./context/config";
+
+export default function Connection() {
+ const { state, setState } = useConfigContext();
+ const { activeTabIndex, setActiveTabIndex } = useTabsContext();
+
+ const onNext = (e: SyntheticEvent) => {
+ e.preventDefault();
+ setActiveTabIndex(activeTabIndex + 1);
+ };
+
+ return (
+
+ );
+}
diff --git a/web/renderer/components/pageComponents/ConnectionsPage/NewConnection/ConnectionTabs.tsx b/web/renderer/components/pageComponents/ConnectionsPage/NewConnection/ConnectionTabs.tsx
new file mode 100644
index 00000000..9a4e9352
--- /dev/null
+++ b/web/renderer/components/pageComponents/ConnectionsPage/NewConnection/ConnectionTabs.tsx
@@ -0,0 +1,101 @@
+import {
+ Tab,
+ TabList,
+ TabPanel,
+ Tabs,
+ useTabsContext,
+} from "@dolthub/react-components";
+import cx from "classnames";
+import { FiCheck } from "@react-icons/all-files/fi/FiCheck";
+import { ReactNode } from "react";
+import About from "./About";
+import Connection from "./Connection";
+import Advanced from "./Advanced";
+import css from "./index.module.css";
+import { useConfigContext } from "./context/config";
+import { ConfigState } from "./context/state";
+
+export default function ConnectionTabs() {
+ const { setErr } = useConfigContext();
+ const clearErr = () => setErr(undefined);
+
+ return (
+
+
+ {["About", "Connection", "Advanced"].map((tab, i) => (
+
+ {tab}
+
+ ))}
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
+
+type PanelProps = {
+ index: number;
+ children: ReactNode;
+};
+
+function CustomTabPanel(props: PanelProps) {
+ return (
+
+ {props.children}
+
+ );
+}
+
+function CustomTab(props: { index: number; children: string }) {
+ const { activeTabIndex } = useTabsContext();
+ const isActive = props.index === activeTabIndex;
+ const { state } = useConfigContext();
+ const isCompleted =
+ props.index < activeTabIndex && getCompleted(props.children, state);
+ return (
+
+ {isCompleted && }
+ {props.children}
+
+ );
+}
+
+function getCompleted(tabName: string, state: ConfigState): boolean {
+ switch (tabName) {
+ case "About":
+ return !!state.name;
+ case "Connection":
+ return !!state.connectionUrl || (!!state.host && !!state.username);
+ default:
+ return true;
+ }
+}
+
+function getDisabled(tabName: string, state: ConfigState): boolean {
+ switch (tabName) {
+ case "Connection":
+ return !state.name;
+ case "Advanced":
+ return (
+ !state.name ||
+ (!state.connectionUrl && (!state.host || !state.username))
+ );
+ default:
+ return false;
+ }
+}
diff --git a/web/renderer/components/pageComponents/ConnectionsPage/NewConnection/WelcomeMessage.tsx b/web/renderer/components/pageComponents/ConnectionsPage/NewConnection/WelcomeMessage.tsx
new file mode 100644
index 00000000..d2ddfb6f
--- /dev/null
+++ b/web/renderer/components/pageComponents/ConnectionsPage/NewConnection/WelcomeMessage.tsx
@@ -0,0 +1,15 @@
+import DoltLink from "@components/links/DoltLink";
+import DoltgresLink from "@components/links/DoltgresLink";
+import css from "./index.module.css";
+
+export default function WelcomeMessage() {
+ return (
+
+
Welcome to the Dolt Workbench
+
+ Connect the workbench to any MySQL or PostgreSQL compatible database.
+ Use or to unlock version control features.
+
+
+ );
+}
diff --git a/web/renderer/components/pageComponents/ConnectionsPage/NewConnection/context/config.tsx b/web/renderer/components/pageComponents/ConnectionsPage/NewConnection/context/config.tsx
new file mode 100644
index 00000000..374915fc
--- /dev/null
+++ b/web/renderer/components/pageComponents/ConnectionsPage/NewConnection/context/config.tsx
@@ -0,0 +1,94 @@
+import { createCustomContext } from "@dolthub/react-contexts";
+import {
+ useContextWithError,
+ useEffectOnMount,
+ useSetState,
+} from "@dolthub/react-hooks";
+import { useAddDatabaseConnectionMutation } from "@gen/graphql-types";
+import useMutation from "@hooks/useMutation";
+import { useRouter } from "next/router";
+import { ReactNode, SyntheticEvent, useEffect, useMemo } from "react";
+import { maybeDatabase } from "@lib/urls";
+import { ConfigContextType, defaultState, getDefaultState } from "./state";
+import { getConnectionUrl } from "./utils";
+
+export const ConfigContext =
+ createCustomContext
("ConfigContext");
+
+type Props = {
+ children: ReactNode;
+};
+
+export function ConfigProvider({ children }: Props) {
+ const router = useRouter();
+
+ const [state, setState] = useSetState(defaultState);
+ const { mutateFn, ...res } = useMutation({
+ hook: useAddDatabaseConnectionMutation,
+ });
+
+ useEffectOnMount(() => {
+ const isDocker = window.location.origin === "http://localhost:3000";
+ setState(getDefaultState(isDocker));
+ });
+
+ useEffect(() => {
+ if (!res.err) return;
+ if (
+ res.err.message.includes("The server does not support SSL connections")
+ ) {
+ setState({ showAdvancedSettings: true });
+ }
+ }, [res.err]);
+
+ const clearState = () => {
+ setState(defaultState);
+ };
+
+ const onSubmit = async (e: SyntheticEvent) => {
+ e.preventDefault();
+ setState({ loading: true });
+
+ try {
+ const db = await mutateFn({
+ variables: {
+ name: state.name,
+ connectionUrl: getConnectionUrl(state),
+ hideDoltFeatures: state.hideDoltFeatures,
+ useSSL: state.useSSL,
+ type: state.type,
+ },
+ });
+ await res.client.clearStore();
+ if (!db.data) {
+ return;
+ }
+ const { href, as } = maybeDatabase(
+ db.data.addDatabaseConnection.currentDatabase,
+ );
+ await router.push(href, as);
+ } catch (_) {
+ // Handled by res.error
+ } finally {
+ setState({ loading: false });
+ }
+ };
+ const value = useMemo(() => {
+ return {
+ state,
+ setState,
+ onSubmit,
+ error: res.err,
+ setErr: res.setErr,
+ clearState,
+ };
+ }, [state, setState, onSubmit, res.err, clearState]);
+
+ return (
+ {children}
+ );
+}
+
+export function useConfigContext(): ConfigContextType {
+ return useContextWithError(ConfigContext);
+}
diff --git a/web/renderer/components/pageComponents/ConnectionsPage/NewConnection/context/state.ts b/web/renderer/components/pageComponents/ConnectionsPage/NewConnection/context/state.ts
new file mode 100644
index 00000000..3858bf1c
--- /dev/null
+++ b/web/renderer/components/pageComponents/ConnectionsPage/NewConnection/context/state.ts
@@ -0,0 +1,42 @@
+import { DatabaseType } from "@gen/graphql-types";
+import { SetApolloErrorType } from "@lib/errors/types";
+import { Dispatch, SyntheticEvent } from "react";
+
+export const defaultState = {
+ name: "",
+ host: "",
+ hostPlaceholder: "127.0.0.1",
+ port: "3306",
+ username: "root",
+ password: "",
+ database: "",
+ connectionUrl: "",
+ hideDoltFeatures: false,
+ useSSL: true,
+ showAbout: true,
+ showConnectionDetails: false,
+ showAdvancedSettings: false,
+ loading: false,
+ type: DatabaseType.Mysql,
+};
+
+export type ConfigState = typeof defaultState;
+export type ConfigDispatch = Dispatch>;
+
+export function getDefaultState(isDocker = false): ConfigState {
+ const defaultHost = isDocker ? "host.docker.internal" : "127.0.0.1";
+ return {
+ ...defaultState,
+ host: defaultHost,
+ hostPlaceholder: defaultHost,
+ };
+}
+
+export type ConfigContextType = {
+ onSubmit: (e: SyntheticEvent) => Promise;
+ state: ConfigState;
+ setState: ConfigDispatch;
+ error?: Error | undefined;
+ setErr: SetApolloErrorType;
+ clearState: () => void;
+};
diff --git a/web/renderer/components/pageComponents/ConnectionsPage/NewConnection/context/utils.ts b/web/renderer/components/pageComponents/ConnectionsPage/NewConnection/context/utils.ts
new file mode 100644
index 00000000..8a0bdf8c
--- /dev/null
+++ b/web/renderer/components/pageComponents/ConnectionsPage/NewConnection/context/utils.ts
@@ -0,0 +1,24 @@
+import { DatabaseType } from "@gen/graphql-types";
+import { ConfigState } from "./state";
+
+export function getConnectionUrl(state: ConfigState): string {
+ if (state.connectionUrl) return state.connectionUrl;
+ const prefix = state.type === DatabaseType.Mysql ? "mysql" : "postgresql";
+ return `${prefix}://${state.username}:${state.password}@${state.host}:${state.port}/${state.database}`;
+}
+
+type GetCanSubmitReturnType = {
+ canSubmit: boolean;
+ message?: string;
+};
+
+export function getCanSubmit(state: ConfigState): GetCanSubmitReturnType {
+ if (!state.name) {
+ return { canSubmit: false, message: "Connection name is required" };
+ }
+ if (state.connectionUrl) return { canSubmit: true };
+ if (!state.host || !state.username) {
+ return { canSubmit: false, message: "Host or user name is required" };
+ }
+ return { canSubmit: true };
+}
diff --git a/web/renderer/components/pageComponents/ConnectionsPage/NewConnection/index.module.css b/web/renderer/components/pageComponents/ConnectionsPage/NewConnection/index.module.css
index c8751836..75687bc5 100644
--- a/web/renderer/components/pageComponents/ConnectionsPage/NewConnection/index.module.css
+++ b/web/renderer/components/pageComponents/ConnectionsPage/NewConnection/index.module.css
@@ -1,40 +1,100 @@
-.databaseForm {
- @apply w-full max-w-xl;
+.container {
+ @apply py-20 bg-stone-50 mb-16;
+}
+
+.panel {
+ @apply pt-10 px-10;
+}
+
+.tabList {
+ @apply px-6;
+}
+
+.tab {
+ @apply w-32 h-10 text-[#9AA5AD] relative;
+ button {
+ @apply flex items-center w-full;
+ }
+ span {
+ @apply flex-shrink-0;
+ }
+}
+.activeTab {
+ @apply text-storm-600 border-storm-600;
+}
+
+.check {
+ @apply mt-1.5 text-xl mr-2 flex-shrink-0 absolute left-0;
+}
+
+.isCompleted {
+ @apply text-green-400;
+}
+
+.databaseForm {
+ @apply w-full max-w-2xl mx-auto mt-14;
+ a {
+ @apply text-coral-300;
+ }
+ a:hover {
+ @apply text-coral-400;
+ }
h3 {
@apply mb-4;
}
}
+.welcome {
+ @apply text-center;
+ h1 {
+ @apply text-4xl font-semibold;
+ }
+ p {
+ @apply text-xl my-6 leading-8;
+ }
+}
+
.whiteContainer {
- @apply max-w-xl w-full border rounded-lg py-10 bg-white mx-auto;
+ @apply max-w-2xl w-full border rounded-lg py-10 bg-white mx-auto;
}
-.goback {
- @apply mb-2 mx-2;
- svg {
- @apply mb-[0.2rem] mr-1 inline-block;
- }
+.top {
+ @apply mx-10;
}
-.section {
- @apply px-14 py-4;
+.form {
+ @apply flex items-center flex-col;
+}
+
+.label {
+ @apply text-left;
}
.typeSelect {
- @apply ml-8 mb-4;
+ @apply mb-4 w-full;
}
.typeSelectInner {
@apply w-full;
}
-.middle {
- @apply border-y pt-8;
+.or {
+ @apply font-semibold text-center w-full my-5 text-lg text-stone-100;
}
-.or {
- @apply font-semibold text-center w-full my-5 text-lg;
+.or::before,
+.or::after {
+ content: "";
+ @apply w-[46%] border-t border-stone-100 inline-block align-middle relative;
+}
+
+.or::after {
+ @apply right-0 -ml-[52%];
+}
+
+.or::before {
+ @apply left-0 -mr-[52%];
}
.advancedSettings {
@@ -46,9 +106,25 @@
}
.checkbox {
- @apply mt-7 mb-10 text-sm;
+ @apply mb-3 text-sm w-full;
+}
+
+.form .checkbox {
+ svg {
+ @apply text-coral-300;
+ &:hover {
+ @apply text-coral-400;
+ }
+ }
}
.instructions {
@apply mb-8;
}
+
+.button {
+ @apply mt-8 min-w-36 py-2 bg-coral-300;
+ &:hover {
+ @apply bg-coral-400;
+ }
+}
diff --git a/web/renderer/components/pageComponents/ConnectionsPage/NewConnection/index.tsx b/web/renderer/components/pageComponents/ConnectionsPage/NewConnection/index.tsx
index 468ac33d..5b660916 100644
--- a/web/renderer/components/pageComponents/ConnectionsPage/NewConnection/index.tsx
+++ b/web/renderer/components/pageComponents/ConnectionsPage/NewConnection/index.tsx
@@ -1,182 +1,45 @@
-import {
- Button,
- ButtonsWithError,
- Checkbox,
- ExternalLink,
- FormInput,
- FormSelect,
- Loader,
-} from "@dolthub/react-components";
-import { DatabaseType } from "@gen/graphql-types";
+import { ExternalLink } from "@dolthub/react-components";
import { dockerHubRepo } from "@lib/constants";
-import { FaCaretDown } from "@react-icons/all-files/fa/FaCaretDown";
-import { FaCaretUp } from "@react-icons/all-files/fa/FaCaretUp";
-import { IoIosArrowDropleftCircle } from "@react-icons/all-files/io/IoIosArrowDropleftCircle";
-import cx from "classnames";
+import MainLayout from "@components/layouts/MainLayout";
+import WelcomeMessage from "./WelcomeMessage";
+import ConnectionTabs from "./ConnectionTabs";
import css from "./index.module.css";
-import useConfig, { getCanSubmit } from "./useConfig";
+import { ConfigProvider } from "./context/config";
type Props = {
- canGoBack: boolean;
- setShowForm: (s: boolean) => void;
+ noExistingConnection?: boolean;
};
-export default function NewConnection(props: Props) {
- const { onSubmit, state, setState, error, clearState } = useConfig();
-
- const onCancel = props.canGoBack
- ? () => {
- props.setShowForm(false);
- }
- : clearState;
+type InnerProps = {
+ showWelcomeMsg?: boolean;
+};
+function Inner({ showWelcomeMsg }: InnerProps) {
return (
-
- {props.canGoBack && (
-
- back to connections
-
- )}
+ {showWelcomeMsg &&
}
-
+
+
Set up a new connection
+
+ View instructions for connecting to local and Docker installed
+ databases here.
+
+
+
+
+
);
}
+
+export default function NewConnection({ noExistingConnection }: Props) {
+ return noExistingConnection ? (
+
+ ) : (
+
+
+
+ );
+}
diff --git a/web/renderer/components/pageComponents/ConnectionsPage/NewConnection/useConfig.ts b/web/renderer/components/pageComponents/ConnectionsPage/NewConnection/useConfig.ts
deleted file mode 100644
index b4e9f083..00000000
--- a/web/renderer/components/pageComponents/ConnectionsPage/NewConnection/useConfig.ts
+++ /dev/null
@@ -1,116 +0,0 @@
-import { useEffectOnMount, useSetState } from "@dolthub/react-hooks";
-import {
- DatabaseType,
- useAddDatabaseConnectionMutation,
-} from "@gen/graphql-types";
-import useMutation from "@hooks/useMutation";
-import { maybeDatabase } from "@lib/urls";
-import { useRouter } from "next/router";
-import { Dispatch, SyntheticEvent, useEffect } from "react";
-
-const defaultState = {
- name: "",
- host: "",
- hostPlaceholder: "127.0.0.1",
- port: "3306",
- username: "root",
- password: "",
- database: "",
- connectionUrl: "",
- hideDoltFeatures: false,
- useSSL: true,
- showAdvancedSettings: false,
- loading: false,
- type: DatabaseType.Mysql,
-};
-
-type ConfigState = typeof defaultState;
-type ConfigDispatch = Dispatch>;
-
-function getDefaultState(isDocker = false): ConfigState {
- const defaultHost = isDocker ? "host.docker.internal" : "127.0.0.1";
- return {
- ...defaultState,
- host: defaultHost,
- hostPlaceholder: defaultHost,
- };
-}
-
-type ReturnType = {
- onSubmit: (e: SyntheticEvent) => Promise;
- state: ConfigState;
- setState: ConfigDispatch;
- error?: Error | undefined;
- clearState: () => void;
-};
-
-export default function useConfig(): ReturnType {
- const router = useRouter();
-
- const [state, setState] = useSetState(defaultState);
- const { mutateFn, ...res } = useMutation({
- hook: useAddDatabaseConnectionMutation,
- });
-
- useEffectOnMount(() => {
- const isDocker = window.location.origin === "http://localhost:3000";
- setState(getDefaultState(isDocker));
- });
-
- useEffect(() => {
- if (!res.err) return;
- if (
- res.err.message.includes("The server does not support SSL connections")
- ) {
- setState({ showAdvancedSettings: true });
- }
- }, [res.err]);
-
- const clearState = () => {
- setState(defaultState);
- };
-
- const onSubmit = async (e: SyntheticEvent) => {
- e.preventDefault();
- setState({ loading: true });
-
- try {
- const db = await mutateFn({
- variables: {
- name: state.name,
- connectionUrl: getConnectionUrl(state),
- hideDoltFeatures: state.hideDoltFeatures,
- useSSL: state.useSSL,
- type: state.type,
- },
- });
- await res.client.clearStore();
- if (!db.data) {
- return;
- }
- const { href, as } = maybeDatabase(
- db.data.addDatabaseConnection.currentDatabase,
- );
- await router.push(href, as);
- } catch (_) {
- // Handled by res.error
- } finally {
- setState({ loading: false });
- }
- };
-
- return { onSubmit, state, setState, error: res.err, clearState };
-}
-
-function getConnectionUrl(state: ConfigState): string {
- if (state.connectionUrl) return state.connectionUrl;
- const prefix = state.type === DatabaseType.Mysql ? "mysql" : "postgresql";
- return `${prefix}://${state.username}:${state.password}@${state.host}:${state.port}/${state.database}`;
-}
-
-export function getCanSubmit(state: ConfigState): boolean {
- if (!state.name) return false;
- if (state.connectionUrl) return true;
- if (!state.host || !state.username) return false;
- return true;
-}
diff --git a/web/renderer/components/pageComponents/ConnectionsPage/index.module.css b/web/renderer/components/pageComponents/ConnectionsPage/index.module.css
index f41e333e..32cd718c 100644
--- a/web/renderer/components/pageComponents/ConnectionsPage/index.module.css
+++ b/web/renderer/components/pageComponents/ConnectionsPage/index.module.css
@@ -1,19 +1,3 @@
.container {
- @apply max-w-6xl py-24 bg-stone-50;
-}
-
-.inner {
- @apply flex justify-between;
-}
-
-.top {
- @apply mr-24 mt-10;
-
- h1 {
- @apply text-left;
- }
-
- p {
- @apply text-xl max-w-lg mt-7 leading-8;
- }
+ @apply py-16 bg-stone-50 mb-16 w-fit max-w-none;
}
diff --git a/web/renderer/components/pageComponents/ConnectionsPage/index.tsx b/web/renderer/components/pageComponents/ConnectionsPage/index.tsx
index 742bef28..1a49b8d4 100644
--- a/web/renderer/components/pageComponents/ConnectionsPage/index.tsx
+++ b/web/renderer/components/pageComponents/ConnectionsPage/index.tsx
@@ -1,56 +1,24 @@
import MainLayout from "@components/layouts/MainLayout";
-import DoltLink from "@components/links/DoltLink";
-import DoltgresLink from "@components/links/DoltgresLink";
import { QueryHandler } from "@dolthub/react-components";
-import {
- DatabaseConnectionFragment,
- useStoredConnectionsQuery,
-} from "@gen/graphql-types";
-import { useEffect, useState } from "react";
+import { useStoredConnectionsQuery } from "@gen/graphql-types";
import ExistingConnections from "./ExistingConnections";
import NewConnection from "./NewConnection";
import css from "./index.module.css";
-type InnerProps = {
- connections: DatabaseConnectionFragment[];
-};
-
-function Inner(props: InnerProps) {
- const [showForm, setShowForm] = useState(!props.connections.length);
-
- useEffect(() => {
- setShowForm(!props.connections.length);
- }, [props.connections]);
-
- if (showForm) {
- return (
-
- );
- }
- return ;
-}
-
export default function ConfigurationPage() {
const res = useStoredConnectionsQuery();
return (
-
-
-
Welcome to the Dolt Workbench
-
- Connect the workbench to any MySQL or PostgreSQL compatible
- database. Use or to unlock version
- control features.
-
-
-
}
- />
-
+
+ data.storedConnections.length ? (
+
+ ) : (
+
+ )
+ }
+ />
);
}
diff --git a/web/renderer/components/pageComponents/DatabasesPage/index.module.css b/web/renderer/components/pageComponents/DatabasesPage/index.module.css
index 1bb942b6..2a3c3503 100644
--- a/web/renderer/components/pageComponents/DatabasesPage/index.module.css
+++ b/web/renderer/components/pageComponents/DatabasesPage/index.module.css
@@ -1,35 +1,34 @@
+.container {
+ @apply flex flex-col items-center;
+}
+
.desc {
- @apply text-lg text-center mb-10;
+ @apply text-lg text-center mb-8;
+}
+
+.dbList {
+ @apply w-fit;
}
.database {
- @apply bg-white w-full border my-2 px-4 py-2 rounded flex justify-between;
+ @apply bg-white w-full h-14 border my-1 px-14 py-2 rounded flex justify-start items-center text-sky-400 min-w-80;
&:hover {
- @apply border-stone-300;
+ @apply border-stone-300 text-link-1;
+ }
+ svg {
+ @apply flex-shrink-0 mr-2;
}
}
.noDbs {
- @apply text-lg;
+ @apply text-lg italic;
}
.button {
- @apply bg-button-1 text-white my-6 px-4 py-1.5 text-base rounded button-shadow;
+ @apply text-white my-6 px-4 py-1.5 text-base rounded button-shadow bg-coral-300;
&:hover {
- @apply text-white bg-button-2 button-shadow-hover;
- }
-}
-
-.go {
- @apply hidden;
-}
-
-.database:hover .go {
- @apply flex items-center;
-
- svg {
- @apply ml-2;
+ @apply text-white bg-coral-400 button-shadow-hover;
}
}
diff --git a/web/renderer/components/pageComponents/DatabasesPage/index.tsx b/web/renderer/components/pageComponents/DatabasesPage/index.tsx
index 5ba48073..e62730e8 100644
--- a/web/renderer/components/pageComponents/DatabasesPage/index.tsx
+++ b/web/renderer/components/pageComponents/DatabasesPage/index.tsx
@@ -1,11 +1,12 @@
import CreateDatabase from "@components/CreateDatabase";
import MainLayout from "@components/layouts/MainLayout";
import Link from "@components/links/Link";
+import { excerpt } from "@dolthub/web-utils";
import { ErrorMsg, Loader } from "@dolthub/react-components";
import { useDatabasesQuery } from "@gen/graphql-types";
import useDatabaseDetails from "@hooks/useDatabaseDetails";
import { database } from "@lib/urls";
-import { FaChevronRight } from "@react-icons/all-files/fa/FaChevronRight";
+import { FaDatabase } from "@react-icons/all-files/fa/FaDatabase";
import cx from "classnames";
import { useRouter } from "next/router";
import { useEffect } from "react";
@@ -27,36 +28,36 @@ export default function DatabasesPage() {
return (
- Choose a database
-
- Choose an existing database or create a new database to get started.
-
- {res.data?.databases.length ? (
-
- {res.data.databases.map(db => (
- -
-
-
- {db}
-
- Go
-
-
-
-
- ))}
-
- ) : (
-
- No databases found. Create a database to get started.
+
+
Choose a database
+
+ Choose an existing database or create a new database to get started.
- )}
-
-
+ {res.data?.databases.length ? (
+
+ {res.data.databases.map(db => (
+ -
+
+
+
+ {excerpt(db, 32)}
+
+
+
+ ))}
+
+ ) : (
+
+ No databases found. Create a database to get started.
+
+ )}
+
+
+
);
diff --git a/web/renderer/lib/urls.ts b/web/renderer/lib/urls.ts
index b91a22cd..b2aebbd7 100644
--- a/web/renderer/lib/urls.ts
+++ b/web/renderer/lib/urls.ts
@@ -7,6 +7,10 @@ export type RefUrl = (p: ps.RefOptionalSchemaParams) => Route;
export const databases = new Route("/database");
+export const connections = new Route("/connections");
+
+export const newConnection = connections.addStatic("new");
+
export const database = (p: ps.DatabaseOptionalSchemaParams): Route =>
databases
.addDynamic("databaseName", p.databaseName)
diff --git a/web/renderer/pages/connections.tsx b/web/renderer/pages/connections/index.tsx
similarity index 87%
rename from web/renderer/pages/connections.tsx
rename to web/renderer/pages/connections/index.tsx
index e7f6a25a..c5b2a692 100644
--- a/web/renderer/pages/connections.tsx
+++ b/web/renderer/pages/connections/index.tsx
@@ -3,7 +3,7 @@ import Page from "@components/util/Page";
import { NextPage } from "next";
const Connections: NextPage = () => (
-
+
);
diff --git a/web/renderer/pages/connections/new.tsx b/web/renderer/pages/connections/new.tsx
new file mode 100644
index 00000000..b55a0e5d
--- /dev/null
+++ b/web/renderer/pages/connections/new.tsx
@@ -0,0 +1,11 @@
+import NewConnection from "@components/pageComponents/ConnectionsPage/NewConnection";
+import Page from "@components/util/Page";
+import { NextPage } from "next";
+
+const AddConnection: NextPage = () => (
+
+
+
+);
+
+export default AddConnection;
diff --git a/web/renderer/public/images/d-large-logo.png b/web/renderer/public/images/d-large-logo.png
new file mode 100644
index 00000000..0ddf53c1
Binary files /dev/null and b/web/renderer/public/images/d-large-logo.png differ
diff --git a/web/renderer/public/images/database-icon.png b/web/renderer/public/images/database-icon.png
new file mode 100644
index 00000000..6c0ec4e9
Binary files /dev/null and b/web/renderer/public/images/database-icon.png differ
diff --git a/web/renderer/tailwind.config.ts b/web/renderer/tailwind.config.ts
index f4eb0c8e..9992e30b 100644
--- a/web/renderer/tailwind.config.ts
+++ b/web/renderer/tailwind.config.ts
@@ -19,6 +19,11 @@ const config = mergeConfig({
"./renderer/styles/**/*.css",
],
theme: {
+ colors: {
+ coral: {
+ 300: "#FF8964",
+ },
+ },
extend: {},
},
plugins: [],
diff --git a/web/yarn.lock b/web/yarn.lock
index 1aa5386a..bd0f96c2 100644
--- a/web/yarn.lock
+++ b/web/yarn.lock
@@ -2564,7 +2564,7 @@ __metadata:
languageName: node
linkType: hard
-"@dolthub/react-components@npm:^0.2.6, @dolthub/react-components@npm:^0.2.7":
+"@dolthub/react-components@npm:^0.2.7":
version: 0.2.7
resolution: "@dolthub/react-components@npm:0.2.7"
dependencies:
@@ -2591,6 +2591,33 @@ __metadata:
languageName: node
linkType: hard
+"@dolthub/react-components@npm:^0.2.8":
+ version: 0.2.8
+ resolution: "@dolthub/react-components@npm:0.2.8"
+ dependencies:
+ "@dolthub/react-contexts": "npm:^0.1.0"
+ "@dolthub/react-hooks": "npm:^0.1.7"
+ "@dolthub/web-utils": "npm:^0.1.5"
+ "@react-icons/all-files": "npm:^4.1.0"
+ classnames: "npm:^2.5.1"
+ deepmerge: "npm:^4.3.1"
+ github-markdown-css: "npm:^5.8.1"
+ numeral: "npm:^2.0.6"
+ react-copy-to-clipboard: "npm:^5.1.0"
+ react-loader: "npm:^2.4.7"
+ react-markdown: "npm:^9.0.1"
+ react-select: "npm:^5.8.3"
+ react-tooltip: "npm:^5.28.0"
+ reactjs-popup: "npm:^2.0.6"
+ remark-gfm: "npm:^4.0.0"
+ tailwindcss: "npm:^3.4.1"
+ peerDependencies:
+ react: ^18
+ react-dom: ^18
+ checksum: 10c0/7708505e0e4b1fc610b52813ca703c9b8fa5d1204e7f1ea141361cde24b209d59b4c1c3def419066e3d2765489815721285015ae5a53905dd3ffeb5e3e17e1ac
+ languageName: node
+ linkType: hard
+
"@dolthub/react-contexts@npm:^0.1.0":
version: 0.1.0
resolution: "@dolthub/react-contexts@npm:0.1.0"
@@ -8897,7 +8924,7 @@ __metadata:
resolution: "dolt-workbench@workspace:."
dependencies:
"@apollo/client": "npm:^3.9.9"
- "@dolthub/react-components": "npm:^0.2.6"
+ "@dolthub/react-components": "npm:^0.2.8"
"@dolthub/react-contexts": "npm:^0.1.0"
"@dolthub/react-hooks": "npm:^0.1.7"
"@dolthub/web-utils": "npm:^0.1.8"
@@ -10780,6 +10807,13 @@ __metadata:
languageName: node
linkType: hard
+"github-markdown-css@npm:^5.8.1":
+ version: 5.8.1
+ resolution: "github-markdown-css@npm:5.8.1"
+ checksum: 10c0/67d3540731f9f1fc3b903362ef270e6db0ffe252fd4998a1a8777fc63b288b1904e5e57703e74a2ee04f1d613a4732b1949cb472b66a3c2e9e2b7a1750d1f0a6
+ languageName: node
+ linkType: hard
+
"glob-parent@npm:^5.1.2, glob-parent@npm:~5.1.2":
version: 5.1.2
resolution: "glob-parent@npm:5.1.2"
@@ -16501,6 +16535,26 @@ __metadata:
languageName: node
linkType: hard
+"react-select@npm:^5.8.3":
+ version: 5.10.0
+ resolution: "react-select@npm:5.10.0"
+ dependencies:
+ "@babel/runtime": "npm:^7.12.0"
+ "@emotion/cache": "npm:^11.4.0"
+ "@emotion/react": "npm:^11.8.1"
+ "@floating-ui/dom": "npm:^1.0.1"
+ "@types/react-transition-group": "npm:^4.4.0"
+ memoize-one: "npm:^6.0.0"
+ prop-types: "npm:^15.6.0"
+ react-transition-group: "npm:^4.3.0"
+ use-isomorphic-layout-effect: "npm:^1.2.0"
+ peerDependencies:
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
+ react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
+ checksum: 10c0/64cc73ef43556d0a199420d7d19f9f72e3c5e3a7f6828aef5421ec16cc0e4bc337061a8fa3c03afc5b929a087a4ca866f497e0ef865b03fe014c5cacde5e71dd
+ languageName: node
+ linkType: hard
+
"react-timeago@npm:^7.2.0":
version: 7.2.0
resolution: "react-timeago@npm:7.2.0"
@@ -16510,7 +16564,7 @@ __metadata:
languageName: node
linkType: hard
-"react-tooltip@npm:^5.26.3, react-tooltip@npm:^5.27.1":
+"react-tooltip@npm:^5.26.3, react-tooltip@npm:^5.27.1, react-tooltip@npm:^5.28.0":
version: 5.28.0
resolution: "react-tooltip@npm:5.28.0"
dependencies:
@@ -19111,6 +19165,18 @@ __metadata:
languageName: node
linkType: hard
+"use-isomorphic-layout-effect@npm:^1.2.0":
+ version: 1.2.0
+ resolution: "use-isomorphic-layout-effect@npm:1.2.0"
+ peerDependencies:
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
+ peerDependenciesMeta:
+ "@types/react":
+ optional: true
+ checksum: 10c0/2e4bdee68d65893b37e716ebdcc111550775189c80e662eda87d6f5b54dc431d3383a18914ea01a893ee5478902a878012713eaebcacbb6611ab88c463accb83
+ languageName: node
+ linkType: hard
+
"use-sync-external-store@npm:1.2.2, use-sync-external-store@npm:^1.2.0":
version: 1.2.2
resolution: "use-sync-external-store@npm:1.2.2"