Skip to content

Commit d1ddd8d

Browse files
feat(overmind-devtools): connect to devtools using default port and document title
BREAKING CHANGE: no need to add devtools option
1 parent e3a82eb commit d1ddd8d

File tree

10 files changed

+255
-76
lines changed

10 files changed

+255
-76
lines changed

packages/node_modules/overmind-devtools/src/app/actions.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Action } from 'overmind'
22
import * as mutations from './mutations'
33
import * as operations from './operations'
4-
import { Message, Tab } from './types'
4+
import { Message, Tab, GroupedComponent } from './types'
55

66
const handleClientMessages: Action<Message> = (action) =>
77
action
@@ -52,11 +52,14 @@ type Collapsed = {
5252
isCollapsed: boolean
5353
}
5454

55-
export const toggleCollapsed: Action<Collapsed> = (action) =>
55+
export const toggleCollapsedActionItem: Action<Collapsed> = (action) =>
5656
action
5757
.filter(operations.isNotExpandingAllActions)
5858
.mutate(mutations.toggleCollapsed)
5959

60+
export const toggleGroupedComponent: Action<string> = (action) =>
61+
action.mutate(mutations.toggleGroupedComponent)
62+
6063
export const selectApp: Action<string> = (action) =>
6164
action.mutate(mutations.selectApp)
6265

