Skip to content

Commit da4053f

Browse files
authored
COMPASS-203: Create Collection (#555)
* COMPASS-203: Add create collection * COMPASS-203: Add databaseName as property * COMPASS-203: Refactor common code into database package * COMPASS-203: Fix instance refresh with a namespace * COMPASS-203: Fixing eslint errors
1 parent 40e4f1d commit da4053f

File tree

16 files changed

+344
-64
lines changed

16 files changed

+344
-64
lines changed

src/app/home/index.js

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -151,12 +151,6 @@ var HomeView = View.extend({
151151
'server memory size (gb)': app.instance.host.memory_bits / 1024 / 1024 / 1024
152152
});
153153

154-
const model = this._getCollection();
155-
// When the current collection no longer exists
156-
if (NamespaceStore.ns && !model) {
157-
NamespaceStore.ns = null;
158-
}
159-
160154
if (!NamespaceStore.ns) {
161155
app.instance.collections.unselectAll();
162156
if (app.instance.collections.length === 0) {

src/internal-packages/database/index.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,27 @@
11
const app = require('ampersand-app');
22
const CollectionsTable = require('./lib/components');
3+
const CreateCollectionCheckbox = require('./lib/components/create-collection-checkbox');
4+
const CreateCollectionInput = require('./lib/components/create-collection-input');
5+
const CreateCollectionSizeInput = require('./lib/components/create-collection-size-input');
36

47
/**
58
* Activate all the components in the Schema package.
69
*/
710
function activate() {
811
app.appRegistry.registerComponent('Database.CollectionsTable', CollectionsTable);
12+
app.appRegistry.registerComponent('Database.CreateCollectionCheckbox', CreateCollectionCheckbox);
13+
app.appRegistry.registerComponent('Database.CreateCollectionInput', CreateCollectionInput);
14+
app.appRegistry.registerComponent('Database.CreateCollectionSizeInput', CreateCollectionSizeInput);
915
}
1016

1117
/**
1218
* Deactivate all the components in the Schema package.
1319
*/
1420
function deactivate() {
1521
app.appRegistry.deregisterComponent('Database.CollectionsTable');
22+
app.appRegistry.deregisterComponent('Database.CreateCollectionCheckbox');
23+
app.appRegistry.deregisterComponent('Database.CreateCollectionInput');
24+
app.appRegistry.deregisterComponent('Database.CreateCollectionSizeInput');
1625
}
1726

1827
module.exports.activate = activate;
Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
const Reflux = require('reflux');
22

33
/**
4-
* The actions used by the server stats components.
4+
* The actions used by the database components.
55
*/
66
const Actions = Reflux.createActions([
77
'sortCollections',
8-
'deleteCollection',
9-
'createCollection'
8+
'dropCollection',
9+
'createCollection',
10+
'openCreateCollectionDialog',
11+
'openDropCollectionDialog'
1012
]);
1113

1214
module.exports = Actions;

src/internal-packages/database/lib/components/collections-table.jsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
const React = require('react');
22
const app = require('ampersand-app');
33
const CollectionsActions = require('../actions/collections-actions');
4+
const CreateCollectionDialog = require('./create-collection-dialog');
5+
const TextButton = require('hadron-app-registry').TextButton;
46
const numeral = require('numeral');
57

68
const _ = require('lodash');
@@ -22,6 +24,10 @@ class CollectionsTable extends React.Component {
2224
// CollectionsActions.deleteCollection(collName);
2325
}
2426

27+
onCreateCollectionButtonClicked() {
28+
CollectionsActions.openCreateCollectionDialog();
29+
}
30+
2531
render() {
2632
// convert some of the values to human-readable units (MB, GB, ...)
2733
// we do this here so that sorting is not affected in the store
@@ -45,6 +51,12 @@ class CollectionsTable extends React.Component {
4551

4652
return (
4753
<div className="collections-table">
54+
<div className="collections-table-create-button">
55+
<TextButton
56+
text="Create Collection"
57+
className="btn btn-default btn-sm"
58+
clickHandler={this.onCreateCollectionButtonClicked.bind(this)} />
59+
</div>
4860
<this.SortableTable
4961
theme="light"
5062
columns={this.props.columns}
@@ -56,6 +68,7 @@ class CollectionsTable extends React.Component {
5668
onColumnHeaderClicked={this.onColumnHeaderClicked.bind(this)}
5769
onRowDeleteButtonClicked={this.onRowDeleteButtonClicked.bind(this)}
5870
/>
71+
<CreateCollectionDialog />
5972
</div>
6073
);
6174
}

src/internal-packages/server-stats/lib/component/create-collection-checkbox.jsx renamed to src/internal-packages/database/lib/components/create-collection-checkbox.jsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
const React = require('react');
22

3+
/**
4+
* A checkbox in the create collection dialog.
5+
*/
36
class CreateCollectionCheckbox extends React.Component {
47

58
/**
Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
const app = require('ampersand-app');
2+
const shell = require('electron').shell;
3+
const React = require('react');
4+
const Modal = require('react-bootstrap').Modal;
5+
const TextButton = require('hadron-app-registry').TextButton;
6+
const NamespaceStore = require('hadron-reflux-store').NamespaceStore;
7+
const toNS = require('mongodb-ns');
8+
const Actions = require('../actions/collections-actions');
9+
const CreateCollectionStore = require('../stores/create-collection-store');
10+
const CreateCollectionInput = require('./create-collection-input');
11+
const CreateCollectionSizeInput = require('./create-collection-size-input');
12+
const CreateCollectionCheckbox = require('./create-collection-checkbox');
13+
14+
/**
15+
* The help icon for capped collections url.
16+
*/
17+
const HELP_URL = 'https://docs.mongodb.com/manual/core/capped-collections/';
18+
19+
/**
20+
* The dialog to create a collection.
21+
*/
22+
class CreateCollectionDialog extends React.Component {
23+
24+
/**
25+
* The component constructor.
26+
*
27+
* @param {Object} props - The properties.
28+
*/
29+
constructor(props) {
30+
super(props);
31+
this.state = { open: false };
32+
this.ModalStatusMessage = app.appRegistry.getComponent('App.ModalStatusMessage');
33+
}
34+
35+
/**
36+
* Subscribe to the open dialog store.
37+
*/
38+
componentWillMount() {
39+
this.unsubscribeOpen = Actions.openCreateCollectionDialog.listen(this.onOpenDialog.bind(this));
40+
this.unsubscribeCreate = CreateCollectionStore.listen(this.onCollectionCreated.bind(this));
41+
}
42+
43+
/**
44+
* Unsubscribe from the store.
45+
*/
46+
componentWillUnmount() {
47+
this.unsubscribeOpen();
48+
this.unsubscribeCreate();
49+
}
50+
51+
/**
52+
* When the open dialog action is fired.
53+
*/
54+
onOpenDialog() {
55+
this.setState({
56+
open: true,
57+
collectionName: '',
58+
databaseName: toNS(NamespaceStore.ns).database,
59+
capped: false,
60+
maxSize: '',
61+
error: false,
62+
inProgress: false,
63+
errorMessage: ''
64+
});
65+
}
66+
67+
/**
68+
* When the cancel button is clicked.
69+
*/
70+
onCancelButtonClicked() {
71+
this.setState({ open: false });
72+
}
73+
74+
/**
75+
* Initiate the attempt to create a collection.
76+
*/
77+
onCreateCollectionButtonClicked() {
78+
this.setState({ inProgress: true, error: false, errorMessage: '' });
79+
Actions.createCollection(
80+
this.state.databaseName,
81+
this.state.collectionName,
82+
this.state.capped,
83+
this.state.maxSize
84+
);
85+
}
86+
87+
/**
88+
* Handle finish collection creation.
89+
*
90+
* @param {Error} error - The error, if any.
91+
*/
92+
onCollectionCreated(error) {
93+
if (error) {
94+
this.setState({ inProgress: false, error: true, errorMessage: error.message });
95+
} else {
96+
this.setState({ inProgress: false, error: false, errorMessage: '', open: false });
97+
}
98+
}
99+
100+
/**
101+
* Handle changing the collection name.
102+
*
103+
* @param {Event} evt - The change event.
104+
*/
105+
onCollectionNameChange(evt) {
106+
this.setState({ collectionName: evt.target.value });
107+
}
108+
109+
/**
110+
* Handle clicking the capped checkbox.
111+
*/
112+
onCappedClicked() {
113+
this.setState({ capped: !this.state.capped });
114+
}
115+
116+
/**
117+
* Handle clicking the help icon.
118+
119+
* @param {Event} evt - The event.
120+
*/
121+
onHelpClicked(evt) {
122+
evt.preventDefault();
123+
evt.stopPropagation();
124+
shell.openExternal(HELP_URL);
125+
}
126+
127+
/**
128+
* Change the max collection size.
129+
*
130+
* @param {Event} evt - The event.
131+
*/
132+
onMaxSizeChange(evt) {
133+
this.setState({ maxSize: evt.target.value });
134+
}
135+
136+
/**
137+
* Render the max size component when capped is selected.
138+
*
139+
* @returns {React.Component} The component.
140+
*/
141+
renderMaxSize() {
142+
if (this.state.capped) {
143+
return (
144+
<CreateCollectionSizeInput
145+
name="bytes max"
146+
placeholder="Enter max bytes"
147+
value={this.state.maxSize}
148+
onChangeHandler={this.onMaxSizeChange.bind(this)} />
149+
);
150+
}
151+
}
152+
153+
/**
154+
* Render the modal dialog.
155+
*
156+
* @returns {React.Component} The react component.
157+
*/
158+
render() {
159+
return (
160+
<Modal show={this.state.open} backdrop="static" keyboard={false} dialogClassName="create-collection-dialog">
161+
<Modal.Header>
162+
<Modal.Title>Create Collection</Modal.Title>
163+
</Modal.Header>
164+
165+
<Modal.Body>
166+
<form name="create-collection-dialog-form">
167+
<CreateCollectionInput
168+
name="Collection Name"
169+
value={this.state.collectionName}
170+
onChangeHandler={this.onCollectionNameChange.bind(this)} />
171+
<CreateCollectionCheckbox
172+
name="Capped Collection"
173+
className="create-collection-dialog-capped"
174+
checked={this.state.checked}
175+
onClickHandler={this.onCappedClicked.bind(this)}
176+
onHelpClickHandler={this.onHelpClicked.bind(this)} />
177+
{this.renderMaxSize()}
178+
{this.state.error ?
179+
<this.ModalStatusMessage icon="times" message={this.state.errorMessage} type="error" />
180+
: null}
181+
{this.state.inProgress ?
182+
<this.ModalStatusMessage icon="align-center" message={'Create in Progress'} type="in-progress" />
183+
: null}
184+
</form>
185+
</Modal.Body>
186+
187+
<Modal.Footer>
188+
<TextButton
189+
className="btn btn-default"
190+
text="Cancel"
191+
clickHandler={this.onCancelButtonClicked.bind(this)} />
192+
<TextButton
193+
className="btn btn-primary"
194+
text="Create Collection"
195+
clickHandler={this.onCreateCollectionButtonClicked.bind(this)} />
196+
</Modal.Footer>
197+
</Modal>
198+
);
199+
}
200+
}
201+
202+
CreateCollectionDialog.displayName = 'CreateCollectionDialog';
203+
204+
module.exports = CreateCollectionDialog;

src/internal-packages/server-stats/lib/component/create-collection-input.jsx renamed to src/internal-packages/database/lib/components/create-collection-input.jsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
const React = require('react');
22

3+
/**
4+
* An input field in the create collection checkbox.
5+
*/
36
class CreateCollectionInput extends React.Component {
47

58
/**

src/internal-packages/server-stats/lib/component/create-collection-size-input.jsx renamed to src/internal-packages/database/lib/components/create-collection-size-input.jsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
const React = require('react');
22

3+
/**
4+
* A size input field in the create collection checkbox.
5+
*/
36
class CreateCollectionSizeInput extends React.Component {
47

58
/**
@@ -12,11 +15,11 @@ class CreateCollectionSizeInput extends React.Component {
1215
<div className="form-group">
1316
<input
1417
type="text"
15-
className="form-control create-database-dialog-size-input"
18+
className="form-control create-collection-dialog-size-input"
1619
onChange={this.props.onChangeHandler}
1720
value={this.props.value}
1821
placeholder={this.props.placeholder} />
19-
<p className="create-database-dialog-size-field">{this.props.name}</p>
22+
<p className="create-collection-dialog-size-field">{this.props.name}</p>
2023
</div>
2124
);
2225
}

0 commit comments

Comments
 (0)