EntityDetail.jsx 6.28 KB
Newer Older
Jaden's avatar
Jaden committed
1
// @flow
2
import * as React from 'react';
Jaden's avatar
Jaden committed
3
4
5
6
import {
	Container,
	Row,
	Col,
7
8
9
10
11
	TabContent,
	TabPane,
	Nav,
	NavItem,
	NavLink,
Jaden's avatar
Jaden committed
12
13
} from 'reactstrap';

14
15
16
17
import { connect } from 'react-redux';

import cn from 'classnames';

18
import * as Actions from '@store/actions.js';
19
import * as Selectors from '@store/selectors.js';
Jaden's avatar
Jaden committed
20
21
22
23
24
25

import {
	Route,
	Link
} from 'react-router-dom';

26
import type { BeatObject, BeatEntity } from '@helpers/beat';
27
import { getDefaultEntityObject } from '@helpers/beat';
28
import { genModuleApiFuncs } from '@helpers/api';
29
import ValidSchemaBadge from './ValidSchemaBadge.jsx';
30

31
32
33
34
35
36
import DataformatEditorContainer from './dataformat';
import AlgorithmEditorContainer from './algorithm';
import LibraryEditorContainer from './library';
import DatabaseEditorContainer from './database';
import ExperimentEditorContainer from './experiment';
import ToolchainEditorContainer from './toolchain';
Jaden DIEFENBAUGH's avatar
Jaden DIEFENBAUGH committed
37
import PlotterEditorContainer from './plotter';
38
import PlotterparameterEditorContainer from './plotterparameter';
39

Jaden's avatar
Jaden committed
40
type Props = {
Jaden DIEFENBAUGH's avatar
Jaden DIEFENBAUGH committed
41
42
	// the match object from react-router
	// used to find which object to render
43
	match: any,
Jaden DIEFENBAUGH's avatar
Jaden DIEFENBAUGH committed
44
45
	// the history object from react-router
	// used to push new history to
46
	history: any,
Jaden DIEFENBAUGH's avatar
Jaden DIEFENBAUGH committed
47
	// gets the object based on the current URL
48
	getEntityObject: () => BeatObject,
Jaden DIEFENBAUGH's avatar
Jaden DIEFENBAUGH committed
49
	// updates the current object
50
	updateFunc: (BeatObject) => any,
51
52
	// the current BEAT entity being show
	entity: BeatEntity,
Jaden's avatar
Jaden committed
53
54
};

Jaden DIEFENBAUGH's avatar
Jaden DIEFENBAUGH committed
55
// 3 tabs so far: editor, docs, raw json
56
type Tab = '0' | '1' | '2';
Jaden's avatar
Jaden committed
57

58
type State = {
Jaden DIEFENBAUGH's avatar
Jaden DIEFENBAUGH committed
59
	// which tab is active
60
61
	activeTab: Tab,
};
62