packages/node_modules/overmind-devtools/src/app/mutations.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
ActionsListItemType,
66
ActionItem,
77
ActionGroupItem,
8+
GroupedComponent,
89
} from './types'
910
import {
1011
runMutation,
@@ -333,8 +334,18 @@ type Collapse = {
333334
isCollapsed: boolean
334335
}
335336

336-
export const toggleCollapsed: Mutate<Collapse> = (_, item) =>
337-
(item.isCollapsed = !item.isCollapsed)
337+
export const toggleCollapsed: Mutate<Collapse> = (_, item) => {
338+
item.isCollapsed = !item.isCollapsed
339+
}
338340

339341
export const toggleExpandAllActions: Mutate = (state) =>
340342
(state.expandAllActionDetails = !state.expandAllActionDetails)
343+
344+
export const toggleGroupedComponent: Mutate<string> = (state, name) => {
345+
const index = state.expandedComponents.indexOf(name)
346+
if (index === -1) {
347+
state.expandedComponents.push(name)
348+
} else {
349+
state.expandedComponents.splice(index, 1)
350+
}
351+
}

packages/node_modules/overmind-devtools/src/app/state.ts

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,12 @@
1-
import { Apps, Tab, App, Component, Flush, Action } from './types'
1+
import {
2+
Apps,
3+
Tab,
4+
App,
5+
Component,
6+
Flush,
7+
Action,
8+
GroupedComponents,
9+
} from './types'
210
import { Derive } from 'overmind'
311

412
export let isConnecting: boolean = true
@@ -69,3 +77,26 @@ export const currentAction: Derive<Action> = (state) =>
6977
state.currentApp.actions[state.currentApp.currentActionId]
7078

7179
export let expandAllActionDetails: boolean = false
80+
81+
export const expandedComponents: string[] = []
82+
83+
export const groupedComponents: Derive<GroupedComponents> = (state) => {
84+
const components = state.componentsMounted
85+
86+
return components.reduce(
87+
(aggr, component) => {
88+
if (aggr[component.name]) {
89+
aggr[component.name].components.push(component)
90+
} else {
91+
aggr[component.name] = {
92+
name: component.name,
93+
components: [component],
94+
isCollapsed: !state.expandedComponents.includes(component.name),
95+
}
96+
}
97+
98+
return aggr
99+
},
100+
{} as GroupedComponents
101+
)
102+
}

packages/node_modules/overmind-devtools/src/app/types.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,3 +141,13 @@ export enum Tab {
141141
Flushes = 'Flushes',
142142
Remove = 'Remove',
143143
}
144+
145+
export type GroupedComponent = {
146+
name: string
147+
components: Component[]
148+
isCollapsed: boolean
149+
}
150+
151+
export type GroupedComponents = {
152+
[name: string]: GroupedComponent
153+
}

packages/node_modules/overmind-devtools/src/components/ActionFlush/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ const ActionFlush: React.SFC<Props> = ({ flush, flushReference, app }) => {
2121
<Path />
2222
<Flush>
2323
<FlushHeader
24-
onClick={() => app.actions.toggleCollapsed(flushReference)}
24+
onClick={() => app.actions.toggleCollapsedActionItem(flushReference)}
2525
>
2626
<Text variant="hint">
2727
<Icon>code</Icon> {flush.components.length}

packages/node_modules/overmind-devtools/src/components/ActionOperator/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ const ActionOperator: React.SFC<Props> = ({
5454
borderColor={operator.type === 'mutate' ? 'red' : 'primary'}
5555
onClick={
5656
operator.mutations.length || operator.effects.length
57-
? () => app.actions.toggleCollapsed(operator)
57+
? () => app.actions.toggleCollapsedActionItem(operator)
5858
: null
5959
}
6060
>

packages/node_modules/overmind-devtools/src/components/Components/elements.tsx

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,30 @@ export const Panels = styled.div`
1717
export const Panel = styled.div`
1818
padding: ${({ theme }) => theme.padding.smaller};
1919
`
20+
21+
export const ComponentContainer = styled<
22+
{
23+
canExpand: boolean
24+
},
25+
'div'
26+
>('div')`
27+
position: relative;
28+
display: flex;
29+
align-items: center;
30+
cursor: pointer;
31+
padding: ${({ theme }) => `0 ${theme.padding.small}`};
32+
background-color: ${({ canExpand, theme }) =>
33+
canExpand ? theme.color.lighten(theme.color.white, -0.01) : 'transparent'};
34+
> div {
35+
flex: 1;
36+
}
37+
> p {
38+
position: absolute;
39+
top: ${({ theme }) => theme.padding.smaller};
40+
right: ${({ theme }) => theme.padding.small};
41+
}
42+
`
43+
44+
export const StatsContainer = styled.div`
45+
margin-bottom: ${({ theme }) => theme.padding.large};
46+
`

packages/node_modules/overmind-devtools/src/components/Components/index.tsx

Lines changed: 142 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -2,62 +2,149 @@ import * as React from 'react'
22
import { connect, Connect } from '../../app'
33
import Text from '../common/Text'
44
import Table, { Row, Cell } from '../common/Table'
5-
import { Wrapper, Panels, Panel } from './elements'
5+
import {
6+
Wrapper,
7+
Panels,
8+
Panel,
9+
ComponentContainer,
10+
StatsContainer,
11+
} from './elements'
12+
import { GroupedComponent } from '../../app/types'
13+
import Icon from '../common/Icon'
614

7-
const Components: React.SFC<Connect> = ({ app }) => (
8-
<Wrapper>
9-
<div>
10-
<Panels>
11-
<Panel>
12-
<Text variant="label" dense>
13-
connected
15+
class Components extends React.Component<Connect> {
16+
renderComponentsGroupExpanded(groupedComponent: GroupedComponent) {
17+
return groupedComponent.components.map((component) => {
18+
return (
19+
<Row key={component.id}>
20+
<Cell>{component.name}</Cell>
21+
<Cell>
22+
<Text variant="title" dense>
23+
{component.updateCount}
24+
</Text>
25+
</Cell>
26+
<Cell wordwrap="break-word" mono>
27+
{component.paths.join(', ')}
28+
</Cell>
29+
</Row>
30+
)
31+
})
32+
}
33+
renderComponentsGroupCollapsed(groupedComponent: GroupedComponent) {
34+
return (
35+
<Row key={groupedComponent.name}>
36+
<Cell>
37+
{groupedComponent.name} ({groupedComponent.components.length})
38+
</Cell>
39+
<Cell>
40+
<Text variant="title" dense>
41+
{groupedComponent.components.reduce(
42+
(aggr, component) => aggr + component.updateCount,
43+
0
44+
)}
1445
</Text>
15-
<Text variant="header" dense>
16-
{app.state.componentsMounted.length}
17-
</Text>
18-
</Panel>
19-
<Panel>
20-
<Text variant="label" dense>
21-
update count
22-
</Text>
23-
<Text variant="header" dense>
24-
{app.state.componentsUpdateCount}
25-
</Text>
26-
</Panel>
27-
<Panel>
28-
<Text variant="label" dense>
29-
paths watched
30-
</Text>
31-
<Text variant="header" dense>
32-
{app.state.componentsStatePathCount}
33-
</Text>
34-
</Panel>
35-
</Panels>
36-
</div>
37-
<Table
38-
headers={[
39-
{ title: 'name', width: '150px' },
40-
{ title: 'updates', width: '100px' },
41-
{ title: 'paths', width: 'calc(100% - 250px)' },
42-
]}
43-
>
44-
{app.state.componentsMounted.map((component) => {
45-
return (
46-
<Row key={component.id}>
47-
<Cell>{component.name}</Cell>
48-
<Cell>
49-
<Text variant="title" dense>
50-
{component.updateCount}
51-
</Text>
52-
</Cell>
53-
<Cell wordwrap="break-word" mono>
54-
{component.paths.join(', ')}
55-
</Cell>
56-
</Row>
57-
)
58-
})}
59-
</Table>
60-
</Wrapper>
61-
)
46+
</Cell>
47+
<Cell wordwrap="break-word" mono />
48+
</Row>
49+
)
50+
}
51+
renderStats() {
52+
const { app } = this.props
53+
54+
return (
55+
<StatsContainer>
56+
<Panels>
57+
<Panel>
58+
<Text variant="label" dense>
59+
connected
60+
</Text>
61+
<Text variant="header" dense>
62+
{app.state.componentsMounted.length}
63+
</Text>
64+
</Panel>
65+
<Panel>
66+
<Text variant="label" dense>
67+
update count
68+
</Text>
69+
<Text variant="header" dense>
70+
{app.state.componentsUpdateCount}
71+
</Text>
72+
</Panel>
73+
<Panel>
74+
<Text variant="label" dense>
75+
paths watched
76+
</Text>
77+
<Text variant="header" dense>
78+
{app.state.componentsStatePathCount}
79+
</Text>
80+
</Panel>
81+
</Panels>
82+
</StatsContainer>
83+
)
84+
}
85+
render() {
86+
const { app } = this.props
87+
88+
return (
89+
<Wrapper>
90+
{this.renderStats()}
91+
<Table
92+
headers={[
93+
{ title: 'name', width: '150px' },
94+
{ title: 'updates', width: '100px' },
95+
{ title: 'paths', width: 'calc(100% - 250px)' },
96+
]}
97+
>
98+
{Object.keys(app.state.groupedComponents).map((name) => {
99+
const groupedComponent = app.state.groupedComponents[name]
100+
const isGroup = groupedComponent.components.length > 1
101+
102+
return (
103+
<Row key={name}>
104+
<Cell colSpan={3}>
105+
<ComponentContainer
106+
canExpand={isGroup}
107+
onClick={
108+
isGroup
109+
? () => app.actions.toggleGroupedComponent(name)
110+
: null
111+
}
112+
>
113+
<div>
114+
<Table
115+
headers={[
116+
{ title: '', width: '150px' },
117+
{ title: '', width: '100px' },
118+
{ title: '', width: 'calc(100% - 250px)' },
119+
]}
120+
>
121+
{groupedComponent.isCollapsed && isGroup
122+
? this.renderComponentsGroupCollapsed(
123+
groupedComponent
124+
)
125+
: this.renderComponentsGroupExpanded(
126+
groupedComponent
127+
)}
128+
</Table>
129+
</div>
130+
{isGroup ? (
131+
<Text variant="hint">
132+
{groupedComponent.isCollapsed ? (
133+
<Icon>chevron-up</Icon>
134+
) : (
135+
<Icon>chevron-down</Icon>
136+
)}
137+
</Text>
138+
) : null}
139+
</ComponentContainer>
140+
</Cell>
141+
</Row>
142+
)
143+
})}
144+
</Table>
145+
</Wrapper>
146+
)
147+
}
148+
}
62149

63150
export default connect(Components)

packages/node_modules/overmind-devtools/src/components/common/Table/elements.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import styled from '../../../styled-components'
22

33
export const TableComponent = styled.table`
44
width: 100%;
5-
margin-top: ${({ theme }) => theme.padding.large};
65
table-layout: fixed;
76
border-collapse: collapse;
87
`
@@ -28,9 +27,12 @@ export const CellComponent = styled<
2827
{
2928
wordwrap?: string
3029
mono?: boolean
30+
colSpan?: number
3131
},
3232
'td'
33-
>('td')`
33+
>('td').attrs({
34+
colSpan: ({ colSpan }) => colSpan,
35+
})`
3436
font-family: ${({ mono }) => (mono ? 'monospace' : 'inherit')};
3537
word-wrap: ${({ wordwrap }) => wordwrap || 'normal'};
3638
`

0 commit comments

Comments
 (0)