Skip to content

Commit

Permalink
Merge pull request #30 from jdeniau/fix-router-and-context-conflicts
Browse files Browse the repository at this point in the history
use more react-router patterns to fix conflict between config and routing
  • Loading branch information
jdeniau authored Mar 5, 2024
2 parents c9665a0 + 9250db4 commit b81d2e6
Show file tree
Hide file tree
Showing 20 changed files with 319 additions and 163 deletions.
4 changes: 0 additions & 4 deletions .storybook/preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,6 @@ const preview: Preview = {
</MemoryRouter>
),
(Story, { globals: { theme } }) => {
// const themeName = useParameter('backgrounds');

// console.log('themeName', themeName);

return (
<ConfigurationContext.Provider
// weirdly needed to force storybook to re-render
Expand Down
2 changes: 1 addition & 1 deletion src/configuration/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
const envPath = envPaths('TianaTables', { suffix: '' });
const dataFilePath = resolve(envPath.config, 'config.json');

console.log('Configuration file path:', dataFilePath);
console.log('[CONFIG] Configuration file path:', dataFilePath);

function getBaseConfig(): Configuration {
return {
Expand Down
2 changes: 1 addition & 1 deletion src/contexts/ConnectionContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { ConnectionObject } from '../sql/types';
interface ConnectToFunc {
(params: ConnectionObject): Promise<void>;
}
interface ConnexionContextProps {
export interface ConnexionContextProps {
currentConnectionName: string | null;
connectionNameList: string[];
connectTo: ConnectToFunc;
Expand Down
2 changes: 1 addition & 1 deletion src/contexts/DatabaseContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { QueryResult, QueryReturnType } from '../sql/types';
interface SetDatabaseFunc {
(theme: string): void;
}
interface DatabaseContextProps {
export interface DatabaseContextProps {
database: string | null;
setDatabase: SetDatabaseFunc;
executeQuery: <T extends QueryReturnType>(query: string) => QueryResult<T>;
Expand Down
2 changes: 1 addition & 1 deletion src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const isMac = process.platform !== 'darwin';
function installReactDevToolsExtension() {
installExtension(REACT_DEVELOPER_TOOLS)
.then((name) => {
console.log(`Added Extension: ${name}`);
console.log(`[DEBUG] Added Extension: ${name}`);

// once extension is loaded, reload the view after a short period (probably to be sure that the extension is loaded ?)
BrowserWindow.getAllWindows().forEach((win) => {
Expand Down
2 changes: 1 addition & 1 deletion src/preload/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { bindChannel } from './bindChannel';
import { CONFIGURATION_CHANNEL } from './configurationChannel';

interface Config {
getConfiguration(): Promise<null | Configuration>;
getConfiguration(): Promise<Configuration>;

addConnectionToConfig(connection: ConnectionObject): Promise<Configuration>;

Expand Down
8 changes: 5 additions & 3 deletions src/preload/sql.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { Connection } from 'mysql2/promise';
import type {
ConnectionObject,
QueryResult,
Expand All @@ -8,8 +7,11 @@ import { bindChannel } from './bindChannel';
import { SQL_CHANNEL } from './sqlChannel';

interface Sql {
openConnection(params: ConnectionObject): Promise<Connection>;
executeQuery<T extends QueryReturnType>(query: string): QueryResult<T>;
openConnection(params: ConnectionObject): Promise<void>;
executeQuery<T extends QueryReturnType>(
connectionName: string,
query: string
): QueryResult<T>;
closeAllConnections(): Promise<void>;
}

Expand Down
31 changes: 20 additions & 11 deletions src/renderer/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,17 @@ import ErrorPage from './error-page';
import Connect from './routes/connect';
import Create from './routes/connect/create';
import Edit from './routes/connect/edit.$connectionName';
import TableName, {
loader as tableNameLoader,
import ConnectionDetailPage, {
loader as connectionDetailPageLoader,
} from './routes/connections.$connectionName';
import DatabaseDetailPage, {
loader as databaseDetailPageLoader,
} from './routes/connections.$connectionName.$databaseName';
import TableNamePage, {
loader as tableNamePageLoader,
} from './routes/connections.$connectionName.$databaseName.$tableName';
import { Home } from './routes/home';
import Root from './routes/root';
import { Tables } from './routes/tables';

const appElement = document.getElementById('App');

Expand Down Expand Up @@ -53,16 +58,20 @@ const router = createMemoryRouter([
},
{
path: 'connections/:connectionName',
element: <Tables />,
},
{
path: 'connections/:connectionName/:databaseName',
element: <Tables />,
element: <ConnectionDetailPage />,
loader: connectionDetailPageLoader,
children: [
{
path: ':tableName',
loader: tableNameLoader,
element: <TableName />,
path: ':databaseName',
element: <DatabaseDetailPage />,
loader: databaseDetailPageLoader,
children: [
{
path: ':tableName',
loader: tableNamePageLoader,
element: <TableNamePage />,
},
],
},
],
},
Expand Down
87 changes: 87 additions & 0 deletions src/renderer/component/Connection/ConnectionPage.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { action } from '@storybook/addon-actions';
import type { Meta, StoryObj } from '@storybook/react';
import { DEFAULT_THEME } from '../../../configuration/themes';
import { testables } from '../../../contexts/ConfigurationContext';
import { ConnectionContext } from '../../../contexts/ConnectionContext';
import ConnectionPage from './ConnectionPage';

const { ConfigurationContext } = testables;

const meta: Meta<typeof ConnectionPage> = {
component: ConnectionPage,
decorators: [
(Story) => (
<ConnectionContext.Provider
value={{
currentConnectionName: null,
connectionNameList: [],
connectTo: async (connection) => {
action('connectTo')(connection);
},
}}
>
<Story />
</ConnectionContext.Provider>
),
(Story) => (
<ConfigurationContext.Provider
value={{
configuration: {
version: 1,
theme: DEFAULT_THEME.name,
connections: {
test: {
name: 'test',
host: 'localhost',
port: 3307,
user: 'root',
password: '',
},
'production connection': {
name: 'prod',
host: 'localhost',
port: 3306,
user: 'root',
password: '',
},
},
},

addConnectionToConfig: (connection) => {
action('addConnectionToConfig')(connection);
},
updateConnectionState: (connectionName, key, value) => {
action('updateConnectionState')(connectionName, key, value);
},
editConnection: (name, connection) => {
action('editConnection')(name, connection);
},
}}
>
<Story />
</ConfigurationContext.Provider>
),
],
};

export default meta;
type Story = StoryObj<typeof ConnectionPage>;

/*
*👇 Render functions are a framework specific feature to allow you control on how the component renders.
* See https://storybook.js.org/docs/api/csf
* to learn how to use render functions.
*/
export const Primary: Story = {};

// export const Edit: Story = {
// args: {
// connection: {
// name: 'test',
// host: 'localhost',
// port: 3307,
// user: 'test-user',
// password: '',
// },
// },
// };
4 changes: 0 additions & 4 deletions src/renderer/component/Connection/ConnectionPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,6 @@ function ConnectionPage() {
const registeredConnectionList = useConfiguration().configuration.connections;
const { connectTo } = useConnectionContext();

if (registeredConnectionList === null) {
return <div>Reading configuration...</div>;
}

const connectionList = Object.values(registeredConnectionList);

if (Object.keys(registeredConnectionList).length === 0) {
Expand Down
65 changes: 45 additions & 20 deletions src/renderer/component/Connection/ConnectionStack.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
import { ReactNode, useCallback, useEffect, useState } from 'react';
import { ReactNode, useCallback, useEffect, useMemo, useState } from 'react';
import { useMatch, useNavigate } from 'react-router';
import invariant from 'tiny-invariant';
import { ConnectionContext } from '../../../contexts/ConnectionContext';
import { DatabaseContext } from '../../../contexts/DatabaseContext';
import {
ConnectionContext,
ConnexionContextProps,
} from '../../../contexts/ConnectionContext';
import {
DatabaseContext,
DatabaseContextProps,
} from '../../../contexts/DatabaseContext';
import type { ConnectionObject } from '../../../sql/types';
import { getErrorMessage } from '../../utils/error';

interface Props {
children: ReactNode;
Expand All @@ -27,14 +34,19 @@ function ConnectionStack({ children }: Props) {
};
}, []);

// TODO we might need to change that into the proper route as reload will not work
const handleConnectTo = useCallback(
async (params: ConnectionObject) => {
await window.sql.openConnection(params);
setConnectionNameList((prev) => [...prev, params.name]);
try {
await window.sql.openConnection(params);
setConnectionNameList((prev) => [...prev, params.name]);
} catch (error: unknown) {
console.error(getErrorMessage(error));
}

navigate(`/connections/${params.name}`);
},
[navigate, setConnectionNameList]
[navigate]
);

const handleSetDatabase = useCallback(
Expand All @@ -46,21 +58,34 @@ function ConnectionStack({ children }: Props) {
[currentConnectionName, navigate]
);

const connectionContextValue = useMemo(
(): ConnexionContextProps => ({
connectionNameList,
currentConnectionName: currentConnectionName ?? null,
connectTo: handleConnectTo,
}),
[connectionNameList, currentConnectionName, handleConnectTo]
);

const databateContextValue = useMemo(
(): DatabaseContextProps => ({
database: databaseName ?? null,
setDatabase: handleSetDatabase,
executeQuery: (query) => {
invariant(
currentConnectionName,
'Connection name is required to execute a query'
);

return window.sql.executeQuery(currentConnectionName, query);
},
}),
[currentConnectionName, databaseName, handleSetDatabase]
);

return (
<ConnectionContext.Provider
value={{
connectionNameList,
currentConnectionName: currentConnectionName ?? null,
connectTo: handleConnectTo,
}}
>
<DatabaseContext.Provider
value={{
database: databaseName ?? null,
setDatabase: handleSetDatabase,
executeQuery: window.sql.executeQuery,
}}
>
<ConnectionContext.Provider value={connectionContextValue}>
<DatabaseContext.Provider value={databateContextValue}>
{children}
</DatabaseContext.Provider>
</ConnectionContext.Provider>
Expand Down
57 changes: 9 additions & 48 deletions src/renderer/component/DatabaseSelector.tsx
Original file line number Diff line number Diff line change
@@ -1,53 +1,14 @@
import { useCallback, useEffect, useState } from 'react';
import { useCallback } from 'react';
import { Select } from 'antd';
import { RowDataPacket } from 'mysql2';
import invariant from 'tiny-invariant';
import { useConfiguration } from '../../contexts/ConfigurationContext';
import { useConnectionContext } from '../../contexts/ConnectionContext';
import { useDatabaseContext } from '../../contexts/DatabaseContext';

interface DatabaseRow extends RowDataPacket {
Database: string;
}

export default function DatabaseSelector() {
const { currentConnectionName } = useConnectionContext();
const { updateConnectionState, configuration } = useConfiguration();
const [databaseList, setDatabaseList] = useState<DatabaseRow[]>([]);
const { database, setDatabase, executeQuery } = useDatabaseContext();

useEffect(() => {
executeQuery<DatabaseRow[]>('SHOW DATABASES;').then(([result]) => {
if (result) {
invariant(currentConnectionName, 'Connection name is required');

setDatabaseList(result);

// TODO : add a helper for appState ?
const currentDatabase =
configuration.connections[currentConnectionName]?.appState
?.activeDatabase ?? result[0].Database;

setDatabase(currentDatabase);
}
});
}, [
configuration.connections,
currentConnectionName,
executeQuery,
setDatabase,
]);

// TODO migrate that into something that does only the side effect ?
useEffect(() => {
invariant(currentConnectionName, 'Connection name is required');

updateConnectionState(
currentConnectionName,
'activeDatabase',
database ?? ''
);
}, [currentConnectionName, database, updateConnectionState]);
import type { ShowDatabasesResult } from '../../sql/types';

export default function DatabaseSelector({
databaseList,
}: {
databaseList: ShowDatabasesResult;
}) {
const { database, setDatabase } = useDatabaseContext();

const handleChange = useCallback(
(database: string) => {
Expand Down
Loading

0 comments on commit b81d2e6

Please sign in to comment.