Jaden DIEFENBAUGH's avatar
Jaden DIEFENBAUGH committed
63
64
// wrapper for editors
// doesnt really do much now besides the raw json tab
65
export class EntityDetail extends React.Component<Props, State> {
66
67
	constructor(props: Props){
		super(props);
68
69
	}

70
71
72
	state = {
		activeTab: '0',
	}
73

74
75
76
77
78
79
	switchToTab = (tab: Tab) => {
		this.setState({
			activeTab: tab
		});
	}

80
81
	saveChanges = (newObj: BeatObject) => {
		this.props.updateFunc(newObj);
82
83
		const put = genModuleApiFuncs(this.props.entity).put;
		return put([newObj]);
84
85
	}

86
87
	render () {
		return (
88
89
			<Container>
				<Row>
Jaden DIEFENBAUGH's avatar
Jaden DIEFENBAUGH committed
90
					{/* title line (name & validation info) */}
91
92
93
					<Col>
						<h4 style={{'textAlign': 'center'}}>
							<span style={{'textTransform': 'capitalize'}}>
94
								{ this.props.entity }
95
96
97
98
99
							</span>
							{' '}
							<pre style={{display: 'inline'}}>
								{ this.props.getEntityObject().name }
							</pre>
100
							<ValidSchemaBadge entity={this.props.entity} obj={this.props.getEntityObject()} />
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
						</h4>
					</Col>
				</Row>
				<Row>
					<Col sm='12'>
						<Nav tabs className='nav-fill'>
							<NavItem>
								<NavLink
									className={cn({ active: this.state.activeTab === '0' })}
									onClick={() => this.switchToTab('0')}
								>
									Editor
								</NavLink>
							</NavItem>
							<NavItem>
								<NavLink
									className={cn({ active: this.state.activeTab === '1' })}
									onClick={() => this.switchToTab('1')}
								>
									Documentation
								</NavLink>
							</NavItem>
							<NavItem>
								<NavLink
									className={cn({ active: this.state.activeTab === '2' })}
									onClick={() => this.switchToTab('2')}
								>
									Raw JSON
								</NavLink>
							</NavItem>
						</Nav>
132
						<TabContent activeTab={this.state.activeTab} className='mt-2'>
Jaden DIEFENBAUGH's avatar
Jaden DIEFENBAUGH committed
133
							{/* Uses the appropriate editor, could probably be done nicer */}
134
135
							<TabPane tabId='0'>
								{
136
									this.props.entity === 'algorithm' &&
137
										<AlgorithmEditorContainer
138
139
140
141
142
											data={this.props.getEntityObject()}
											saveFunc={this.saveChanges}
										/>
								}
								{
143
									this.props.entity === 'dataformat' &&
144
										<DataformatEditorContainer
145
146
147
148
149
											data={this.props.getEntityObject()}
											saveFunc={this.saveChanges}
										/>
								}
								{
150
									this.props.entity === 'library' &&
151
										<LibraryEditorContainer
152
153
154
155
											data={this.props.getEntityObject()}
											saveFunc={this.saveChanges}
										/>
								}
Jaden DIEFENBAUGH's avatar
Jaden DIEFENBAUGH committed
156
								{
157
									this.props.entity === 'database' &&
158
										<DatabaseEditorContainer
Jaden DIEFENBAUGH's avatar
Jaden DIEFENBAUGH committed
159
160
161
162
											data={this.props.getEntityObject()}
											saveFunc={this.saveChanges}
										/>
								}
163
								{
164
									this.props.entity === 'experiment' &&
165
166
167
168
169
										<ExperimentEditorContainer
											data={this.props.getEntityObject()}
											saveFunc={this.saveChanges}
										/>
								}
170
								{
171
									this.props.entity === 'toolchain' &&
172
173
174
175
176
										<ToolchainEditorContainer
											data={this.props.getEntityObject()}
											saveFunc={this.saveChanges}
										/>
								}
Jaden DIEFENBAUGH's avatar
Jaden DIEFENBAUGH committed
177
								{
178
									this.props.entity === 'plotter' &&
Jaden DIEFENBAUGH's avatar
Jaden DIEFENBAUGH committed
179
180
181
182
183
										<PlotterEditorContainer
											data={this.props.getEntityObject()}
											saveFunc={this.saveChanges}
										/>
								}
184
								{
185
									this.props.entity === 'plotterparameter' &&
186
187
188
189
190
										<PlotterparameterEditorContainer
											data={this.props.getEntityObject()}
											saveFunc={this.saveChanges}
										/>
								}
191
192
							</TabPane>
							<TabPane tabId='1'>
193
194
								<Row>
									<Col>
195
										<h4 style={{textAlign: 'center'}}>Under construction 😄</h4>
196
197
									</Col>
								</Row>
198
199
200
201
202
203
204
205
							</TabPane>
							<TabPane tabId='2'>
								<pre>{ JSON.stringify(this.props.getEntityObject(), null, 4) }</pre>
							</TabPane>
						</TabContent>
					</Col>
				</Row>
			</Container>
206
207
208
209
		);
	}
}

210
const mapStateToProps = (state, ownProps) => {
Jaden DIEFENBAUGH's avatar
Jaden DIEFENBAUGH committed
211
	// which beat entity is currently active: 'algorithm', 'plotter', 'database', etc.
212
	const entity = ownProps.match.params.entity;
Jaden DIEFENBAUGH's avatar
Jaden DIEFENBAUGH committed
213
	// the name of the object ("atnt/1", "plot/isoroc/1", "user/tc/test/1/exp", etc.)
214
215
	const name = ownProps.match.params.name;
	const obj = {
Jaden DIEFENBAUGH's avatar
Jaden DIEFENBAUGH committed
216
217
		// uses a selector based off the entity and finds the obj given the name
		// if the obj doesnt exist (huge edge case) just return a default obj to not break everything
218
		getEntityObject: (): BeatObject => Selectors[`${ entity }Get`](state).find(o => o.name === name) || getDefaultEntityObject(),
219
		entity,
220
221
222
223
224
	};

	return obj;
};

225
const mapDispatchToProps = (dispatch, ownProps) => ({
Jaden DIEFENBAUGH's avatar
Jaden DIEFENBAUGH committed
226
	// replace the obj in the Redux store with the new object
227
228
229
230
231
232
	updateFunc: (obj) => {
		dispatch(Actions[`${ ownProps.match.params.entity }Update`](ownProps.match.params.name, obj));
		ownProps.history.push(`/${ ownProps.match.params.entity }/${ obj.name }`);
	},
});

233
export default connect(mapStateToProps, mapDispatchToProps)(EntityDetail);