Skip to content

Commit

Permalink
feat: finalize state structure
Browse files Browse the repository at this point in the history
  • Loading branch information
invm committed Jul 18, 2023
1 parent 64e9bc4 commit 9545c39
Show file tree
Hide file tree
Showing 7 changed files with 120 additions and 123 deletions.
22 changes: 13 additions & 9 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { Console } from 'components/Screens/Console/Console';
import { Home } from 'components/Screens/Home/Home';

function App() {
const { connectionsService: { tabsStore, setActiveTab, removeTab, clearStore } } = useAppSelector()
const { connectionsService: { removeTab, clearStore, connectionStore, setConnectionStore } } = useAppSelector()

const closeTab = async (id: string) => {
await removeTab(id)
Expand All @@ -19,18 +19,22 @@ function App() {
<div class="px-2 pb-2 bg-base-300 tabs tabs-boxed rounded-none gap-2 flex justify-between items-center">
<div class="flex items-center">
<div class="flex items-center">
<div onClick={() => setActiveTab(0)} class="tab tab-md"
classList={{ 'tab-active': tabsStore.activeConnectionTabIdx === 0, }} >
<div onClick={() => {
console.log('click')
setConnectionStore('idx', 0)
}} class="tab tab-md"
classList={{ 'tab-active': connectionStore.idx === 0, }} >
<span class="text-md font-bold">Home</span>
</div>
</div>
<For each={tabsStore.connectionTabs}>
<For each={connectionStore.tabs}>
{(tab, idx) =>
<div class="flex items-center">
<div onClick={() => setActiveTab(idx() + 1)} class="tab tab-md"
classList={{ 'tab-active': tabsStore.activeConnectionTabIdx === idx() + 1, }}
<div onClick={() => { setConnectionStore('idx', idx() + 1) }}
class="tab tab-md"
classList={{ 'tab-active': connectionStore.idx === idx() + 1, }}
><span class="text-md font-bold">{tab.label}</span></div>
<Show when={tabsStore.activeConnectionTabIdx === idx() + 1}>
<Show when={connectionStore.idx === idx() + 1}>
<button onClick={() => closeTab(tab.id!)} class="pl-2 mb-1">
<CloseIcon />
</button>
Expand All @@ -47,10 +51,10 @@ function App() {
<div class="h-full">
<div class="h-full">
<Switch>
<Match when={tabsStore.activeConnectionTabIdx === 0}>
<Match when={connectionStore.idx === 0}>
<Home />
</Match>
<Match when={tabsStore.activeConnectionTabIdx !== 0}>
<Match when={connectionStore.idx !== 0}>
<Console />
</Match>
</Switch>
Expand Down
2 changes: 1 addition & 1 deletion src/components/Screens/Console/Console.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Split from 'split.js'
import { createEffect, onCleanup } from "solid-js"
import { Sidebar } from 'components/Screens/Console/Sidebar'
import { Content } from 'components/Screens/Console/Content/Content'
import {Content} from 'components/Screens/Console/Content/Content'

export const Console = () => {
createEffect(() => {
Expand Down
36 changes: 16 additions & 20 deletions src/components/Screens/Console/Content/Content.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,40 +4,36 @@ import { AddIcon, CloseIcon } from "components/UI/Icons";
import { t } from "utils/i18n";
import { QueryTab } from "./QueryTab/QueryTab";
import { TableStructureTab } from "./TableStructureTab";
import { ContentComponent } from "services/ConnectionTabs";

export const NEW_QUERY_TAB = { label: 'Query', data: { query: '' }, key: ContentComponent.QueryTab }
import { ContentComponent, ContentTab, ContentTabData, NEW_QUERY_TAB } from "services/ConnectionTabs";

export const Content = () => {
const { connectionsService: {
updateActiveConnectionActiveContentTabIdx,
updateActiveConnectionContentTabs,
updateActiveContentTabData,
tabsStore: { activeConnectionTab: { contentTabs, activeTabIdx } } }
} = useAppSelector()
const { connectionsService: { contentStore, setContentStore } } = useAppSelector()

const addTab = async () => {
updateActiveConnectionContentTabs([...contentTabs, NEW_QUERY_TAB])
updateActiveConnectionActiveContentTabIdx(contentTabs.length - 1)
setContentStore('tabs', [...contentStore.tabs, NEW_QUERY_TAB])
setContentStore('idx', contentStore.tabs.length - 1)
}

const updateQueryText = async (query: string) => {
updateActiveContentTabData({ query })
setContentStore('tabs', contentStore.tabs.map((t, idx) => idx === contentStore.idx ? {
...t,
data: { ...t.data, query }
} as ContentTab<'QueryTab'> : t))
}

const closeTab = async (idx: number) => {
if (!idx) return;
updateActiveConnectionContentTabs(contentTabs.filter((_t, i) => i !== idx));
updateActiveConnectionActiveContentTabIdx(0)
setContentStore('tabs', contentStore.tabs.filter((_t, i) => i !== idx));
setContentStore('idx', 0)
}

return (
<div class="flex flex-col h-full">
<div class="bg-base-300 tabs gap-1">
<For each={contentTabs}>
<For each={contentStore.tabs}>
{(_tab, idx) =>
<div onClick={() => updateActiveConnectionActiveContentTabIdx(idx())} class="tab py-2 tab-md tab-lifted"
classList={{ 'tab-active': activeTabIdx === idx() }}
<div onClick={() => setContentStore('idx', idx())} class="tab py-2 tab-md tab-lifted"
classList={{ 'tab-active': contentStore.idx === idx() }}
>{t('components.console.query')} #{idx() + 1}
<Show when={idx() > 0}>
<button onClick={() => closeTab(idx())} class="pl-2 mb-1">
Expand All @@ -51,10 +47,10 @@ export const Content = () => {
</div>
<div class="flex-1">
<Switch>
<Match when={contentTabs[activeTabIdx]?.key === ContentComponent.QueryTab}>
<QueryTab query={contentTabs[activeTabIdx]?.data.query ?? ''} updateQueryText={updateQueryText} />
<Match when={contentStore.tabs[contentStore.idx]?.key === ContentComponent.QueryTab}>
<QueryTab query={(contentStore.tabs[contentStore.idx]?.data as ContentTabData['QueryTab']).query} updateQueryText={updateQueryText} />
</Match>
<Match when={contentTabs[activeTabIdx]?.key === ContentComponent.TableStructureTab}>
<Match when={contentStore.tabs[contentStore.idx]?.key === ContentComponent.TableStructureTab}>
<TableStructureTab />
</Match>
</Switch>
Expand Down
17 changes: 9 additions & 8 deletions src/components/Screens/Console/Sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,19 @@ const TypeToEmoji = {
}

export const Sidebar = () => {
const { connectionsService: { tabsStore: { activeConnectionTab: { schema } } } } = useAppSelector()
const { connectionsService: { connectionStore } } = useAppSelector()
const getSchema = () => connectionStore.tabs[connectionStore.idx - 1].schema
const [displayedSchema, setDisplayedSchema] = createSignal('')
const [tables, setTables] = createStore<Table[]>([])

onMount(() => {
const _schema = Object.keys(schema)[0];
const _schema = Object.keys(getSchema())[0];
setDisplayedSchema(_schema)
setTables(transformSchema(_schema))
})

const transformSchema = (sch: string) => {
const _tables = Object.entries(schema[sch])
const _tables = Object.entries(getSchema()[sch])
.reduce((acc: any, [name, columns]) => [...acc, {
name, columns: Object.entries(columns).reduce(
(cols: any, [name, props]) => [...cols, { name, props }], []
Expand All @@ -40,9 +41,9 @@ export const Sidebar = () => {
return _tables
};

const select = (schema: string) => {
setDisplayedSchema(schema)
setTables(transformSchema(schema))
const select = (_schema: string) => {
setDisplayedSchema(_schema)
setTables(transformSchema(_schema))
}

const emojiType = (t: string) => {
Expand All @@ -54,8 +55,8 @@ export const Sidebar = () => {
<div class="p-2 bg-base-200 h-full rounded-tr-lg">
<div class="pb-2 rounded-md">
<select value={displayedSchema()} onChange={(e) => select(e.currentTarget.value)} class="select select-accent select-bordered select-xs w-full">
<For each={Object.keys(schema)}>
{(schema) => <option class="py-1" value={schema}>{schema}</option>}
<For each={Object.keys(getSchema())}>
{(_schema) => <option class="py-1" value={_schema}>{_schema}</option>}
</For>
</select>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { invoke } from '@tauri-apps/api';
import { NEW_QUERY_TAB } from 'components/Screens/Console/Content/Content';
import { ConnectionConfig } from 'interfaces';
import { useAppSelector } from 'services/Context';

Expand Down Expand Up @@ -32,8 +31,6 @@ export const ActionsMenu = (props: { connection: ConnectionConfig }) => {
label: props.connection.name,
schema,
connection: props.connection,
contentTabs: [NEW_QUERY_TAB],
activeTabIdx: 0
})
} catch (error) {
addError(String(error))
Expand Down
150 changes: 68 additions & 82 deletions src/services/ConnectionTabs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { createStore } from "solid-js/store"
import { ConnectionConfig, DbSchema } from "../interfaces";
import { onMount } from "solid-js";
import { Store } from "tauri-plugin-store-api";
import { debounce } from "utils/utils";

const store = new Store(".connections.dat");

Expand All @@ -10,123 +11,108 @@ export const ContentComponent = {
TableStructureTab: 'TableStructureTab'
} as const;

export const NEW_QUERY_TAB = { label: 'Query', data: { query: '', results: [] }, key: ContentComponent.QueryTab }

type ContentComponentKeys = keyof typeof ContentComponent

export type ContentTab = {
export type ContentTabData = {
[ContentComponent.QueryTab]: {
query: string,
results: Record<string, any>[]
},
[ContentComponent.TableStructureTab]: {
table: string,
structure: Record<string, any>[]
indices: Record<string, any>[]
foreignKeys: Record<string, any>[]
triggers: Record<string, any>[]
}
}

export type ContentTab<C extends ContentComponentKeys> = {
label: string,
data: any
key: ContentComponentKeys
key: C,
data: ContentTabData[C]
}

type Tab = {
type ContentTabOption = ContentTab<'TableStructureTab'> | ContentTab<'QueryTab'>

type ConnectionTab = {
label: string,
id: string,
schema: DbSchema,
connection: ConnectionConfig,
contentTabs: ContentTab[],
activeTabIdx: number,
}

type TabStore = {
connectionTabs: Tab[],
activeConnectionTabIdx: number,
activeConnectionTab: Tab,
const CONNECTIONS_TABS_KEY = '_conn_tabs'
const CONTENT_TABS_KEY = '_content_tabs'

const getSavedData = async (key: string, defaultValue: any = []) => {
const str = await store.get(key);
if (!str) return defaultValue;
try {
const res = JSON.parse(str as string)
return res as unknown
} catch (e) {
console.log(e)
return defaultValue
}
}

const EMPTY_TAB = {
label: '',
id: '',
schema: { db_name: { col_name: {} } },
connection: {} as ConnectionConfig,
contentTabs: [],
activeTabIdx: 0,
type ConnectionStore = {
tabs: ConnectionTab[],
idx: number,
}

const _tabsStore = createStore<TabStore>({
connectionTabs: [],
activeConnectionTabIdx: 0,
activeConnectionTab: EMPTY_TAB,
});

const TAB_STORE_STORAGE_KEY = '_tabs'
type ContentStore = {
tabs: ContentTabOption[],
idx: number,
}

export const ConnectionTabsService = () => {
const [tabsStore, setTabsStore] = _tabsStore
const [connectionStore, setConnectionStore] = createStore<ConnectionStore>({ tabs: [], idx: 0 })
const [contentStore, setContentStore] = createStore<ContentStore>({ tabs: [], idx: 0 })

onMount(async () => {
const tabStr = await store.get(TAB_STORE_STORAGE_KEY);
if (!tabStr) return
const res = JSON.parse(tabStr as string)
setTabsStore(() => res as unknown as TabStore)
const conn_tabs = await getSavedData(CONNECTIONS_TABS_KEY)
setConnectionStore(() => conn_tabs as ConnectionStore)
const content = await getSavedData(CONTENT_TABS_KEY)
setContentStore(() => content as ContentStore)
})

const updateStore = async (newStore: TabStore) => {
await store.set(TAB_STORE_STORAGE_KEY, JSON.stringify(newStore));
const updateStore = debounce(async () => {
await store.set(CONNECTIONS_TABS_KEY, JSON.stringify(connectionStore));
await store.set(CONTENT_TABS_KEY, JSON.stringify(contentStore));
await store.save();
}

const addTab = async (tab: Tab) => {
if (tabsStore.connectionTabs.find(t => t.id === tab.id)) return;
setTabsStore('connectionTabs', tabsStore.connectionTabs.concat(tab))
setTabsStore('activeConnectionTab', tab)
const idx = tabsStore.connectionTabs.length;
setTabsStore('activeConnectionTabIdx', idx)
await updateStore(tabsStore)
}, 3000)

const addTab = async (tab: ConnectionTab) => {
if (connectionStore.tabs.find(t => t.id === tab.id)) return;
setConnectionStore('tabs', connectionStore.tabs.concat(tab))
setContentStore('tabs', [NEW_QUERY_TAB])
const idx = connectionStore.tabs.length;
setConnectionStore('idx', idx)
updateStore()
}

const removeTab = async (id: string) => {
setTabsStore('connectionTabs', tabsStore.connectionTabs.filter((t) => t.id !== id));
setTabsStore('activeConnectionTab', EMPTY_TAB)
setTabsStore('activeConnectionTabIdx', 0)
await updateStore(tabsStore)
}

const setActiveTab = async (idx: number) => {
if (idx > 0) {
const tabs = tabsStore.connectionTabs
tabs[tabsStore.activeConnectionTabIdx] = tabsStore.activeConnectionTab
setTabsStore('connectionTabs', tabs);
const tab = tabsStore.connectionTabs[idx - 1]
setTabsStore('activeConnectionTab', tab)
}
setTabsStore('activeConnectionTabIdx', idx)
await updateStore(tabsStore)
setConnectionStore('tabs', connectionStore.tabs.filter((t) => t.id !== id));
setConnectionStore('idx', 0)
updateStore()
}

const clearStore = async () => {
await store.clear();
}

const updateActiveContentTabData = (data: Record<string, any>) => {
const activeTabIdx = tabsStore.activeConnectionTab.activeTabIdx;
const activeConnectionTab = { ...tabsStore.activeConnectionTab };
activeConnectionTab.contentTabs[activeTabIdx].data = data;
setTabsStore('activeConnectionTab', activeConnectionTab)
}

const updateActiveConnectionContentTabs = (tabs: ContentTab[]) => {
const activeConnectionTab = { ...tabsStore.activeConnectionTab };
activeConnectionTab.contentTabs = tabs;
console.log(activeConnectionTab.contentTabs)
setTabsStore('activeConnectionTab', activeConnectionTab)
}

const updateActiveConnectionActiveContentTabIdx = (idx: number) => {
const activeConnectionTab = { ...tabsStore.activeConnectionTab }
activeConnectionTab.activeTabIdx = idx
setTabsStore('activeConnectionTab', activeConnectionTab)
}


return {
tabsStore,
connectionStore,
setConnectionStore,
contentStore,
setContentStore,
addTab,
removeTab,
setActiveTab,
clearStore,
updateActiveConnectionActiveContentTabIdx,
updateActiveConnectionContentTabs,
updateActiveContentTabData,
}
}

Loading

0 comments on commit 9545c39

Please sign in to comment.