Skip to content

Commit

Permalink
Move connections button position & add settings page (#77)
Browse files Browse the repository at this point in the history
* Update TopPivot.tsx

* ConnectionButton

* move ConnectionButton

* add settings page

* update getMap

* v0.2.0

* Update settings.tsx

* v0.1.2

* catch getMap
  • Loading branch information
renzholy authored Aug 6, 2020
1 parent 5831544 commit 879ae83
Show file tree
Hide file tree
Showing 8 changed files with 267 additions and 176 deletions.
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@renzholy/mongood",
"version": "0.1.0",
"version": "0.1.2",
"description": "A MongoDB GUI",
"main": "index.js",
"private": "true",
Expand Down
148 changes: 148 additions & 0 deletions src/components/ConnectionButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
import React, { useEffect, useCallback, useState, useMemo } from 'react'
import {
CommandButton,
ContextualMenuItemType,
IContextualMenuItem,
IStyle,
} from '@fluentui/react'
import useSWR from 'swr'
import { useSelector, useDispatch } from 'react-redux'
import useAsyncEffect from 'use-async-effect'
import { compact } from 'lodash'

import { listConnections, runCommand } from '@/utils/fetcher'
import { actions } from '@/stores'
import { ServerStats } from '@/types'
import { ConnectionEditModal } from './ConnectionEditModal'

export function ConnectionButton(props: { style?: IStyle }) {
const connection = useSelector((state) => state.root.connection)
const connections = useSelector((state) => state.root.connections)
const dispatch = useDispatch()
const { data } = useSWR('connections', listConnections)
const serverStatus = useCallback(
async (_connection: string) =>
runCommand<ServerStats>(_connection, 'admin', {
serverStatus: 1,
}),
[],
)
const [selfConnections, setSelfConnections] = useState<
{ c: string; host: string; replSetName?: string }[]
>([])
useAsyncEffect(
async (isMounted) => {
const _connections = await Promise.all(
connections.map(async (c) => {
try {
const { host, repl } = await serverStatus(c)
return { c, host, replSetName: repl?.setName }
} catch {
return { c, host: c }
}
}),
)
if (isMounted()) {
setSelfConnections(compact(_connections))
}
},
[connections, serverStatus],
)
const [builtInConnections, setBuiltInConnections] = useState<
{ c: string; host: string; replSetName?: string }[]
>([])
useAsyncEffect(
async (isMounted) => {
const _connections = await Promise.all(
(data || []).map(async (c) => {
try {
const { host, repl } = await serverStatus(c)
return { c, host, replSetName: repl?.setName }
} catch {
return { c, host: c }
}
}),
)
if (isMounted()) {
setBuiltInConnections(compact(_connections))
}
},
[data, serverStatus],
)
const [isOpen, setIsOpen] = useState(false)
useEffect(() => {
if ((data?.length || connections.length) && !connection) {
dispatch(actions.root.setConnection([...connections, ...(data || [])][0]))
}
}, [connection, connections, data, dispatch])
useEffect(() => {
if (connections.length === 0 && data?.length === 0) {
setIsOpen(true)
}
}, [connection, connections, data])
const connectionToItem = useCallback(
({ c, host, replSetName }) => ({
key: c,
text: host,
secondaryText: replSetName,
canCheck: true,
checked: connection === c,
onClick() {
dispatch(actions.root.setConnection(c))
},
}),
[connection, dispatch],
)
const items = useMemo<IContextualMenuItem[]>(
() =>
compact([
...selfConnections.map(connectionToItem),
selfConnections.length
? { key: 'divider0', itemType: ContextualMenuItemType.Divider }
: undefined,
...builtInConnections.map(connectionToItem),
{ key: 'divider1', itemType: ContextualMenuItemType.Divider },
{
key: 'create',
text: 'Edit Connections',
onClick() {
setIsOpen(true)
},
},
]),
[builtInConnections, connectionToItem, selfConnections],
)

return (
<>
<ConnectionEditModal
isOpen={isOpen}
onDismiss={() => {
setIsOpen(false)
}}
/>
<CommandButton
text={
[...builtInConnections, ...selfConnections].find(
({ c }) => c === connection,
)?.host || 'Connection'
}
styles={{
root: props.style,
label: {
overflow: 'hidden',
textOverflow: 'ellipsis',
display: 'block',
textAlign: 'start',
wordBreak: 'break-all',
},
}}
iconProps={{ iconName: 'Database' }}
menuIconProps={{ hidden: true }}
menuProps={{
items,
}}
/>
</>
)
}
14 changes: 14 additions & 0 deletions src/components/DatabaseNav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import useAsyncEffect from 'use-async-effect'
import { actions } from '@/stores'
import { runCommand } from '@/utils/fetcher'
import { DatabaseContextualMenu } from './DatabaseContextualMenu'
import { ConnectionButton } from './ConnectionButton'

const splitter = '/'

Expand Down Expand Up @@ -251,6 +252,19 @@ export function DatabaseNav() {
}}
/>
</div>
<div
style={{
flexShrink: 0,
backgroundColor: theme.palette.neutralLight,
}}>
<ConnectionButton
style={{
width: '100%',
marginTop: 10,
marginBottom: 10,
}}
/>
</div>
</div>
)
}
11 changes: 3 additions & 8 deletions src/components/TableCell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ function PlainCard(props: { value: MongoData; index2dsphere?: MongoData }) {
props.index2dsphere,
])
const theme = getTheme()
const mapSrc = location ? getMap(500, 250, ...location) : undefined

return (
<div
Expand All @@ -25,15 +26,9 @@ function PlainCard(props: { value: MongoData; index2dsphere?: MongoData }) {
overflowY: 'scroll',
backgroundColor: theme.palette.neutralLighterAlt,
}}>
{location ? (
{mapSrc ? (
<img
src={getMap(
{
width: 500,
height: 250,
},
...location,
)}
src={mapSrc}
alt="map"
width={500}
height={250}
Expand Down
Loading

0 comments on commit 879ae83

Please sign in to comment.