Skip to content

Commit

Permalink
Merge pull request #302 from dolthub/liuliu/web-nav-dropdown
Browse files Browse the repository at this point in the history
Web: added connections and databases selector, changed theme color
  • Loading branch information
liuliu-dev authored Jan 15, 2025
2 parents e5bac37 + 977d422 commit c050456
Show file tree
Hide file tree
Showing 58 changed files with 950 additions and 330 deletions.
10 changes: 10 additions & 0 deletions web/README.desktop-app.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
## Run the desktop app in dev mode:

1. Rebuild `graphql-server` (if changes were made):

```bash
# in graphql-server
yarn build
```

2.Start the desktop app:

```bash
# in web
yarn dev:app
```

Expand Down
10 changes: 4 additions & 6 deletions web/main/background.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,10 +125,9 @@ app.on("ready", async () => {
mainWindow = createWindow("main", {
width: 1400,
height: 900,
minHeight: 600,
minWidth: 600,
titleBarStyle: process.platform === "darwin" ? "hiddenInset" : undefined,
titleBarOverlay: process.platform === "darwin",
titleBarOverlay:
process.platform === "darwin" ? { height: HEADER_HEIGHT } : undefined,
trafficLightPosition: {
x: 20,
y: HEADER_HEIGHT / 2 - MACOS_TRAFFIC_LIGHTS_HEIGHT / 2,
Expand All @@ -142,9 +141,7 @@ app.on("ready", async () => {
Menu.setApplicationMenu(initMenu(mainWindow, isProd));
setupTitleBarClickMac();
createGraphqlSeverProcess();
mainWindow?.webContents.executeJavaScript(
` console.error('for mac nav:', ${process.env.NEXT_PUBLIC_FOR_MAC_NAV})`,
);

await waitForGraphQLServer("http://localhost:9002/graphql");

if (isProd) {
Expand All @@ -163,6 +160,7 @@ app.on("ready", async () => {

return { action: "deny" };
});
mainWindow.setMinimumSize(1080, 780);

// hit when clicking <a href/> with no target
// optionally redirect to browser
Expand Down
1 change: 0 additions & 1 deletion web/main/helpers/create-window.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ export const createWindow = (
};

state = ensureVisibleOnSomeDisplay(restore());

const win = new BrowserWindow({
...state,
...options,
Expand Down
2 changes: 1 addition & 1 deletion web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@
"autoprefixer": "^10.4.19",
"babel-jest": "^29.7.0",
"cssnano": "^7.0.6",
"electron": "^31.0.1",
"electron": "33.2.1",
"electron-builder": "^25.1.8",
"eslint": "^8.57.0",
"eslint-config-airbnb": "^19.0.4",
Expand Down
53 changes: 53 additions & 0 deletions web/renderer/components/ConnectionsAndDatabases/ConnectionItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import {
DatabaseConnection,
DatabaseConnectionFragment,
} from "@gen/graphql-types";
import { MdRemoveRedEye } from "@react-icons/all-files/md/MdRemoveRedEye";
import { FaChevronRight } from "@react-icons/all-files/fa/FaChevronRight";
import { Button } from "@dolthub/react-components";
import { excerpt } from "@dolthub/web-utils";
import cx from "classnames";
import { DatabaseTypeLabel } from "./DatabaseTypeLabel";
import css from "./index.module.css";

type Props = {
conn: DatabaseConnectionFragment;
selectedConnection: DatabaseConnectionFragment;
onSelected: (conn: DatabaseConnection) => void;
currentConnection: DatabaseConnection;
};
export default function ConnectionItem({
conn,
selectedConnection,
onSelected,
currentConnection,
}: Props) {
return (
<Button.Link
key={conn.name}
className={cx(css.connection, {
[css.selected]: selectedConnection.name === conn.name,
})}
onClick={async () => onSelected(conn)}
>
<div className={css.connectionTop}>
<div className={css.nameAndLabel}>
<span className={css.connectionName}>{excerpt(conn.name, 16)}</span>
<DatabaseTypeLabel conn={conn} />
{conn.name === currentConnection.name && (
<MdRemoveRedEye className={css.viewing} />
)}
</div>
<FaChevronRight className={css.arrow} />
</div>
<div className={css.connectionUrl}>
{excerpt(getHostAndPort(conn.connectionUrl), 42)}
</div>
</Button.Link>
);
}

function getHostAndPort(connectionString: string) {
const url = new URL(connectionString);
return `${url.hostname}:${url.port}`;
}
77 changes: 77 additions & 0 deletions web/renderer/components/ConnectionsAndDatabases/DatabaseItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { Button, ErrorMsg, Loader } from "@dolthub/react-components";
import { MdRemoveRedEye } from "@react-icons/all-files/md/MdRemoveRedEye";
import {
DatabaseConnectionFragment,
DatabaseType,
useAddDatabaseConnectionMutation,
useResetDatabaseMutation,
} from "@gen/graphql-types";
import useMutation from "@hooks/useMutation";
import { useRouter } from "next/router";
import { database } from "@lib/urls";
import { excerpt } from "@dolthub/web-utils";
import cx from "classnames";
import css from "./index.module.css";

type Props = {
db: string;
conn: DatabaseConnectionFragment;
currentConnection: DatabaseConnectionFragment;
currentDatabase: string;
};

export default function DatabaseItem({
db,
conn,
currentConnection,
currentDatabase,
}: Props) {
const {
mutateFn: resetDB,
loading,
err,
} = useMutation({
hook: useResetDatabaseMutation,
});
const router = useRouter();
const [addDb, res] = useAddDatabaseConnectionMutation();

const onClick = async (databaseName: string) => {
const addedDb = await addDb({ variables: conn });
if (!addedDb.data) {
return;
}
await res.client.clearStore();

if (conn.type === DatabaseType.Postgres) {
await resetDB({ variables: { newDatabase: databaseName } });
}
const { href, as } = database({ databaseName });
router.push(href, as).catch(console.error);
};

if (loading) {
return <Loader loaded={!loading} />;
}

if (err) {
return <ErrorMsg err={err} />;
}
const dbName = excerpt(db, 32);
if (db === currentDatabase && conn.name === currentConnection.name) {
return (
<span className={css.dbItem}>
{dbName}
<MdRemoveRedEye className={css.viewing} />
</span>
);
}
return (
<Button.Link
className={cx(css.dbItem, css.link)}
onClick={async () => onClick(db)}
>
{dbName}
</Button.Link>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { getDatabaseType } from "@components/DatabaseTypeLabel";
import { DatabaseConnectionFragment } from "@gen/graphql-types";
import css from "./index.module.css";

type Props = {
conn: DatabaseConnectionFragment;
};

export function DatabaseTypeLabel({ conn }: Props) {
const type = getDatabaseType(conn.type ?? undefined, !!conn.isDolt);
switch (type) {
case "Dolt":
return (
<span className={css.label}>
<img src="/images/dolt-logo.png" alt="Dolt" />
</span>
);
case "MySQL":
return (
<span className={css.label}>
<img src="/images/mysql-logo.png" alt="MySQL" />
</span>
);
case "PostgreSQL":
return (
<span className={css.label}>
<img src="/images/postgres-logo.png" alt="PostgreSQL" />
</span>
);
case "DoltgreSQL":
return (
<span className={css.label}>
<img src="/images/doltgres-logo.png" alt="DoltgreSQL" />
</span>
);
default:
return <span className={css.label}>{type}</span>;
}
}
72 changes: 72 additions & 0 deletions web/renderer/components/ConnectionsAndDatabases/Popup.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { DatabaseConnection, DatabaseType } from "@gen/graphql-types";
import { DatabaseParams } from "@lib/params";
import cx from "classnames";
import Link from "@components/links/Link";
import { ErrorMsg, SmallLoader } from "@dolthub/react-components";
import CreateDatabase from "@components/CreateDatabase";
import { FiTool } from "@react-icons/all-files/fi/FiTool";
import { StateType } from "./useSelectedConnection";
import DatabaseItem from "./DatabaseItem";
import css from "./index.module.css";
import ConnectionItem from "./ConnectionItem";

type Props = {
params: DatabaseParams;
currentConnection: DatabaseConnection;
onSelected: (conn: DatabaseConnection) => void;
storedConnections: DatabaseConnection[];
state: StateType;
};

export default function Popup({
params,
currentConnection,
onSelected,
storedConnections,
state,
}: Props) {
return (
<div className={css.container}>
<div className={css.top}>
<div className={cx(css.header, css.left)}>
<span>CONNECTIONS</span>
<Link href="/connections">
<FiTool className={css.wrench} />
</Link>
</div>
<div className={cx(css.header, css.right)}>
<span>DATABASES</span>
<CreateDatabase
isPostgres={currentConnection.type === DatabaseType.Postgres}
/>
</div>
</div>
<div className={css.middle}>
<div className={css.left}>
{storedConnections.map(conn => (
<ConnectionItem
key={conn.name}
conn={conn}
currentConnection={currentConnection}
onSelected={onSelected}
selectedConnection={state.connection}
/>
))}
</div>
<div className={css.right}>
{state.loading && <SmallLoader loaded={!state.loading} />}
{state.databases.map(db => (
<DatabaseItem
key={db}
db={db}
conn={state.connection}
currentConnection={currentConnection}
currentDatabase={params.databaseName}
/>
))}
<ErrorMsg err={state.err} />
</div>
</div>
</div>
);
}
Loading

0 comments on commit c050456

Please sign in to comment.