diff --git a/package.json b/package.json
index f3833958604..3b84286189f 100644
--- a/package.json
+++ b/package.json
@@ -40,6 +40,7 @@
"node_modules/@mongodb-js/compass-document-validation",
"node_modules/@mongodb-js/compass-deployment-awareness",
"node_modules/@mongodb-js/compass-charts",
+ "node_modules/@mongodb-js/compass-crud",
"node_modules/@mongodb-js/compass-query-history"
],
"styles": [
@@ -54,21 +55,9 @@
"node_modules/@mongodb-js/compass-serverstats",
"node_modules/@mongodb-js/compass-document-validation",
"node_modules/@mongodb-js/compass-deployment-awareness",
- "node_modules/@mongodb-js/compass-charts"
- ],
- "styles": [
- "index"
- ]
- },
- "compass-charts": {
- "name": "mongodb-compass-charts",
- "productName": "MongoDB Compass Visualisations",
- "plugins-directory": ".mongodb/compass-charts/plugins",
- "packages": [
- "node_modules/@mongodb-js/compass-serverstats",
- "node_modules/@mongodb-js/compass-document-validation",
- "node_modules/@mongodb-js/compass-deployment-awareness",
- "node_modules/@mongodb-js/compass-charts"
+ "node_modules/@mongodb-js/compass-charts",
+ "node_modules/@mongodb-js/compass-crud",
+ "node_modules/@mongodb-js/compass-query-history"
],
"styles": [
"index"
@@ -142,6 +131,7 @@
},
"dependencies": {
"@mongodb-js/compass-charts": "^0.2.3",
+ "@mongodb-js/compass-crud": "0.0.3",
"@mongodb-js/compass-deployment-awareness": "3.2.0",
"@mongodb-js/compass-document-validation": "4.1.0",
"@mongodb-js/compass-serverstats": "9.1.1",
diff --git a/src/app/index.less b/src/app/index.less
index c8953b04254..b888049a7d5 100644
--- a/src/app/index.less
+++ b/src/app/index.less
@@ -17,7 +17,6 @@
@import "../internal-packages/app/styles/index.less";
@import "../internal-packages/collection/styles/index.less";
@import "../internal-packages/collection-stats/styles/index.less";
-@import "../internal-packages/crud/styles/index.less";
@import "../internal-packages/database-ddl/styles/index.less";
@import "../internal-packages/home/styles/index.less";
@import "../internal-packages/status/styles/index.less";
diff --git a/src/internal-packages/crud/README.md b/src/internal-packages/crud/README.md
deleted file mode 100644
index 3a1c06ed00d..00000000000
--- a/src/internal-packages/crud/README.md
+++ /dev/null
@@ -1,85 +0,0 @@
-# Compass CRUD Package
-
-Provide functionality shown in the "Documents" tab in the collection view.
-
-## Available Resources in the App Registry
-
-### Components
-
-#### Definitions
-
-| Key | Description |
-|---------------------|------------------------------|
-| `CRUD.Document` | Renders a single document. |
-| `CRUD.DocumentList` | Renders a list of documents. |
-
-### Actions
-
-| Key | Description |
-|----------------|-------------------------------|
-| `CRUD.Actions` | All the CRUD related actions. |
-
-### Stores
-
-| Key | Description
-|-------------------------------|---------------------------------------------------------|
-| `CRUD.InsertDocumentStore` | Triggers when a document is inserted. |
-| `CRUD.ResetDocumentListStore` | Triggers when the query filter is reset. |
-| `CRUD.LoadMoreDocumentsStore` | Triggers when more documents are fetched via scrolling. |
-
-## Usage
-
-Render an editable document in a React component.
-
-```jsx
-const app = require('hadron-app');
-const React = require('react');
-
-class MyComponent extends React.Component {
- constructor(props) {
- super(props);
- this.Document = app.appRegistry.getRole('CRUD.Document')[0].component;
- }
- render() {
- return ();
- }
-}
-```
-
-Render a non-editable pre-expanded document in a React component.
-
-```jsx
-const app = require('hadron-app');
-const React = require('react');
-
-class MyComponent extends React.Component {
- constructor(props) {
- super(props);
- this.Document = app.appRegistry.getRole('CRUD.Document')[0].component;
- }
- render() {
- return ();
- }
-}
-```
-
-Listen to the various CRUD actions.
-
-```javascript
-const app = require('hadron-app');
-const CrudActions = app.appRegistry.getAction('CRUD.Actions');
-
-CrudActions.documentRemoved.listen((id) => {
- console.log(`Document with _id ${id} removed.`);
-});
-
-CrudActions.openInsertDocumentDialog((doc, clone) => {
- if (clone) {
- console.log('Opening insert dialog with cloned document');
- }
-});
-
-CrudActions.insertDocument((doc) => {
- console.log('Inserting document into db');
-});
-```
diff --git a/src/internal-packages/crud/index.js b/src/internal-packages/crud/index.js
deleted file mode 100644
index 5faac8060c8..00000000000
--- a/src/internal-packages/crud/index.js
+++ /dev/null
@@ -1,105 +0,0 @@
-const app = require('hadron-app');
-const Document = require('./lib/component/document');
-const DocumentList = require('./lib/component/document-list');
-const Actions = require('./lib/actions');
-const InsertDocumentStore = require('./lib/store/insert-document-store');
-const ResetDocumentListStore = require('./lib/store/reset-document-list-store');
-const LoadMoreDocumentsStore = require('./lib/store/load-more-documents-store');
-const {
- StandardEditor,
- DateEditor,
- StringEditor,
- Int32Editor,
- DoubleEditor,
- NullEditor,
- UndefinedEditor,
- ObjectIDEditor
-} = require('./lib/component/editor');
-
-const COLLECTION_TAB_ROLE = {
- component: DocumentList,
- name: 'DOCUMENTS',
- hasQueryHistory: true,
- order: 1
-};
-
-const DOCUMENT_ROLE = {
- component: Document,
- name: 'STANDARD',
- order: 1
-};
-
-const STANDARD_EDITOR_ROLE = {
- component: StandardEditor
-};
-
-const DATE_EDITOR_ROLE = {
- component: DateEditor
-};
-
-const DOUBLE_EDITOR_ROLE = {
- component: DoubleEditor
-};
-
-const STRING_EDITOR_ROLE = {
- component: StringEditor
-};
-
-const INT32_EDITOR_ROLE = {
- component: Int32Editor
-};
-
-const NULL_EDITOR_ROLE = {
- component: NullEditor
-};
-
-const UNDEFINED_EDITOR_ROLE = {
- component: UndefinedEditor
-};
-
-const OBJECT_ID_EDITOR_ROLE = {
- component: ObjectIDEditor
-};
-
-/**
- * Activate all the components in the CRUD package.
- */
-function activate(appRegistry) {
- appRegistry.registerRole('Collection.Tab', COLLECTION_TAB_ROLE);
- appRegistry.registerRole('CRUD.Document', DOCUMENT_ROLE);
- appRegistry.registerRole('CRUD.Editor.Standard', STANDARD_EDITOR_ROLE);
- appRegistry.registerRole('CRUD.Editor.Date', DATE_EDITOR_ROLE);
- appRegistry.registerRole('CRUD.Editor.Double', DOUBLE_EDITOR_ROLE);
- appRegistry.registerRole('CRUD.Editor.String', STRING_EDITOR_ROLE);
- appRegistry.registerRole('CRUD.Editor.Int32', INT32_EDITOR_ROLE);
- appRegistry.registerRole('CRUD.Editor.Null', NULL_EDITOR_ROLE);
- appRegistry.registerRole('CRUD.Editor.Undefined', UNDEFINED_EDITOR_ROLE);
- appRegistry.registerRole('CRUD.Editor.ObjectID', OBJECT_ID_EDITOR_ROLE);
- appRegistry.registerAction('CRUD.Actions', Actions);
- appRegistry.registerStore('CRUD.InsertDocumentStore', InsertDocumentStore);
- appRegistry.registerStore('CRUD.ResetDocumentListStore', ResetDocumentListStore);
- appRegistry.registerStore('CRUD.LoadMoreDocumentsStore', LoadMoreDocumentsStore);
-}
-
-/**
- * Deactivate all the components in the CRUD package.
- */
-function deactivate() {
- app.appRegistry.deregisterRole('Collection.Tab', COLLECTION_TAB_ROLE);
- app.appRegistry.deregisterRole('CRUD.Document', DOCUMENT_ROLE);
- app.appRegistry.deregisterRole('CRUD.Editor.Standard', STANDARD_EDITOR_ROLE);
- app.appRegistry.deregisterRole('CRUD.Editor.Date', DATE_EDITOR_ROLE);
- app.appRegistry.deregisterRole('CRUD.Editor.Double', DOUBLE_EDITOR_ROLE);
- app.appRegistry.deregisterRole('CRUD.Editor.String', STRING_EDITOR_ROLE);
- app.appRegistry.deregisterRole('CRUD.Editor.Int32', INT32_EDITOR_ROLE);
- app.appRegistry.deregisterRole('CRUD.Editor.Null', NULL_EDITOR_ROLE);
- app.appRegistry.deregisterRole('CRUD.Editor.Undefined', UNDEFINED_EDITOR_ROLE);
- app.appRegistry.deregisterRole('CRUD.Editor.ObjectID', OBJECT_ID_EDITOR_ROLE);
- app.appRegistry.deregisterAction('CRUD.Actions');
- app.appRegistry.deregisterStore('CRUD.InsertDocumentStore');
- app.appRegistry.deregisterStore('CRUD.ResetDocumentListStore');
- app.appRegistry.deregisterStore('CRUD.LoadMoreDocumentsStore');
-}
-
-module.exports.activate = activate;
-module.exports.deactivate = deactivate;
diff --git a/src/internal-packages/crud/lib/actions.js b/src/internal-packages/crud/lib/actions.js
deleted file mode 100644
index c2e80b5aede..00000000000
--- a/src/internal-packages/crud/lib/actions.js
+++ /dev/null
@@ -1,40 +0,0 @@
-const fs = require('fs');
-const Reflux = require('reflux');
-const debug = require('debug')('mongodb-compass:crud:actions');
-
-const Actions = Reflux.createActions([
- 'documentRemoved',
- 'openInsertDocumentDialog',
- 'closeInsertDocumentDialog',
- 'insertDocument',
- 'fileDropped',
- 'refreshDocuments',
- 'closeAllMenus',
- 'fetchNextDocuments',
- 'elementInvalid',
- 'elementValid'
-]);
-
-document.ondragover = document.ondrop = (ev) => {
- ev.preventDefault();
-};
-
-document.body.ondrop = (ev) => {
- ev.preventDefault();
- const file = ev.dataTransfer.files[0];
- if (file) {
- const path = file.path;
- fs.readFile(path, 'utf-8', (error, data) => {
- if (error) {
- debug(`Error opening file '${path}': ${error.message}`);
- }
- try {
- Actions.openInsertDocumentDialog(JSON.parse(data), false);
- } catch (e) {
- debug(`File ${path} is not a single parseable JSON document: ${e.message}`);
- }
- });
- }
-};
-
-module.exports = Actions;
diff --git a/src/internal-packages/crud/lib/component/document-actions.jsx b/src/internal-packages/crud/lib/component/document-actions.jsx
deleted file mode 100644
index f3a1432db53..00000000000
--- a/src/internal-packages/crud/lib/component/document-actions.jsx
+++ /dev/null
@@ -1,110 +0,0 @@
-const React = require('react');
-const PropTypes = require('prop-types');
-const { IconButton } = require('hadron-react-buttons');
-
-/**
- * Override once the button to be able to update.
- */
-class UpdatableIconButton extends IconButton {
-
- /**
- * By default should always need to to re-render itself.
- *
- * @returns {Boolean} Always true.
- */
- shouldComponentUpdate() {
- return true;
- }
-}
-
-/**
- * Component for actions on the document.
- */
-class DocumentActions extends React.Component {
-
- /**
- * Instantiate the actions.
- *
- * @param {Object} props - The properties.
- */
- constructor(props) {
- super(props);
- this.state = { allExpanded: props.allExpanded };
- }
-
- /**
- * Set the state when new props are received.
- *
- * @param {Object} nextProps - The new props.
- */
- componentWillReceiveProps(nextProps) {
- if (nextProps.allExpanded !== this.state.allExpanded) {
- this.setState({ allExpanded: nextProps.allExpanded });
- }
- }
-
- /**
- * Render the expand all button.
- *
- * @returns {React.Component} The expand all button.
- */
- renderExpandAll() {
- const title = this.state.allExpanded ? 'Collapse All' : 'Expand All';
- const iconClass = this.state.allExpanded ? 'fa-angle-down' : 'fa-angle-right';
- return (
-
- );
- }
-
- /**
- * Render the actions.
- *
- * @returns {Component} The actions component.
- */
- render() {
- return (
-
-
- {this.renderExpandAll()}
-
-
-
-
-
-
-
- );
- }
-}
-
-DocumentActions.displayName = 'DocumentActions';
-
-DocumentActions.propTypes = {
- edit: PropTypes.func.isRequired,
- remove: PropTypes.func.isRequired,
- clone: PropTypes.func.isRequired,
- allExpanded: PropTypes.bool.isRequired,
- expandAll: PropTypes.func.isRequired
-};
-
-module.exports = DocumentActions;
diff --git a/src/internal-packages/crud/lib/component/document-footer.jsx b/src/internal-packages/crud/lib/component/document-footer.jsx
deleted file mode 100644
index 716959eb5dc..00000000000
--- a/src/internal-packages/crud/lib/component/document-footer.jsx
+++ /dev/null
@@ -1,246 +0,0 @@
-const _ = require('lodash');
-const React = require('react');
-const PropTypes = require('prop-types');
-const { Element } = require('hadron-document');
-const { TextButton } = require('hadron-react-buttons');
-
-/**
- * The progress mode.
- */
-const PROGRESS = 'Progress';
-
-/**
- * The success mode.
- */
-const SUCCESS = 'Success';
-
-/**
- * The error mode.
- */
-const ERROR = 'Error';
-
-/**
- * The editing mode.
- */
-const EDITING = 'Editing';
-
-/**
- * The viewing mode.
- */
-const VIEWING = 'Viewing';
-
-/**
- * The invalid message.
- */
-const INVALID_MESSAGE = 'Update not permitted while document contains errors.';
-
-/**
- * Map of modes to styles.
- */
-const MODES = {
- 'Progress': 'is-in-progress',
- 'Success': 'is-success',
- 'Error': 'is-error',
- 'Editing': 'is-modified',
- 'Viewing': 'is-viewing'
-};
-
-/**
- * The empty message.
- */
-const EMPTY = '';
-
-/**
- * The modified message.
- */
-const MODIFIED = 'Document Modified.';
-
-/**
- * The updating message.
- */
-const UPDATING = 'Updating Document.';
-
-/**
- * The updated message.
- */
-const UPDATED = 'Document Updated.';
-
-/**
- * Component for a the edit document footer.
- */
-class DocumentFooter extends React.Component {
-
- /**
- * The component constructor.
- *
- * @param {Object} props - The properties.
- */
- constructor(props) {
- super(props);
- this.doc = props.doc;
- this.updateStore = props.updateStore;
- this.actions = props.actions;
- this.state = { mode: VIEWING, message: EMPTY };
- this.invalidElements = [];
- }
-
- /**
- * Subscribe to the update store on mount.
- */
- componentDidMount() {
- this.unsubscribeUpdate = this.updateStore.listen(this.handleStoreUpdate.bind(this));
-
- this.unsubscribeAdded = this.handleModification.bind(this);
- this.unsubscribeEdited = this.handleModification.bind(this);
- this.unsubscribeRemoved = this.handleModification.bind(this);
- this.unsubscribeReverted = this.handleModification.bind(this);
- this.unsubscribeInvalid = this.handleInvalid.bind(this);
- this.unsubscribeValid = this.handleValid.bind(this);
-
- this.doc.on(Element.Events.Added, this.unsubscribeAdded);
- this.doc.on(Element.Events.Edited, this.unsubscribeEdited);
- this.doc.on(Element.Events.Removed, this.unsubscribeRemoved);
- this.doc.on(Element.Events.Reverted, this.unsubscribeReverted);
- this.doc.on(Element.Events.Invalid, this.unsubscribeInvalid);
- this.doc.on(Element.Events.Valid, this.unsubscribeValid);
- }
-
- /**
- * Unsubscribe from the udpate store on unmount.
- */
- componentWillUnmount() {
- this.unsubscribeUpdate();
- this.doc.removeListener(Element.Events.Added, this.unsubscribeAdded);
- this.doc.removeListener(Element.Events.Edited, this.unsubscribeEdited);
- this.doc.removeListener(Element.Events.Removed, this.unsubscribeRemoved);
- this.doc.removeListener(Element.Events.Reverted, this.unsubscribeReverted);
- this.doc.removeListener(Element.Events.Invalid, this.unsubscribeInvalid);
- this.doc.removeListener(Element.Events.Valid, this.unsubscribeValid);
- }
-
- /**
- * Handle the user clicking the cancel button.
- */
- handleCancel() {
- this.doc.cancel();
- this.setState({ mode: VIEWING, message: EMPTY });
- }
-
- /**
- * Handle an error with the document update.
- *
- * @param {Error} error - The error.
- */
- handleError(error) {
- this.setState({ mode: ERROR, message: error.message });
- }
-
- handleValid(uuid) {
- _.pull(this.invalidElements, uuid);
- }
-
- handleInvalid(uuid) {
- if (!_.includes(this.invalidElements, uuid)) {
- this.invalidElements.push(uuid);
- this.handleModification();
- }
- }
-
- /**
- * Handle modification to the document.
- */
- handleModification() {
- const isModified = this.doc.isModified();
- if (this.hasErrors()) {
- this.setState({ mode: ERROR, message: INVALID_MESSAGE });
- } else {
- this.setState({
- mode: isModified ? EDITING : VIEWING,
- message: isModified ? MODIFIED : EMPTY
- });
- }
- }
-
- /**
- * Handle the user clicking the update button.
- */
- handleUpdate() {
- const object = this.props.doc.generateObject();
- this.setState({ mode: PROGRESS, message: UPDATING });
- this.actions.update(object);
- }
-
- /**
- * Handle a successful document update.
- */
- handleSuccess() {
- this.setState({ mode: SUCCESS, message: UPDATED });
- }
-
- /**
- * Handles a trigger from the store.
- *
- * @param {Boolean} success - If the update succeeded.
- * @param {Object} object - The error or document.
- */
- handleStoreUpdate(success, object) {
- if (success) {
- this.handleSuccess();
- } else {
- this.handleError(object);
- }
- }
-
- hasErrors() {
- return this.invalidElements.length > 0;
- }
-
- /**
- * Get the style of the footer based on the current mode.
- *
- * @returns {String} The style.
- */
- style() {
- return `document-footer document-footer-${MODES[this.state.mode]}`;
- }
-
- /**
- * Render the footer.
- *
- * @returns {Component} The footer component.
- */
- render() {
- return (
-
-
- {this.state.message}
-
-
-
-
-
-
- );
- }
-}
-
-DocumentFooter.displayName = 'DocumentFooter';
-
-DocumentFooter.propTypes = {
- doc: PropTypes.object.isRequired,
- actions: PropTypes.object.isRequired,
- updateStore: PropTypes.object.isRequired
-};
-
-module.exports = DocumentFooter;
diff --git a/src/internal-packages/crud/lib/component/document-list.jsx b/src/internal-packages/crud/lib/component/document-list.jsx
deleted file mode 100644
index 3422aebac45..00000000000
--- a/src/internal-packages/crud/lib/component/document-list.jsx
+++ /dev/null
@@ -1,296 +0,0 @@
-const _ = require('lodash');
-const React = require('react');
-const uuid = require('uuid');
-const ObjectID = require('bson').ObjectID;
-const Action = require('../actions');
-const { StatusRow } = require('hadron-react-components');
-const ResetDocumentListStore = require('../store/reset-document-list-store');
-const LoadMoreDocumentsStore = require('../store/load-more-documents-store');
-const RemoveDocumentStore = require('../store/remove-document-store');
-const InsertDocumentStore = require('../store/insert-document-store');
-const InsertDocumentDialog = require('./insert-document-dialog');
-const Actions = require('../actions');
-
-const debug = require('debug')('mongodb-compass:crud:component');
-
-/* eslint no-return-assign:0 */
-
-/**
- * The full document list container class.
- */
-const LIST_CLASS = 'document-list';
-
-/**
- * The scroll event name.
- */
-const SCROLL_EVENT = 'scroll';
-
-/**
- * The loading more class.
- */
-const LOADING = 'loading-indicator';
-
-/**
- * Loading indicator is loading.
- */
-const IS_LOADING = `${LOADING}-is-loading`;
-
-/**
- * The list item test id.
- */
-const LIST_ITEM_TEST_ID = 'document-list-item';
-
-/**
- * Component for the entire document list.
- */
-class DocumentList extends React.Component {
-
- /**
- * The component constructor.
- *
- * @param {Object} props - The properties.
- */
- constructor(props) {
- super(props);
- const appRegistry = global.hadronApp.appRegistry;
- this.samplingMessage = appRegistry.getComponent('Query.SamplingMessage');
- this.CollectionStore = appRegistry.getStore('App.CollectionStore');
- this.NamespaceStore = appRegistry.getStore('App.NamespaceStore');
- this.projection = false;
- this.queryBar = appRegistry.getComponent('Query.QueryBar');
- this.QueryChangedStore = appRegistry.getStore('Query.ChangedStore');
- this.Document = appRegistry.getRole('CRUD.Document')[0].component;
- this.state = {
- docs: [],
- nextSkip: 0,
- namespace: this.NamespaceStore.ns,
- loading: false
- };
- }
-
- /**
- * Fetch the state when the component mounts.
- */
- componentDidMount() {
- this.attachScrollEvent();
- this.unsubscribeReset = ResetDocumentListStore.listen(this.handleReset.bind(this));
- this.unsubscribeLoadMore = LoadMoreDocumentsStore.listen(this.handleLoadMore.bind(this));
- this.unsubscribeRemove = RemoveDocumentStore.listen(this.handleRemove.bind(this));
- this.unsubscribeInsert = InsertDocumentStore.listen(this.handleInsert.bind(this));
- this.unsubscribeQueryStore = this.QueryChangedStore.listen(this.handleQueryChanged.bind(this));
- }
-
- /**
- * Unsibscribe from the document list store when unmounting.
- */
- componentWillUnmount() {
- this.unsubscribeReset();
- this.unsubscribeLoadMore();
- this.unsubscribeRemove();
- this.unsubscribeInsert();
- }
-
- /**
- * Attach the scroll event to the parent container.
- */
- attachScrollEvent() {
- this._node.parentNode.parentNode.addEventListener(
- SCROLL_EVENT,
- this.handleScroll.bind(this)
- );
- }
-
- /**
- * Handle the loading of more documents.
- *
- * @param {Object} error - Error when trying to load more documents.
- * @param {Array} documents - The next batch of documents.
- */
- handleLoadMore(error, documents) {
- // If not resetting we append the documents to the existing
- // list and increment the page. The loaded count is incremented
- // by the number of new documents.
- this.setState({
- docs: this.state.docs.concat(this.renderDocuments(documents)),
- nextSkip: (this.state.nextSkip + documents.length),
- loadedCount: (this.state.loadedCount + documents.length),
- error: error,
- loading: false
- });
- }
-
- /**
- * Handle the reset of the document list.
- *
- * @param {Object} error - Error when trying to reset the document list.
- * @param {Array} documents - The documents.
- * @param {Integer} count - The count.
- */
- handleReset(error, documents, count) {
- if (error) {
- this.setState({ error: error });
- } else {
- // If resetting, then we need to go back to page one with
- // the documents as the filter changed. The loaded count and
- // total count are reset here as well.
- this.setState({
- docs: this.renderDocuments(documents),
- nextSkip: documents.length,
- count: count,
- loadedCount: documents.length,
- namespace: this.NamespaceStore.ns,
- error: error
- });
- }
- }
-
- /**
- * Handles removal of a document from the document list.
- *
- * @param {Object} id - The id of the removed document.
- */
- handleRemove(id) {
- const index = _.findIndex(this.state.docs, (component) => {
- const _id = component.props.children.props.doc._id;
- if (id instanceof ObjectID) {
- return id.equals(_id);
- }
- return _id === id;
- });
- this.state.docs.splice(index, 1);
- this.setState({
- docs: this.state.docs,
- loadedCount: (this.state.loadedCount - 1),
- nextSkip: (this.state.nextSkip - 1)
- });
- }
-
- /**
- * Handle the scroll event of the parent container.
- *
- * @param {Event} evt - The scroll event.
- */
- handleScroll(evt) {
- const container = evt.srcElement;
- if (container.scrollTop === (container.scrollHeight - container.offsetHeight)) {
- this.loadMore();
- }
- }
-
- /**
- * Handle opening of the insert dialog.
- */
- handleOpenInsert() {
- Actions.openInsertDocumentDialog({ _id: new ObjectID(), '': '' }, false);
- }
-
- /**
- * Handle insert of a new document.
- *
- * @param {Boolean} success - If the insert was successful.
- * @param {Object} doc - The raw document that was inserted.
- */
- handleInsert(success, doc) {
- if (success) {
- this.setState({
- docs: this.state.docs.concat(this.renderDocuments([doc])),
- nextSkip: (this.state.nextSkip + 1),
- loadedCount: (this.state.loadedCount + 1),
- count: this.state.count + 1
- });
- }
- }
-
- handleQueryChanged(state) {
- debug('state', state);
- this.projection = state.project !== null;
- }
-
- /**
- * Get the next batch of documents. Will only fire if there are more documents
- * in the collection to load.
- */
- loadMore() {
- if (!this.state.loading && (this.state.loadedCount < this.state.count)) {
- this.setState({ loading: true });
- Action.fetchNextDocuments(this.state.nextSkip);
- }
- }
-
- /**
- * Get the key for a doc.
- *
- * @returns {String} The unique key.
- */
- _key() {
- return uuid.v4();
- }
-
- /**
- * Get the document list item components.
- *
- * @param {Array} docs - The raw documents.
- *
- * @return {Array} The document list item components.
- */
- renderDocuments(docs) {
- return _.map(docs, (doc) => {
- const editable = !this.CollectionStore.isReadonly() && !this.projection;
- return (
-
-
-
- );
- });
- }
-
- /**
- * Render the list of documents.
- *
- * @returns {React.Component} The list.
- */
- renderContent() {
- if (this.state.error) {
- return (
-
- {this.state.error.message}
-
- );
- }
- return (
-
-
-
this._node = c}>
- {this.state.docs}
-
-
-
-
-
-
-
- );
- }
-
- /**
- * Render the document list.
- *
- * @returns {React.Component} The document list.
- */
- render() {
- return (
-
-
-
-
-
- {this.renderContent()}
-
- );
- }
-}
-
-DocumentList.displayName = 'DocumentList';
-DocumentList.Document = Document;
-
-module.exports = DocumentList;
diff --git a/src/internal-packages/crud/lib/component/document.jsx b/src/internal-packages/crud/lib/component/document.jsx
deleted file mode 100644
index cd294eaa883..00000000000
--- a/src/internal-packages/crud/lib/component/document.jsx
+++ /dev/null
@@ -1,36 +0,0 @@
-const React = require('react');
-const PropTypes = require('prop-types');
-const EditableDocument = require('./editable-document');
-const ReadonlyDocument = require('./readonly-document');
-
-/**
- * Component for a single document in a list of documents.
- */
-class Document extends React.Component {
-
- /**
- * Render a single document list item.
- *
- * @returns {React.Component} The component.
- */
- render() {
- if (this.props.editable) {
- return ();
- }
- return (
-
- );
- }
-}
-
-Document.displayName = 'Document';
-
-Document.propTypes = {
- doc: PropTypes.object.isRequired,
- editable: PropTypes.bool,
- expandAll: PropTypes.bool
-};
-
-module.exports = Document;
diff --git a/src/internal-packages/crud/lib/component/editable-document.jsx b/src/internal-packages/crud/lib/component/editable-document.jsx
deleted file mode 100644
index 8714add8760..00000000000
--- a/src/internal-packages/crud/lib/component/editable-document.jsx
+++ /dev/null
@@ -1,484 +0,0 @@
-const app = require('hadron-app');
-const React = require('react');
-const PropTypes = require('prop-types');
-const Reflux = require('reflux');
-const HadronDocument = require('hadron-document');
-const Element = require('hadron-document').Element;
-const Actions = require('../actions');
-const EditableElement = require('./editable-element');
-const DocumentActions = require('./document-actions');
-const DocumentFooter = require('./document-footer');
-const RemoveDocumentFooter = require('./remove-document-footer');
-
-/**
- * The arrow up class.
- */
-const ARROW_UP = 'fa fa-arrow-up';
-
-/**
- * The arrow down class.
- */
-const ARROW_DOWN = 'fa fa-arrow-down';
-
-/**
- * The base class.
- */
-const BASE = 'document';
-
-/**
- * The elements class.
- */
-const ELEMENTS = `${BASE}-elements`;
-
-/**
- * The field limit.
- */
-const FIELD_LIMIT = 30;
-
-/**
- * The expander class.
- */
-const EXPANDER = 'btn btn-default btn-xs';
-
-/**
- * The test id.
- */
-const TEST_ID = 'editable-document';
-
-/**
- * The delete error message.
- */
-const DELETE_ERROR = new Error('Cannot delete documents that do not have an _id field.');
-
-/**
- * Component for a single editable document in a list of documents.
- */
-class EditableDocument extends React.Component {
-
- /**
- * The component constructor.
- *
- * @param {Object} props - The properties.
- */
- constructor(props) {
- super(props);
- this.doc = EditableDocument.loadDocument(props.doc);
- this.state = {
- editing: false,
- deleting: false,
- deleteFinished: false,
- expandAll: false,
- expanded: false
- };
-
- // Actions need to be scoped to the single document component and not
- // global singletons.
- this.actions = Reflux.createActions([ 'update', 'remove', 'cancelRemove' ]);
-
- // The update store needs to be scoped to a document and not a global
- // singleton.
- this.updateStore = this.createUpdateStore(this.actions);
- this.removeStore = this.createRemoveStore(this.actions);
- }
-
- /**
- * Subscribe to the update store on mount.
- */
- componentDidMount() {
- this.unsubscribeUpdate = this.updateStore.listen(this.handleStoreUpdate.bind(this));
- this.unsubscribeRemove = this.removeStore.listen(this.handleStoreRemove.bind(this));
- this.subscribeToDocumentEvents();
- }
-
- /**
- * Unsubscribe from the udpate store on unmount.
- */
- componentWillUnmount() {
- this.unsubscribeUpdate();
- this.unsubscribeRemove();
- this.unsubscribeFromDocumentEvents();
- }
-
- /**
- * Load the hadron document for the provided document.
- *
- * @param {Object} doc - The document to load.
- *
- * @returns {HadronDocument} The hadron document.
- */
- static loadDocument(doc) {
- return new HadronDocument(doc);
- }
-
- subscribeToDocumentEvents() {
- this.unsubscribeFromDocumentEvents();
-
- if (!this.unsubscribeAdded) {
- this.unsubscribeAdded = this.handleModify.bind(this);
- this.unsubscribeRemoved = this.handleModify.bind(this);
- this.unsubscribeCancel = this.handleCancel.bind(this);
- }
-
- this.doc.on(Element.Events.Added, this.unsubscribeAdded);
- this.doc.on(Element.Events.Removed, this.unsubscribeRemoved);
- this.doc.on(HadronDocument.Events.Cancel, this.unsubscribeCancel);
- }
-
- unsubscribeFromDocumentEvents() {
- if (this.unsubscribeAdded) {
- this.doc.removeListener(Element.Events.Added, this.unsubscribeAdded);
- this.doc.removeListener(Element.Events.Removed, this.unsubscribeRemoved);
- this.doc.removeListener(HadronDocument.Events.Cancel, this.unsubscribeCancel);
- }
- }
-
- /**
- * Create the scoped update store.
- *
- * @param {Action} actions - The component reflux actions.
- *
- * @returns {Store} The scoped store.
- */
- createUpdateStore(actions) {
- return Reflux.createStore({
-
- /**
- * Initialize the store.
- */
- init: function() {
- this.ns = app.appRegistry.getStore('App.NamespaceStore').ns;
- this.listenTo(actions.update, this.update);
- },
-
- /**
- * Update the document in the database.
- *
- * @param {Object} object - The replacement document.
- *
- * @todo: Durran: Determine shard key.
- */
- update: function(object) {
- // TODO (@thomasr) this does not work for projections
- app.dataService.findOneAndReplace(
- this.ns,
- { _id: object._id },
- object,
- { returnOriginal: false, promoteValues: false },
- this.handleResult
- );
- },
-
- /**
- * Handle the result from the driver.
- *
- * @param {Error} error - The error.
- * @param {Object} doc - The document.
- *
- * @returns {Object} The trigger event.
- */
- handleResult: function(error, doc) {
- return (error) ? this.trigger(false, error) : this.trigger(true, doc);
- }
- });
- }
-
- /**
- * Create the scoped remove store.
- *
- * @param {Action} actions - The component reflux actions.
- *
- * @returns {Store} The scoped store.
- */
- createRemoveStore(actions) {
- return Reflux.createStore({
-
- /**
- * Initialize the store.
- */
- init: function() {
- this.ns = app.appRegistry.getStore('App.NamespaceStore').ns;
- this.listenTo(actions.remove, this.remove);
- },
-
- /**
- * Remove the document from the collection.
- *
- * @param {Object} object - The object to delete.
- */
- remove: function(object) {
- const id = object.getId();
- if (id) {
- app.dataService.deleteOne(this.ns, { _id: id }, {}, this.handleResult);
- } else {
- this.handleResult(DELETE_ERROR);
- }
- },
-
- /**
- * Handle the result from the driver.
- *
- * @param {Error} error - The error.
- * @param {Object} result - The document.
- *
- * @returns {Object} The trigger event.
- */
- handleResult: function(error, result) {
- return (error) ? this.trigger(false, error) : this.trigger(true, result);
- }
- });
- }
-
- /**
- * Handle clicking the expand button.
- */
- handleExpandClick() {
- this.setState({ expanded: !this.state.expanded });
- }
-
- /**
- * Handles a trigger from the store.
- *
- * @param {Boolean} success - If the update succeeded.
- * @param {Object} object - The error or document.
- */
- handleStoreUpdate(success, object) {
- if (this.state.editing) {
- if (success) {
- this.handleUpdateSuccess(object);
- }
- }
- }
-
- /**
- * Handles a trigger from the store.
- *
- * @param {Boolean} success - If the update succeeded.
- * @param {Object} object - The error or document.
- */
- handleStoreRemove(success) {
- if (success) {
- this.handleRemoveSuccess();
- }
- }
-
- /**
- * Handle a sucessful update.
- *
- * @param {Object} doc - The updated document.
- */
- handleUpdateSuccess(doc) {
- this.doc = EditableDocument.loadDocument(doc);
- this.subscribeToDocumentEvents();
- setTimeout(() => {
- this.setState({ editing: false });
- }, 500);
- }
-
- /**
- * Handle a sucessful update.
- *
- * @param {Object} doc - The updated document.
- */
- handleRemoveSuccess() {
- this.setState({ deleting: false, deleteFinished: true });
- Actions.documentRemoved(this.props.doc._id);
- }
-
- /**
- * Handles canceling edits to the document.
- */
- handleCancel() {
- this.setState({ editing: false });
- }
-
- /**
- * Handle cloning of the document.
- */
- handleClone() {
- Actions.openInsertDocumentDialog(this.doc.generateObject(), true);
- }
-
- /**
- * Handles document deletion.
- */
- handleDelete() {
- this.setState({ editing: false, deleting: true, expanded: true });
- }
-
- /**
- * Handles canceling a delete.
- */
- handleCancelDelete() {
- this.setState({ deleting: false });
- }
-
- /**
- * Handle the edit click.
- */
- handleEdit() {
- this.setState({ editing: true, expanded: true });
- }
-
- /**
- * Handles modification to the document.
- */
- handleModify() {
- this.setState({});
- }
-
- /**
- * Handle clicking the expand all button.
- */
- handleExpandAll() {
- this.setState({ expandAll: !this.state.expandAll });
- }
-
- /**
- * Get the current style of the document div.
- *
- * @returns {String} The document class name.
- */
- style() {
- let style = BASE;
- if (this.state.editing) {
- style = style.concat(' document-is-editing');
- }
- if (this.state.deleting && !this.state.deleteFinished) {
- style = style.concat(' document-is-deleting');
- }
- return style;
- }
-
- /**
- * Render the actions component.
- *
- * @returns {Component} The actions component.
- */
- renderActions() {
- if (!this.state.editing && !this.state.deleting) {
- return (
-
- );
- }
- }
-
- /**
- * Get the elements for the document. If we are editing, we get editable elements,
- * otherwise the readonly elements are returned.
- *
- * @returns {Array} The elements.
- */
- renderElements() {
- const components = [];
- let index = 0;
- for (const element of this.doc.elements) {
- components.push((
-
- ));
- index++;
- }
- return components;
- }
-
- /**
- * Render the expander bar.
- *
- * @returns {React.Component} The expander bar.
- */
- renderExpansion() {
- if (this.doc.elements.size > FIELD_LIMIT && !this.state.editing && !this.state.deleting) {
- return (
-
- );
- }
- }
-
- /**
- * Render the expansion text.
- *
- * @returns {String} The text.
- */
- renderExpansionText() {
- const extraFields = this.doc.elements.size - FIELD_LIMIT;
- if (this.state.expanded) {
- return `Hide ${extraFields} fields`;
- }
- return `Show ${extraFields} more fields`;
- }
-
- /**
- * Render the footer component.
- *
- * @returns {Component} The footer component.
- */
- renderFooter() {
- if (this.state.editing) {
- return (
-
- );
- } else if (this.state.deleting) {
- return (
-
- );
- }
- }
-
- /**
- * Render the style for the expansion icon.
- *
- * @returns {String} The style.
- */
- renderIconStyle() {
- return this.state.expanded ? ARROW_UP : ARROW_DOWN;
- }
-
- /**
- * Render a single document list item.
- *
- * @returns {React.Component} The component.
- */
- render() {
- return (
-
-
- {this.renderElements()}
- {this.renderExpansion()}
-
- {this.renderActions()}
- {this.renderFooter()}
-
- );
- }
-}
-
-EditableDocument.displayName = 'EditableDocument';
-
-EditableDocument.propTypes = {
- doc: PropTypes.object.isRequired,
- editable: PropTypes.bool,
- expandAll: PropTypes.bool
-};
-
-module.exports = EditableDocument;
diff --git a/src/internal-packages/crud/lib/component/editable-element.jsx b/src/internal-packages/crud/lib/component/editable-element.jsx
deleted file mode 100644
index 00ba3ae3c3f..00000000000
--- a/src/internal-packages/crud/lib/component/editable-element.jsx
+++ /dev/null
@@ -1,432 +0,0 @@
-const React = require('react');
-const PropTypes = require('prop-types');
-const getComponent = require('hadron-react-bson');
-const { Element } = require('hadron-document');
-const EditableKey = require('./editable-key');
-const EditableValue = require('./editable-value');
-const ElementAction = require('./element-action');
-const LineNumber = require('./line-number');
-const Types = require('./types');
-
-/**
- * The BEM base style name for the element.
- */
-const BEM_BASE = 'editable-element';
-
-/**
- * The BEM base style name for the expandable element.
- */
-const BEM_EXP_BASE = 'editable-expandable-element';
-
-/**
- * The added constant.
- */
-const ADDED = 'is-added';
-
-/**
- * The edited constant.
- */
-const EDITED = 'is-edited';
-
-/**
- * The editing constant.
- */
-const EDITING = 'is-editing';
-
-/**
- * The field limit.
- */
-const FIELD_LIMIT = 30;
-
-/**
- * The removed constant.
- */
-const REMOVED = 'is-removed';
-
-/**
- * The expanded class name.
- */
-const EXPANDED = 'is-expanded';
-
-/**
- * The class for the document itself.
- */
-const CHILDREN = `${BEM_EXP_BASE}-children`;
-
-/**
- * The header class for expandable elements.
- */
-const HEADER = `${BEM_EXP_BASE}-header`;
-
-/**
- * The expandable label class.
- */
-const HEADER_LABEL = `${HEADER}-label`;
-
-/**
- * The separator style.
- */
-const SEPARATOR = 'element-separator';
-
-/**
- * The field class.
- */
-const FIELD_CLASS = 'editable-element-field';
-
-/**
- * Wrapper class.
- */
-const WRAPPER = 'editable-element-value-wrapper';
-
-/**
- * General editable element component.
- */
-class EditableElement extends React.Component {
-
- /**
- * The component constructor.
- *
- * @param {Object} props - The properties.
- */
- constructor(props) {
- super(props);
- this.element = props.element;
- this.state = {
- expanded: this.props.expandAll,
- expandAll: this.props.expandAll,
- focusKey: false,
- focusValue: false
- };
- }
-
- /**
- * Subscribe to the events.
- */
- componentDidMount() {
- this.unsubscribeAdded = this.handleExpand.bind(this);
- this.unsubscribeConverted = this.handleExpand.bind(this);
- this.unsubscribeEdited = this.handleChange.bind(this);
- this.unsubscribeRemoved = this.handleChange.bind(this);
- this.unsubscribeReverted = this.handleChange.bind(this);
- this.unsubscribeInvalid = this.handleChange.bind(this);
-
- this.element.on(Element.Events.Added, this.unsubscribeAdded);
- this.element.on(Element.Events.Converted, this.unsubscribeConverted);
- this.element.on(Element.Events.Edited, this.unsubscribeEdited);
- this.element.on(Element.Events.Removed, this.unsubscribeRemoved);
- this.element.on(Element.Events.Reverted, this.unsubscribeReverted);
- this.element.on(Element.Events.Invalid, this.unsubscribeInvalid);
- }
-
- /**
- * Set the state if the expand all prop changes.
- *
- * @param {Object} nextProps - The next properties.
- */
- componentWillReceiveProps(nextProps) {
- const state = {};
- if (!nextProps.editing) {
- state.focusKey = false;
- state.focusValue = false;
- }
-
- if (nextProps.expandAll !== this.state.expandAll) {
- state.expanded = nextProps.expandAll;
- state.expandAll = nextProps.expandAll;
- }
-
- this.setState(state);
- }
-
- /**
- * Unsubscribe from the events.
- */
- componentWillUnmount() {
- this.element.removeListener(Element.Events.Added, this.unsubscribeAdded);
- this.element.removeListener(Element.Events.Converted, this.unsubscribeConverted);
- this.element.removeListener(Element.Events.Edited, this.unsubscribeEdited);
- this.element.removeListener(Element.Events.Removed, this.unsubscribeRemoved);
- this.element.removeListener(Element.Events.Reverted, this.unsubscribeReverted);
- this.element.removeListener(Element.Events.Invalid, this.unsubscribeInvalid);
- }
-
- /**
- * Expand the element.
- */
- handleExpand() {
- this.setState({ expanded: true });
- }
-
- /**
- * Here to re-render the component when a change is made.
- */
- handleChange() {
- this.setState({});
- }
-
- /**
- * Toggles the expandable aspect of the element.
- */
- toggleExpandable() {
- this.setState({ expanded: !this.state.expanded });
- }
-
- /**
- * Get the inline style for the element.
- *
- * @returns {Object} The inline style object.
- */
- inlineStyle() {
- return { paddingLeft: `${this.props.indent}px` };
- }
-
- /**
- * Get the inline style for the toggle.
- *
- * @returns {Object} The inline style for the toggle.
- */
- inlineToggleStyle() {
- return { left: `${this.props.indent + 48}px` };
- }
-
- /**
- * Get the style for the element component.
- *
- * @param {String} base - The base style.
- *
- * @returns {String} The element style.
- */
- style(base = BEM_BASE) {
- let style = base;
- if (this.props.editing) {
- style = style.concat(` ${base}-${EDITING}`);
- if (this.element.isAdded()) {
- style = style.concat(` ${base}-${ADDED}`);
- } else if (this.element.isEdited()) {
- style = style.concat(` ${base}-${EDITED}`);
- } else if (this.element.isRemoved()) {
- style = style.concat(` ${base}-${REMOVED}`);
- }
- } else if (this.props.rootFieldIndex >= FIELD_LIMIT) {
- style = `${style} hidden`;
- }
- if (this.state.expanded) {
- style = style.concat(` ${base}-${EXPANDED}`);
- }
- return style;
- }
-
- focusEditKey() {
- this.props.edit();
- this.setState({focusKey: true});
- }
-
- focusEditValue() {
- this.props.edit();
- this.setState({focusValue: true});
- }
-
- /**
- * Get the components for the elements.
- *
- * @returns {Array} The components.
- */
- renderChildren() {
- const components = [];
- if (!this.state.expanded && !this.props.expandAll) {
- // COMPASS-1312 Lazily render children when user clicks on expand
- return components;
- }
- let index = 0;
- for (const element of this.element.elements) {
- components.push((
-
- ));
- index++;
- }
- return components;
- }
-
- /**
- * Render the action column.
- *
- * @returns {React.Component} The component.
- */
- renderAction() {
- if (this.props.editing && this.element.isValueEditable()) {
- return ();
- }
- }
-
- /**
- * Render the line number column.
- *
- * @returns {React.Component} The component.
- */
- renderLineNumber() {
- if (this.props.editing) {
- return ();
- }
- }
-
- /**
- * Render the separator column.
- *
- * @returns {React.Component} The component.
- */
- renderSeparator() {
- return (:);
- }
-
- /**
- * Render the types column.
- *
- * @returns {React.Component} The component.
- */
- renderTypes() {
- if (this.props.editing) {
- return ();
- }
- }
-
- /**
- * Render the key column.
- *
- * @returns {React.Component} The component.
- */
- renderKey() {
- if (this.props.editing && this.element.isKeyEditable()) {
- return ();
- }
- const onDoubleClick = this.element.isKeyEditable() ? null : this.focusEditKey.bind(this);
- return (
-
- {this.element.parent.currentType === 'Array' ? this.props.index : this.element.currentKey}
-
- );
- }
-
- /**
- * Render the toggle column.
- *
- * @returns {Component} The component.
- */
- renderToggle() {
- const HEADER_TOGGLE = this.state.expanded ? 'fa fa-angle-down' : 'fa fa-angle-right';
-
- return (
-
-
- );
- }
-
- /**
- * Render the expandable label column.
- *
- * @returns {Component} The component.
- */
- renderLabel() {
- return (
-
- {this.element.currentType}
-
- );
- }
-
- /**
- * Render the value column.
- *
- * @todo: Durran: Editing or not?
- *
- * @returns {Component} The component.
- */
- renderValue() {
- if (this.props.editing && this.element.isValueEditable()) {
- return ();
- }
- const component = getComponent(this.element.currentType);
- const reactComponent = React.createElement(
- component,
- { type: this.element.currentType, value: this.element.currentValue }
- );
-
- return {reactComponent};
- }
-
- /**
- * Render a non-expandable element.
- *
- * @returns {Component} The component.
- */
- renderNonExpandable() {
- return (
-
- {this.renderAction()}
- {this.renderLineNumber()}
- {this.renderKey()}
- {this.renderSeparator()}
- {this.renderValue()}
- {this.renderTypes()}
-
- );
- }
-
- /**
- * Render an expandable element.
- *
- * @returns {React.Component} The component.
- */
- renderExpandable() {
- return (
-
-
- {this.renderAction()}
- {this.renderLineNumber()}
- {this.renderToggle()}
- {this.renderKey()}
- {this.renderSeparator()}
- {this.renderLabel()}
- {this.renderTypes()}
-
-
- {this.renderChildren()}
-
-
- );
- }
-
- /**
- * Render a single editable element.
- *
- * @returns {React.Component} The element component.
- */
- render() {
- return this.element.elements ? this.renderExpandable() : this.renderNonExpandable();
- }
-}
-
-EditableElement.displayName = 'EditableElement';
-
-EditableElement.propTypes = {
- editing: PropTypes.bool,
- edit: PropTypes.func,
- element: PropTypes.object.isRequired,
- index: PropTypes.number,
- indent: PropTypes.number,
- expandAll: PropTypes.bool,
- rootFieldIndex: PropTypes.number
-};
-
-module.exports = EditableElement;
diff --git a/src/internal-packages/crud/lib/component/editable-key.jsx b/src/internal-packages/crud/lib/component/editable-key.jsx
deleted file mode 100644
index fb09f5c3702..00000000000
--- a/src/internal-packages/crud/lib/component/editable-key.jsx
+++ /dev/null
@@ -1,234 +0,0 @@
-const React = require('react');
-const PropTypes = require('prop-types');
-const chars = require('./utils');
-
-/* eslint no-return-assign:0 */
-
-/**
- * The editing class constant.
- */
-const EDITING = 'editable-element-field-is-editing';
-
-/**
- * The duplicate key value.
- */
-const DUPLICATE = 'editable-element-field-is-duplicate';
-
-/**
- * The document key class.
- */
-const KEY_CLASS = 'editable-element-field';
-
-/**
- * Escape key code.
- */
-const ESC = 27;
-
-/**
- * Colon key code.
- */
-const COLON = 186;
-
-/**
- * General editable key component.
- */
-class EditableKey extends React.Component {
-
- /**
- * The component constructor.
- *
- * @param {Object} props - The properties.
- */
- constructor(props) {
- super(props);
- this.element = props.element;
- this.state = { duplcate: false, editing: false };
- }
-
- /**
- * Focus on this field on mount, so the tab can do it's job and move
- * to the value field.
- */
- componentDidMount() {
- if (this.isAutoFocusable() || this.props.isFocused) {
- this._node.focus();
- }
- }
-
- /**
- * When hitting a key on the last element some special things may happen.
- *
- * @param {Event} evt - The event.
- */
- handleKeyDown(evt) {
- const value = evt.target.value;
- if (evt.keyCode === ESC) {
- if (value.length === 0) {
- this.element.remove();
- } else {
- this._node.blur();
- }
- } else if (evt.keyCode === 13) {
- // Simulate a tab if the user presses enter.
- try {
- this._node.nextSibling.nextSibling.firstChild.focus();
- } catch (e) {
- return;
- }
- }
- }
-
- /**
- * If they key is a colon, tab to the next input.
- *
- * @param {Object} evt - The event.
- */
- handleKeyUp(evt) {
- if (evt.keyCode === COLON) {
- const value = evt.target.value;
- if (value !== ':') {
- this.element.rename(value.replace(':', ''));
- evt.target.value = '';
- // focus is not always available, this is now guarded
- try {
- this._node.nextSibling.nextSibling.firstChild.focus();
- } catch (e) {
- return;
- }
- }
- }
- }
-
- /**
- * Handles changes to the element key.
- *
- * @param {Event} evt - The event.
- */
- handleChange(evt) {
- const value = evt.target.value;
- this._node.size = chars(value);
- if (this.isEditable()) {
- if (this.element.isDuplicateKey(value)) {
- this.setState({ duplicate: true });
- } else if (this.state.duplicate) {
- this.setState({ duplicate: false });
- }
- this.element.rename(value);
- }
- }
-
- /**
- * Handle focus on the key.
- */
- handleFocus() {
- if (this.isEditable()) {
- this.setState({ editing: true });
- }
- }
-
- /**
- * Handle blur from the key.
- */
- handleBlur() {
- if (this.isEditable()) {
- this.setState({ editing: false });
- }
- }
-
- /**
- * Is this component auto focusable?
- *
- * This is true if:
- * - When a new element has been added and is a normal element.
- * - When not being tabbed into.
- *
- * Is false if:
- * - When a new array value has been added.
- * - When the key is _id
- *
- * @returns {Boolean} If the component is editable.
- */
- isAutoFocusable() {
- return this.element.isAdded() && this.isEditable();
- }
-
- /**
- * Is the key able to be edited?
- *
- * @returns {Boolean} If the key can be edited.
- */
- isEditable() {
- return this.element.isKeyEditable() && this.element.parent.currentType !== 'Array';
- }
-
- /**
- * Get the style for the key of the element.
- *
- * @returns {String} The key style.
- */
- style() {
- let style = KEY_CLASS;
- if (this.state.editing) {
- style = style.concat(` ${EDITING}`);
- }
- if (this.state.duplicate) {
- style = style.concat(` ${DUPLICATE}`);
- }
- return style;
- }
-
- /**
- * Render the value of the key.
- *
- * @returns {String} The value for the key.
- */
- renderValue() {
- return this.element.parent.currentType === 'Array' ? this.props.index : this.element.currentKey;
- }
-
- /**
- * Render the title.
- *
- * @returns {String} The title.
- */
- renderTitle() {
- if (this.state.duplicate) {
- return `Duplicate key: '${this.element.currentKey}' - this will overwrite previous values.`;
- }
- return this.element.currentKey;
- }
-
- /**
- * Render a single editable key.
- *
- * @returns {React.Component} The element component.
- */
- render() {
- const length = (chars(this.renderValue()) * 6.625) + 6.625;
- return (
- this._node = c}
- type="text"
- style={{ width: `${length}px` }}
- tabIndex={this.isEditable() ? 0 : -1}
- onBlur={this.handleBlur.bind(this)}
- onFocus={this.handleFocus.bind(this)}
- onChange={this.handleChange.bind(this)}
- onKeyDown={this.handleKeyDown.bind(this)}
- onKeyUp={this.handleKeyUp.bind(this)}
- value={this.renderValue()}
- title={this.renderTitle()} />
- );
- }
-}
-
-EditableKey.displayName = 'EditableKey';
-
-EditableKey.propTypes = {
- element: PropTypes.object.isRequired,
- index: PropTypes.number,
- isFocused: PropTypes.bool.isRequired
-};
-
-module.exports = EditableKey;
diff --git a/src/internal-packages/crud/lib/component/editable-value.jsx b/src/internal-packages/crud/lib/component/editable-value.jsx
deleted file mode 100644
index df4f8631043..00000000000
--- a/src/internal-packages/crud/lib/component/editable-value.jsx
+++ /dev/null
@@ -1,267 +0,0 @@
-const app = require('hadron-app');
-const React = require('react');
-const PropTypes = require('prop-types');
-const { Tooltip } = require('hadron-react-components');
-const initEditors = require('./editor/');
-
-/* eslint no-return-assign:0 */
-
-/**
- * Escape key code.
- */
-const ESC = 27;
-
-/**
- * The editing class constant.
- */
-const EDITING = 'is-editing';
-
-/**
- * The document value class.
- */
-const VALUE_CLASS = 'editable-element-value';
-
-/**
- * The version at which high precision values are available.
- */
-const HP_VERSION = '3.4.0';
-
-/**
- * Invalid type class.
- */
-const INVALID = `${VALUE_CLASS}-is-invalid-type`;
-
-/**
- * General editable value component.
- */
-class EditableValue extends React.Component {
-
- /**
- * The component constructor.
- *
- * @param {Object} props - The properties.
- */
- constructor(props) {
- super(props);
- this.element = props.element;
- this.state = { editing: false };
- this._pasting = false;
- this._version = app.instance.build.version;
- this._editors = initEditors(this.element);
- }
-
- /**
- * Focus on this field on mount, so the tab can do it's job and move
- * to the value field.
- */
- componentDidMount() {
- if (this.isAutoFocusable() || this.props.isFocused) {
- this._node.focus();
- }
- }
-
- /**
- * Get the editor for the current type.
- *
- * @returns {Editor} The editor.
- */
- editor() {
- return this._editors[this.element.currentType] || this._editors.Standard;
- }
-
- /**
- * Is the element auto-focusable?
- *
- * @returns {Boolean} If the element can be focused automatically.
- */
- isAutoFocusable() {
- return !this.element.isKeyEditable();
- }
-
- /**
- * Are high precision values available?
- *
- * @returns {boolean} if high precision values are available.
- */
- isHighPrecision() {
- return this._version >= HP_VERSION;
- }
-
- /**
- * When hitting a key on the last element some special things may happen.
- *
- * @param {Event} evt - The event.
- */
- handleKeyDown(evt) {
- if (evt.keyCode === 9 && !evt.shiftKey) {
- this.simulateTab(evt);
- } else if (evt.keyCode === ESC) {
- const value = evt.target.value;
- if (value.length === 0 && this.element.currentKey.length === 0) {
- this.element.remove();
- } else {
- this._node.blur();
- }
- } else if (evt.keyCode === 13) {
- if (this.element.nextElement) {
- // need to force the focus.
- this._node.parentNode.parentNode.nextSibling.childNodes[2].focus();
- }
- this.simulateTab(evt);
- }
- }
-
- /**
- * Simulates a tab event.
- *
- * @param {Event} evt - The event.
- */
- simulateTab(evt) {
- if (this.isTabable()) {
- if (!this.element.nextElement ||
- this.element.currentValue === '{' ||
- this.element.currentValue === '[') {
- this.element.next();
- evt.preventDefault();
- evt.stopPropagation();
- }
- } else {
- // We don't want to create another element when the current one is blank.
- evt.preventDefault();
- evt.stopPropagation();
- }
- }
-
- /**
- * Sets the flag that the user pasted the value. The reason for this is that
- * the onpaste event that is passed does not have consistent behaviour with
- * respect to event.target.value - it is sometimes undefined. The onchange
- * event always gets fired after this to we can set the flag and then check
- * for it in that event.
- */
- handlePaste() {
- this._pasting = true;
- }
-
- /**
- * Is the element tabbable.
- *
- * @returns {Boolean} If the element is tabbable.
- */
- isTabable() {
- if (this.element.parent.currentType === 'Array') {
- return this.element.currentValue !== '';
- }
- return this.element.currentKey.length !== 0;
- }
-
- /**
- * Handles changes to the element value.
- *
- * @param {Event} evt - The event.
- */
- handleChange(evt) {
- const value = evt.target.value;
- if (this._pasting) {
- this._pasteEdit(value);
- } else {
- this.editor().edit(value);
- }
- }
-
- /**
- * Edit the field value when using copy/paste.
- *
- * @param {String} value - The value to paste in.
- */
- _pasteEdit(value) {
- try {
- this.editor().paste(value);
- } catch (e) {
- this.editor().edit(value);
- } finally {
- this._pasting = false;
- }
- }
-
- /**
- * Handle focus on the value.
- */
- handleFocus() {
- this.editor().start();
- this.setState({ editing: true });
- }
-
- /**
- * Handle blur from the value. Calls complete on the editor and sets the state.
- */
- handleBlur() {
- this.editor().complete();
- this.setState({ editing: false });
- }
-
- /**
- * Get the style for the value of the element.
- *
- * @returns {String} The value style.
- */
- style() {
- let typeClass = `${VALUE_CLASS}-is-${this.element.currentType.toLowerCase()}`;
- if (!this.element.isCurrentTypeValid()) {
- typeClass = `${typeClass} ${INVALID}`;
- }
- if (this.state.editing) {
- return `${VALUE_CLASS} ${VALUE_CLASS}-${EDITING} ${typeClass}`;
- }
- return `${VALUE_CLASS} ${typeClass}`;
- }
-
- /**
- * Get the style for the input wrapper.
- *
- * @returns {String} The class name.
- */
- wrapperStyle() {
- return `${VALUE_CLASS}-wrapper ${VALUE_CLASS}-wrapper-is-${this.element.currentType.toLowerCase()}`;
- }
-
- /**
- * Render a single editable value.
- *
- * @returns {React.Component} The element component.
- */
- render() {
- const length = (this.editor().size(this.state.editing) * 6.625) + 6.625;
- return (
-
- { return this.element.invalidTypeMessage; }}/>
- this._node = c}
- type="text"
- style={{ width: `${length}px` }}
- className={this.style()}
- onBlur={this.handleBlur.bind(this)}
- onFocus={this.handleFocus.bind(this)}
- onChange={this.handleChange.bind(this)}
- onKeyDown={this.handleKeyDown.bind(this)}
- onPaste={this.handlePaste.bind(this)}
- value={this.editor().value(this.state.editing)} />
-
- );
- }
-}
-
-EditableValue.displayName = 'EditableValue';
-
-EditableValue.propTypes = {
- element: PropTypes.object.isRequired,
- isFocused: PropTypes.bool.isRequired
-};
-
-module.exports = EditableValue;
diff --git a/src/internal-packages/crud/lib/component/editor/date.js b/src/internal-packages/crud/lib/component/editor/date.js
deleted file mode 100644
index 5ee09c0d102..00000000000
--- a/src/internal-packages/crud/lib/component/editor/date.js
+++ /dev/null
@@ -1,102 +0,0 @@
-const moment = require('moment');
-const TypeChecker = require('hadron-type-checker');
-const { Element } = require('hadron-document');
-const chars = require('../utils');
-const StandardEditor = require('./standard');
-
-/**
- * The date format.
- */
-const FORMAT = 'YYYY-MM-DD HH:mm:ss.SSS';
-
-/**
- * CRUD editor for date values.
- */
-class DateEditor extends StandardEditor {
-
- /**
- * Create the editor with the element.
- *
- * @param {Element} element - The hadron document element.
- */
- constructor(element) {
- super(element);
- }
-
- /**
- * Complete the date edit by converting the valid string to a date
- * object or leaving as invalid.
- */
- complete() {
- if (this.element.isCurrentTypeValid()) {
- this.element.edit(TypeChecker.cast(this.element.currentValue, 'Date'));
- }
- }
-
- /**
- * Edit the element with the provided value.
- *
- * @param {Object} value - The new value.
- */
- edit(value) {
- try {
- const date = TypeChecker.cast(value, 'Date');
- if (date.toString() === 'Invalid Date') {
- this.element.setInvalid(value, 'Date', `${value} is not in a valid date format`);
- } else {
- this.element.currentValue = value;
- this.element.setValid();
- this.element._bubbleUp(Element.Events.Edited);
- }
- } catch (e) {
- this.element.setInvalid(value, this.element.currentType, e.message);
- }
- }
-
- /**
- * Get the number of characters the value should display.
- *
- * @param {Boolean} editMode - If the element is being edited.
- *
- * @returns {Number} The number of characters.
- */
- size(editMode) {
- const value = this.element.currentValue;
- if (editMode) {
- return chars(value);
- }
- return this.element.isCurrentTypeValid() ? chars(this._formattedValue()) : chars(value);
- }
-
- /**
- * Start the date edit.
- *
- * @param {Object} value - The value in the field.
- */
- start() {
- if (this.element.isCurrentTypeValid()) {
- this.edit(this._formattedValue());
- }
- }
-
- /**
- * Get the value being edited.
- *
- * @param {Boolean} editMode - If the UI is in edit mode.
- *
- * @returns {String} The value.
- */
- value(editMode) {
- const value = this.element.currentValue;
- if (!editMode && this.element.isCurrentTypeValid()) {
- return this._formattedValue();
- }
- return value;
- }
-
- _formattedValue() {
- return moment(this.element.currentValue).format(FORMAT);
- }
-}
-
-module.exports = DateEditor;
diff --git a/src/internal-packages/crud/lib/component/editor/double.js b/src/internal-packages/crud/lib/component/editor/double.js
deleted file mode 100644
index 09eef600434..00000000000
--- a/src/internal-packages/crud/lib/component/editor/double.js
+++ /dev/null
@@ -1,30 +0,0 @@
-const chars = require('../utils');
-const StandardEditor = require('./standard');
-
-/**
- * CRUD editor for double values.
- */
-class DoubleEditor extends StandardEditor {
-
- /**
- * Create the editor with the element.
- *
- * @param {Element} element - The hadron document element.
- */
- constructor(element) {
- super(element);
- }
-
- /**
- * Get the number of characters the value should display.
- *
- * @param {Boolean} editMode - If the element is being edited.
- *
- * @returns {Number} The number of characters.
- */
- size() {
- return chars(this.element.currentValue.value);
- }
-}
-
-module.exports = DoubleEditor;
diff --git a/src/internal-packages/crud/lib/component/editor/index.js b/src/internal-packages/crud/lib/component/editor/index.js
deleted file mode 100644
index 2e77a74bd0c..00000000000
--- a/src/internal-packages/crud/lib/component/editor/index.js
+++ /dev/null
@@ -1,31 +0,0 @@
-const StandardEditor = require('./standard');
-const StringEditor = require('./string');
-const Int32Editor = require('./int32');
-const DoubleEditor = require('./double');
-const DateEditor = require('./date');
-const NullEditor = require('./null');
-const UndefinedEditor = require('./undefined');
-const ObjectIDEditor = require('./objectid');
-
-const init = (element) => {
- return {
- 'Standard': new StandardEditor(element),
- 'String': new StringEditor(element),
- 'Date': new DateEditor(element),
- 'Double': new DoubleEditor(element),
- 'Int32': new Int32Editor(element),
- 'Null': new NullEditor(element),
- 'Undefined': new UndefinedEditor(element),
- 'ObjectID': new ObjectIDEditor(element)
- };
-};
-
-module.exports = init;
-module.exports.DateEditor = DateEditor;
-module.exports.StandardEditor = StandardEditor;
-module.exports.StringEditor = StringEditor;
-module.exports.DoubleEditor = DoubleEditor;
-module.exports.Int32Editor = Int32Editor;
-module.exports.NullEditor = NullEditor;
-module.exports.UndefinedEditor = UndefinedEditor;
-module.exports.ObjectIDEditor = ObjectIDEditor;
diff --git a/src/internal-packages/crud/lib/component/editor/int32.js b/src/internal-packages/crud/lib/component/editor/int32.js
deleted file mode 100644
index e764b5be147..00000000000
--- a/src/internal-packages/crud/lib/component/editor/int32.js
+++ /dev/null
@@ -1,30 +0,0 @@
-const chars = require('../utils');
-const StandardEditor = require('./standard');
-
-/**
- * CRUD editor for int32 values.
- */
-class Int32Editor extends StandardEditor {
-
- /**
- * Create the editor with the element.
- *
- * @param {Element} element - The hadron document element.
- */
- constructor(element) {
- super(element);
- }
-
- /**
- * Get the number of characters the value should display.
- *
- * @param {Boolean} editMode - If the element is being edited.
- *
- * @returns {Number} The number of characters.
- */
- size() {
- return chars(this.element.currentValue.valueOf());
- }
-}
-
-module.exports = Int32Editor;
diff --git a/src/internal-packages/crud/lib/component/editor/null.js b/src/internal-packages/crud/lib/component/editor/null.js
deleted file mode 100644
index f58c7c23385..00000000000
--- a/src/internal-packages/crud/lib/component/editor/null.js
+++ /dev/null
@@ -1,43 +0,0 @@
-const StandardEditor = require('./standard');
-
-/**
- * Null is always 'null'
- */
-const VALUE = 'null';
-
-/**
- * CRUD editor for null values.
- */
-class NullEditor extends StandardEditor {
-
- /**
- * Create the editor with the element.
- *
- * @param {Element} element - The hadron document element.
- */
- constructor(element) {
- super(element);
- }
-
- /**
- * Get the number of characters the value should display.
- *
- * @param {Boolean} editMode - If the element is being edited.
- *
- * @returns {Number} The number of characters.
- */
- size() {
- return 4;
- }
-
- /**
- * Get the value being edited.
- *
- * @returns {Object} The value.
- */
- value() {
- return VALUE;
- }
-}
-
-module.exports = NullEditor;
diff --git a/src/internal-packages/crud/lib/component/editor/objectid.js b/src/internal-packages/crud/lib/component/editor/objectid.js
deleted file mode 100644
index 0e55a0ac23e..00000000000
--- a/src/internal-packages/crud/lib/component/editor/objectid.js
+++ /dev/null
@@ -1,73 +0,0 @@
-const TypeChecker = require('hadron-type-checker');
-const { Element } = require('hadron-document');
-const chars = require('../utils');
-
-/**
- * CRUD editor for object id values.
- */
-class ObjectIDEditor {
-
- /**
- * Create the editor with the element.
- *
- * @param {Element} element - The hadron document element.
- */
- constructor(element) {
- this.element = element;
- }
-
- /**
- * Complete the object id edit by converting the valid string to an object id
- * object or leaving as invalid.
- */
- complete() {
- if (this.element.isCurrentTypeValid()) {
- this.element.edit(TypeChecker.cast(this.element.currentValue, 'ObjectID'));
- }
- }
-
- /**
- * Edit the element with the provided value.
- *
- * @param {Object} value - The new value.
- */
- edit(value) {
- try {
- TypeChecker.cast(value, 'ObjectID');
- this.element.currentValue = value;
- this.element.setValid();
- this.element._bubbleUp(Element.Events.Edited);
- } catch (e) {
- this.element.setInvalid(value, this.element.currentType, e.message);
- }
- }
-
- /**
- * Get the number of characters the value should display.
- *
- * @returns {Number} The number of characters.
- */
- size() {
- return chars(this.element.currentValue);
- }
-
- /**
- * Start the object id edit.
- */
- start() {
- if (this.element.isCurrentTypeValid()) {
- this.edit(String(this.element.currentValue));
- }
- }
-
- /**
- * Get the value being edited.
- *
- * @returns {String} The value.
- */
- value() {
- return this.element.currentValue;
- }
-}
-
-module.exports = ObjectIDEditor;
diff --git a/src/internal-packages/crud/lib/component/editor/standard.js b/src/internal-packages/crud/lib/component/editor/standard.js
deleted file mode 100644
index 6a67aa6141a..00000000000
--- a/src/internal-packages/crud/lib/component/editor/standard.js
+++ /dev/null
@@ -1,79 +0,0 @@
-const TypeChecker = require('hadron-type-checker');
-const { Element } = require('hadron-document');
-const chars = require('../utils');
-
-/**
- * Regex to match an array or object string.
- */
-const ARRAY_OR_OBJECT = /^(\[|\{)(.+)(\]|\})$/;
-
-/**
- * CRUD editor for standard values.
- */
-class StandardEditor {
-
- /**
- * Create the editor with the element.
- *
- * @param {Element} element - The hadron document element.
- */
- constructor(element) {
- this.element = element;
- }
-
- /**
- * Edit the element with the provided value.
- *
- * @param {Object} value - The new value.
- */
- edit(value) {
- const currentType = this.element.currentType;
- try {
- const newValue = TypeChecker.cast(value, currentType);
- this.element.edit(newValue);
- } catch (e) {
- this.element.setInvalid(value, currentType, e.message);
- }
- }
-
- /**
- * Edit the element via a paste.
- *
- * @param {String} value - The balue.
- */
- paste(value) {
- if (value.match(ARRAY_OR_OBJECT)) {
- this.edit(JSON.parse(value));
- this.element._bubbleUp(Element.Events.Converted);
- } else {
- this.edit(value);
- }
- }
-
-
- /**
- * Get the number of characters the value should display.
- *
- * @param {Boolean} editMode - If the element is being edited.
- *
- * @returns {Number} The number of characters.
- */
- size() {
- return chars(this.element.currentValue);
- }
-
- /**
- * Get the value being edited.
- *
- * @returns {Object} The value.
- */
- value() {
- return this.element.currentValue;
- }
-
- // Standard editing requires no special start/complete behaviour.
- start() {}
- complete() {}
-}
-
-module.exports = StandardEditor;
diff --git a/src/internal-packages/crud/lib/component/editor/string.js b/src/internal-packages/crud/lib/component/editor/string.js
deleted file mode 100644
index 7f96ab50ff4..00000000000
--- a/src/internal-packages/crud/lib/component/editor/string.js
+++ /dev/null
@@ -1,30 +0,0 @@
-const chars = require('../utils');
-const StandardEditor = require('./standard');
-
-/**
- * CRUD editor for string values.
- */
-class StringEditor extends StandardEditor {
-
- /**
- * Create the editor with the element.
- *
- * @param {Element} element - The hadron document element.
- */
- constructor(element) {
- super(element);
- }
-
- /**
- * Get the number of characters the value should display.
- *
- * @param {Boolean} editMode - If the element is being edited.
- *
- * @returns {Number} The number of characters.
- */
- size() {
- return chars(this.element.currentValue);
- }
-}
-
-module.exports = StringEditor;
diff --git a/src/internal-packages/crud/lib/component/editor/undefined.js b/src/internal-packages/crud/lib/component/editor/undefined.js
deleted file mode 100644
index cfc6a11cd7a..00000000000
--- a/src/internal-packages/crud/lib/component/editor/undefined.js
+++ /dev/null
@@ -1,43 +0,0 @@
-const StandardEditor = require('./standard');
-
-/**
- * Undefined is always 'undefined'
- */
-const VALUE = 'undefined';
-
-/**
- * CRUD editor for undefined values.
- */
-class UndefinedEditor extends StandardEditor {
-
- /**
- * Create the editor with the element.
- *
- * @param {Element} element - The hadron document element.
- */
- constructor(element) {
- super(element);
- }
-
- /**
- * Get the number of characters the value should display.
- *
- * @param {Boolean} editMode - If the element is being edited.
- *
- * @returns {Number} The number of characters.
- */
- size() {
- return 9;
- }
-
- /**
- * Get the value being edited.
- *
- * @returns {Object} The value.
- */
- value() {
- return VALUE;
- }
-}
-
-module.exports = UndefinedEditor;
diff --git a/src/internal-packages/crud/lib/component/element-action.jsx b/src/internal-packages/crud/lib/component/element-action.jsx
deleted file mode 100644
index 2e49af8a948..00000000000
--- a/src/internal-packages/crud/lib/component/element-action.jsx
+++ /dev/null
@@ -1,33 +0,0 @@
-const React = require('react');
-const PropTypes = require('prop-types');
-const RevertAction = require('./revert-action');
-const RemoveAction = require('./remove-action');
-const NoAction = require('./no-action');
-
-/**
- * Component to render the available action for an element.
- */
-class ElementAction extends React.Component {
-
- /**
- * Render the action available for the element.
- *
- * @returns {React.Component} The component.
- */
- render() {
- if (this.props.element.isRevertable()) {
- return ();
- } else if (this.props.element.isNotActionable()) {
- return ();
- }
- return ();
- }
-}
-
-ElementAction.displayName = 'ElementAction';
-
-ElementAction.propTypes = {
- element: PropTypes.object.isRequired
-};
-
-module.exports = ElementAction;
diff --git a/src/internal-packages/crud/lib/component/element.jsx b/src/internal-packages/crud/lib/component/element.jsx
deleted file mode 100644
index c18430dc98f..00000000000
--- a/src/internal-packages/crud/lib/component/element.jsx
+++ /dev/null
@@ -1,201 +0,0 @@
-const React = require('react');
-const PropTypes = require('prop-types');
-const getComponent = require('hadron-react-bson');
-
-/**
- * The base class.
- */
-const CLASS = 'element';
-
-/**
- * The field class.
- */
-const FIELD = `${CLASS}-field`;
-
-/**
- * The field limit.
- */
-const FIELD_LIMIT = 30;
-
-/**
- * The separator class.
- */
-const SEPARATOR = `${CLASS}-separator`;
-
-/**
- * The expandable element class.
- */
-const EXP_CLASS = 'expandable-element';
-
-/**
- * The expandable header class.
- */
-const EXP_HEADER = `${EXP_CLASS}-header`;
-
-/**
- * The carat toggle class.
- */
-const EXP_TOGGLE = `${EXP_HEADER}-toggle`;
-
-/**
- * The expandable field class.
- */
-const EXP_FIELD = `${EXP_HEADER}-field`;
-
-/**
- * The expandable label class.
- */
-const EXP_LABEL = `${EXP_HEADER}-label`;
-
-/**
- * The expandable children class.
- */
-const EXP_CHILDREN = `${EXP_CLASS}-children`;
-
-/**
- * The expandable element separator class.
- */
-const EXP_SEPARATOR = `${EXP_HEADER}-separator`;
-
-/**
- * General element component.
- */
-class Element extends React.Component {
-
- /**
- * Instantiate the element.
- *
- * @param {Object} props - The properties.
- */
- constructor(props) {
- super(props);
- this.state = { expanded: props.expandAll };
- }
-
- /**
- * Get the full class name for the base style.
- *
- * @param {String} base - The base class.
- *
- * @returns {String} The full class name.
- */
- getClassName(base) {
- if (this.state.expanded) {
- return `${base} ${base}-is-expanded`;
- }
- return base;
- }
-
- /**
- * Toggles the expandable aspect of the element.
- */
- toggleExpandable() {
- this.setState({ expanded: !this.state.expanded });
- }
-
- /**
- * Render the children.
- *
- * @returns {Array} The children.
- */
- renderChildren() {
- const components = [];
- for (const element of this.props.element.elements) {
- components.push(
- ()
- );
- }
- return components;
- }
-
- /**
- * Render a single element.
- *
- * @returns {React.Component} The single element.
- */
- renderElement() {
- return (
-
-
- {this.props.element.currentKey}
-
- :
- {this.renderValue()}
-
- );
- }
-
- /**
- * Render a single expandable element.
- *
- * @returns {React.Component} The expandable element.
- */
- renderExpandableElement() {
- return (
-
-
-
-
{this.props.element.currentKey}
-
:
-
- {this.props.element.currentType}
-
-
-
- {this.renderChildren()}
-
-
- );
- }
-
- /**
- * Render the style with the provided base style.
- *
- * @param {String} base - The base style.
- *
- * @returns {String} The style.
- */
- renderStyle(base) {
- let style = base;
- if (this.props.rootFieldIndex >= FIELD_LIMIT) {
- style = `${style} hidden`;
- }
- return style;
- }
-
- /**
- * Render the value of the element.
- *
- * @returns {React.Component} The value component.
- */
- renderValue() {
- const component = getComponent(this.props.element.currentType);
- return React.createElement(
- component,
- { type: this.props.element.currentType, value: this.props.element.currentValue }
- );
- }
-
- /**
- * Render a single element in a document.
- *
- * @returns {React.Component} The element component.
- */
- render() {
- return this.props.element.elements ? this.renderExpandableElement() : this.renderElement();
- }
-}
-
-Element.displayName = 'Element';
-
-Element.propTypes = {
- element: PropTypes.any.isRequired,
- expandAll: PropTypes.bool,
- rootFieldIndex: PropTypes.number
-};
-
-module.exports = Element;
diff --git a/src/internal-packages/crud/lib/component/insert-document-dialog.jsx b/src/internal-packages/crud/lib/component/insert-document-dialog.jsx
deleted file mode 100644
index a7343995451..00000000000
--- a/src/internal-packages/crud/lib/component/insert-document-dialog.jsx
+++ /dev/null
@@ -1,167 +0,0 @@
-const _ = require('lodash');
-const React = require('react');
-const Modal = require('react-bootstrap').Modal;
-const OpenInsertDocumentDialogStore = require('../store/open-insert-document-dialog-store');
-const InsertDocumentStore = require('../store/insert-document-store');
-const InsertDocument = require('./insert-document');
-const InsertDocumentFooter = require('./insert-document-footer');
-const { TextButton } = require('hadron-react-buttons');
-const { Element } = require('hadron-document');
-const Actions = require('../actions');
-
-/**
- * Component for the insert document dialog.
- */
-class InsertDocumentDialog extends React.Component {
-
- /**
- * The component constructor.
- *
- * @param {Object} props - The properties.
- */
- constructor(props) {
- super(props);
- this.state = { open: false, canHide: false };
- }
-
- /**
- * Subscribe to the open dialog store.
- */
- componentWillMount() {
- this.invalidElements = [];
- this.unsubscribeOpen = OpenInsertDocumentDialogStore.listen(this.handleStoreOpen.bind(this));
- this.unsubscribeInsert = InsertDocumentStore.listen(this.handleDocumentInsert.bind(this));
- this.unsubscribeClose = Actions.closeInsertDocumentDialog.listen(this.closeDialog.bind(this));
- }
-
- /**
- * Unsubscribe from the store.
- */
- componentWillUnmount() {
- this.unsubscribeOpen();
- this.unsubscribeInsert();
- this.unsubscribeClose();
- }
-
- /**
- * Close the dialog.
- */
- closeDialog() {
- this.invalidElements = [];
- this.state.doc.removeListener(Element.Events.Invalid, this.unsubscribeInvalid);
- this.state.doc.removeListener(Element.Events.Valid, this.unsubscribeValid);
- this.setState({ open: false });
- }
-
- /**
- * Handle opening the dialog with the new document.
- *
- * @param {Object} doc - The document.
- */
- handleStoreOpen(doc) {
- this.setState({ doc: doc, open: true });
- this.unsubscribeInvalid = this.handleInvalid.bind(this);
- this.unsubscribeValid = this.handleValid.bind(this);
- this.state.doc.on(Element.Events.Invalid, this.unsubscribeInvalid);
- this.state.doc.on(Element.Events.Valid, this.unsubscribeValid);
- }
-
- /**
- * Handle canceling the insert.
- */
- handleCancel() {
- this.closeDialog();
- }
-
- /**
- * handle losing focus from element
- */
- handleBlur() {
- this.setState({canHide: false});
- }
-
- /**
- * handle hide event rather than cancel
- */
- handleHide() {
- if (this.state.canHide) {
- this.closeDialog();
- } else {
- this.setState({ canHide: true });
- }
- }
-
- /**
- * Handles completion of the document insert.
- *
- * @param {Boolean} success - If the operation succeeded.
- */
- handleDocumentInsert(success) {
- if (success) {
- this.closeDialog();
- }
- }
-
- handleValid(uuid) {
- _.pull(this.invalidElements, uuid);
- this.setState({});
- Actions.elementValid(uuid);
- }
-
- handleInvalid(uuid) {
- if (!_.includes(this.invalidElements, uuid)) {
- this.invalidElements.push(uuid);
- this.setState({});
- Actions.elementInvalid(uuid);
- }
- }
-
- /**
- * Handle the insert.
- */
- handleInsert() {
- Actions.insertDocument(this.state.doc.generateObject());
- }
-
- hasErrors() {
- return this.invalidElements.length > 0;
- }
-
- /**
- * Render the modal dialog.
- *
- * @returns {React.Component} The react component.
- */
- render() {
- return (
-
-
- Insert Document
-
-
-
-
-
-
-
-
-
-
-
-
- );
- }
-}
-
-InsertDocumentDialog.displayName = 'InsertDocumentDialog';
-
-module.exports = InsertDocumentDialog;
diff --git a/src/internal-packages/crud/lib/component/insert-document-footer.jsx b/src/internal-packages/crud/lib/component/insert-document-footer.jsx
deleted file mode 100644
index b2792cbe3d9..00000000000
--- a/src/internal-packages/crud/lib/component/insert-document-footer.jsx
+++ /dev/null
@@ -1,124 +0,0 @@
-const _ = require('lodash');
-const React = require('react');
-const InsertDocumentStore = require('../store/insert-document-store');
-const Actions = require('../actions');
-
-const INSERTING = 'Inserting Document';
-
-/**
- * The invalid message.
- */
-const INVALID_MESSAGE = 'Insert not permitted while document contains errors.';
-
-/**
- * Map of modes to styles.
- */
-const MODES = {
- 'Progress': 'is-in-progress',
- 'Error': 'is-error',
- 'Viewing': 'is-viewing',
- 'Modifying': 'is-modifying'
-};
-
-/**
- * Component for the insert document footer.
- */
-class InsertDocumentFooter extends React.Component {
-
- /**
- * The component constructor.
- *
- * @param {Object} props - The properties.
- */
- constructor(props) {
- super(props);
- this.state = { message: '', mode: 'Modifying' };
- }
-
- /**
- * Subscribe to the insert document store.
- */
- componentWillMount() {
- this.invalidElements = [];
- this.unsubscribeInsert = InsertDocumentStore.listen(this.handleDocumentInsert.bind(this));
- this.unsubscribeStart = Actions.insertDocument.listen(this.handleInsertStart.bind(this));
- this.unsubscribeInvalid = Actions.elementInvalid.listen(this.handleInvalid.bind(this));
- this.unsubscribeValid = Actions.elementValid.listen(this.handleValid.bind(this));
- }
-
- /**
- * Unsubscribe from the store.
- */
- componentWillUnmount() {
- this.invalidElements = [];
- this.unsubscribeInsert();
- this.unsubscribeStart();
- this.unsubscribeInvalid();
- this.unsubscribeValid();
- }
-
- /**
- * Handles completion of document insert.
- *
- * @param {Boolean} success - If the operation succeeded.
- * @param {Object} doc - The document or error.
- */
- handleDocumentInsert(success, doc) {
- if (!success) {
- this.setState({ message: doc.message, mode: 'Error' });
- }
- }
-
- /**
- * Handles the start of a document insert.
- */
- handleInsertStart() {
- this.setState({ message: INSERTING, mode: 'Progess' });
- }
-
- handleValid(uuid) {
- _.pull(this.invalidElements, uuid);
- if (!this.hasErrors()) {
- this.handleInsertStart();
- }
- }
-
- handleInvalid(uuid) {
- if (!_.includes(this.invalidElements, uuid)) {
- this.invalidElements.push(uuid);
- this.setState({ message: INVALID_MESSAGE, mode: 'Error' });
- }
- }
-
- hasErrors() {
- return this.invalidElements.length > 0;
- }
-
- /**
- * Get the style of the footer based on the current mode.
- *
- * @returns {String} The style.
- */
- style() {
- return `document-footer document-footer-${MODES[this.state.mode]}`;
- }
-
- /**
- * Render the footer.
- *
- * @returns {Component} The footer component.
- */
- render() {
- return (
-
-
- {this.state.message}
-
-
- );
- }
-}
-
-InsertDocumentFooter.displayName = 'InsertDocumentFooter';
-
-module.exports = InsertDocumentFooter;
diff --git a/src/internal-packages/crud/lib/component/insert-document.jsx b/src/internal-packages/crud/lib/component/insert-document.jsx
deleted file mode 100644
index 4259d3b54b0..00000000000
--- a/src/internal-packages/crud/lib/component/insert-document.jsx
+++ /dev/null
@@ -1,94 +0,0 @@
-const React = require('react');
-const PropTypes = require('prop-types');
-const Element = require('hadron-document').Element;
-const EditableElement = require('./editable-element');
-
-/**
- * The class for the document itself.
- */
-const DOCUMENT = 'document';
-
-/**
- * The elements wrapper class.
- */
-const DOCUMENT_ELEMENTS = 'document-elements';
-
-/**
- * Component for a single document in a list of documents.
- */
-class InsertDocument extends React.Component {
-
- /**
- * The component constructor.
- *
- * @param {Object} props - The properties.
- */
- constructor(props) {
- super(props);
- this.doc = props.doc;
- this.doc.on(Element.Events.Added, this.handleModify.bind(this));
- this.doc.on(Element.Events.Removed, this.handleModify.bind(this));
- }
-
- /**
- * Subscribe to the events.
- */
- componentDidMount() {
- this.unsubscribeAdded = this.handleModify.bind(this);
- this.unsubscribeRemoved = this.handleModify.bind(this);
-
- this.doc.on(Element.Events.Added, this.unsubscribeAdded);
- this.doc.on(Element.Events.Removed, this.unsubscribeRemoved);
- }
-
- /**
- * Unsubscribe from the events.
- */
- componentWillUnmount() {
- this.doc.removeListener(Element.Events.Added, this.unsubscribeAdded);
- this.doc.removeListener(Element.Events.Removed, this.unsubscribeRemoved);
- }
-
- /**
- * Handle modifications to the document.
- */
- handleModify() {
- this.setState({});
- }
-
- /**
- * Get the editable elements.
- *
- * @returns {Array} The editable elements.
- */
- renderElements() {
- const components = [];
- for (const element of this.doc.elements) {
- components.push();
- }
- return components;
- }
-
- /**
- * Render a single document list item.
- *
- * @returns {React.Component} The component.
- */
- render() {
- return (
-
-
- {this.renderElements(this.doc)}
-
-
- );
- }
-}
-
-InsertDocument.displayName = 'InsertDocument';
-
-InsertDocument.propTypes = {
- doc: PropTypes.object
-};
-
-module.exports = InsertDocument;
diff --git a/src/internal-packages/crud/lib/component/line-number.jsx b/src/internal-packages/crud/lib/component/line-number.jsx
deleted file mode 100644
index 3e742602827..00000000000
--- a/src/internal-packages/crud/lib/component/line-number.jsx
+++ /dev/null
@@ -1,323 +0,0 @@
-const React = require('react');
-const PropTypes = require('prop-types');
-const outsideClickable = require('react-click-outside');
-const getComponent = require('hadron-react-bson');
-const Actions = require('../actions');
-// const debug = require('debug')('mongodb-compass:crud:line-number');
-
-/**
- * The BEM base style name for the element.
- */
-const BEM_BASE = 'line-number';
-
-/**
- * The menu class.
- */
-const MENU_CLASS = `${BEM_BASE}-menu`;
-
-/**
- * The field name class.
- */
-const FIELD_NAME_CLASS = `${MENU_CLASS}-field`;
-
-/**
- * The default text.
- */
-const DEFAULT_TEXT = 'Add Field After ';
-
-/**
- * Object text.
- */
-const OBJECT_TEXT = 'Add Field To ';
-
-/**
- * Array text.
- */
-const ARRAY_TEXT = 'Add Array Element To ';
-
-/**
- * Array element text.
- */
-const ARRAY_ELEMENT_TEXT = 'Add Array Element After ';
-
-/**
- * Add child icon.
- */
-const ADD_CHILD_ICON = 'fa fa-level-down fa-rotate-90';
-
-/**
- * Add field icon.
- */
-const ADD_FIELD_ICON = 'fa fa-plus-square-o';
-
-/**
- * Line number component.
- */
-class LineNumber extends React.Component {
-
- /**
- * Instantiate the line number component.
- *
- * @param {Object} props - The props.
- */
- constructor(props) {
- super(props);
- this.state = { menu: false };
- }
-
- /**
- * Subscribe to the close menu action.
- */
- componentDidMount() {
- this.unsubscribeClose = Actions.closeAllMenus.listen(this.handleCloseAllMenus.bind(this));
- }
-
- /**
- * Unsubscribe from the close menu action.
- */
- componentWillUnmount() {
- this.unsubscribeClose();
- }
-
- /**
- * Class name for line number div.
- *
- * @returns {String} The class name.
- */
- divClassName() {
- return this.state.menu ? `${BEM_BASE} ${BEM_BASE}-is-selected` : BEM_BASE;
- }
-
- /**
- * Handle click on the line number.
- */
- handleClick() {
- // Provide menu for _id because it's top-level, but not for any potential children.
- if (this.props.element.isParentEditable()) {
- Actions.closeAllMenus(this);
- this.setState({menu: !this.state.menu});
- }
- }
-
- /**
- * Handle key press for enter on the line number.
- *
- * @param {Object} event The DOM event
- */
- handleKeyPress(event) {
- if (event.key === 'Enter' && this.props.element.isParentEditable()) {
- Actions.closeAllMenus(this);
- this.setState({menu: !this.state.menu});
- }
- }
-
- /**
- * Handle clicking outside the element.
- */
- handleClickOutside() {
- this.setState({ menu: false });
- }
-
- /**
- * When clicking on a hotspot we append or remove on the parent.
- */
- handleAddFieldClick() {
- this.props.element.next();
- this.setState({ menu: false });
- }
-
- /**
- * When clicking on an expandable element to append a child.
- */
- handleAddChildClick() {
- this.props.element.insertPlaceholder();
- this.setState({ menu: false });
- }
-
- /**
- * Handle the close all menus action.
- *
- * @param {React.Component} component - The component that called the action.
- */
- handleCloseAllMenus(component) {
- if (component !== this) {
- this.setState({ menu: false });
- }
- }
-
-
- /**
- * Is the current element an object?
- *
- * @returns {Boolean} If the element is an object.
- */
- isElementObject() {
- return this.props.element.currentType === 'Object';
- }
-
- /**
- * Is the current element an array?
- *
- * @returns {Boolean} If the element is an array.
- */
- isElementArray() {
- return this.props.element.currentType === 'Array';
- }
-
- /**
- * Is the parent of this element an array?
- *
- * @returns {Boolean} If the parent element is an array.
- */
- isParentArray() {
- return !this.props.element.parent.isRoot() &&
- this.props.element.parent.currentType === 'Array';
- }
-
- /**
- * Class name for the menu.
- *
- * @returns {String} The class name.
- */
- menuClassName() {
- return this.state.menu ?
- `${MENU_CLASS} ${MENU_CLASS}-is-visible dropdown-menu` : `${MENU_CLASS} dropdown-menu`;
- }
-
- /**
- * Render an array menu item.
- *
- * @returns {React.Component} The component.
- */
- renderArrayItem() {
- if (this.isElementArray() && this.props.element.isValueEditable()) {
- return this.renderMenuItem(
- ADD_CHILD_ICON,
- ARRAY_TEXT,
- this.handleAddChildClick.bind(this),
- 'add-element-to-array'
- );
- }
- }
-
- /**
- * Render the default menu item.
- *
- * @returns {React.Component} The component.
- */
- renderDefaultItem() {
- const text = this.isParentArray() ? ARRAY_ELEMENT_TEXT : DEFAULT_TEXT;
- return this.renderMenuItem(
- ADD_FIELD_ICON,
- text,
- this.handleAddFieldClick.bind(this),
- 'add-field-after'
- );
- }
-
- /**
- * Render the value of the element.
- *
- * @returns {React.Component} The value component.
- */
- renderValue() {
- const component = getComponent(this.props.element.currentType);
- return React.createElement(
- component,
- { type: this.props.element.currentType, value: this.props.element.currentValue }
- );
- }
-
- /**
- * Render the identifier in the menu. For objects and arrays in an array,
- * this is the type, because the type is already part of the message. For other
- * values inside arrays, it's the actual value. Otherwise it's the key.
- *
- * @returns {String} The field name or value if an array element.
- */
- renderIdentifier() {
- // this case is already handled in renderDefaultItem()
- if (this.isParentArray() && (this.isElementObject() || this.isElementArray())) {
- return this.props.element.currentType;
- }
- return this.props.element.currentKey || this.renderValue();
- }
-
- /**
- * Render a single menu item.
- *
- * @param {String} iconClassName - The icon class name.
- * @param {String} text - The text.
- * @param {Function} handler - The click handler.
- * @param {String} testId - The test id.
- *
- * @returns {Component} the menu item component
- */
- renderMenuItem(iconClassName, text, handler, testId) {
- return (
-
-
-
- {text}
- {this.renderIdentifier()}
-
-
- );
- }
-
- /**
- * Render an object menu item.
- *
- * @returns {React.Component} The component.
- */
- renderObjectItem() {
- if (this.isElementObject() && this.props.element.isValueEditable()) {
- return this.renderMenuItem(
- ADD_CHILD_ICON,
- OBJECT_TEXT,
- this.handleAddChildClick.bind(this),
- 'add-child-to-object'
- );
- }
- }
-
- /**
- * Render the menu.
- *
- * @returns {React.Component} The menu.
- */
- renderMenu() {
- return (
-
- {this.renderObjectItem()}
- {this.renderArrayItem()}
- {this.renderDefaultItem()}
-
- );
- }
-
- /**
- * Render the line number.
- *
- * @returns {React.Component} The component.
- */
- render() {
- return (
-
- {this.renderMenu()}
-
- );
- }
-}
-
-LineNumber.displayName = 'LineNumber';
-
-LineNumber.propTypes = {
- element: PropTypes.object.isRequired
-};
-
-module.exports = outsideClickable(LineNumber);
diff --git a/src/internal-packages/crud/lib/component/no-action.jsx b/src/internal-packages/crud/lib/component/no-action.jsx
deleted file mode 100644
index 377a31a7207..00000000000
--- a/src/internal-packages/crud/lib/component/no-action.jsx
+++ /dev/null
@@ -1,27 +0,0 @@
-const React = require('react');
-
-/**
- * The actions class.
- */
-const ACTIONS = 'editable-element-actions';
-
-/**
- * General element action component.
- */
-class NoAction extends React.Component {
-
- /**
- * Render a single editable key.
- *
- * @returns {React.Component} The element component.
- */
- render() {
- return (
-
- );
- }
-}
-
-NoAction.displayName = 'NoAction';
-
-module.exports = NoAction;
diff --git a/src/internal-packages/crud/lib/component/readonly-document.jsx b/src/internal-packages/crud/lib/component/readonly-document.jsx
deleted file mode 100644
index dc0e57620c6..00000000000
--- a/src/internal-packages/crud/lib/component/readonly-document.jsx
+++ /dev/null
@@ -1,147 +0,0 @@
-const React = require('react');
-const PropTypes = require('prop-types');
-const HadronDocument = require('hadron-document');
-const Element = require('./element');
-
-/**
- * The arrow up class.
- */
-const ARROW_UP = 'fa fa-arrow-up';
-
-/**
- * The arrow down class.
- */
-const ARROW_DOWN = 'fa fa-arrow-down';
-
-/**
- * The base class.
- */
-const BASE = 'document';
-
-/**
- * The elements class.
- */
-const ELEMENTS = `${BASE}-elements`;
-
-/**
- * The field limit.
- */
-const FIELD_LIMIT = 30;
-
-/**
- * The expander class.
- */
-const EXPANDER = 'btn btn-default btn-xs';
-
-/**
- * The test id.
- */
-const TEST_ID = 'readonly-document';
-
-/**
- * Component for a single readonly document in a list of documents.
- */
-class ReadonlyDocument extends React.Component {
-
- /**
- * Initialize the readonly document.
- *
- * @param {Object} props - The properties.
- */
- constructor(props) {
- super(props);
- this.doc = new HadronDocument(props.doc);
- this.state = { expanded: false };
- }
-
- /**
- * Handle clicking the expand button.
- */
- handleExpandClick() {
- this.setState({ expanded: !this.state.expanded });
- }
-
- /**
- * Get the elements for the document.
- *
- * @returns {Array} The elements.
- */
- renderElements() {
- const components = [];
- let index = 0;
- for (const element of this.doc.elements) {
- components.push((
-
- ));
- index++;
- }
- return components;
- }
-
- /**
- * Render the expander bar.
- *
- * @returns {React.Component} The expander bar.
- */
- renderExpansion() {
- if (this.doc.elements.size >= FIELD_LIMIT) {
- return (
-
- );
- }
- }
-
- /**
- * Render the expansion text.
- *
- * @returns {String} The text.
- */
- renderExpansionText() {
- const extraFields = this.doc.elements.size - FIELD_LIMIT;
- if (this.state.expanded) {
- return `Hide ${extraFields} fields`;
- }
- return `Show ${extraFields} more fields`;
- }
-
- /**
- * Render the style for the expansion icon.
- *
- * @returns {String} The style.
- */
- renderIconStyle() {
- return this.state.expanded ? ARROW_UP : ARROW_DOWN;
- }
-
- /**
- * Render a single document list item.
- *
- * @returns {React.Component} The component.
- */
- render() {
- return (
-
-
- {this.renderElements()}
- {this.renderExpansion()}
-
-
- );
- }
-}
-
-ReadonlyDocument.displayName = 'ReadonlyDocument';
-
-ReadonlyDocument.propTypes = {
- doc: PropTypes.object.isRequired,
- expandAll: PropTypes.bool
-};
-
-module.exports = ReadonlyDocument;
diff --git a/src/internal-packages/crud/lib/component/remove-action.jsx b/src/internal-packages/crud/lib/component/remove-action.jsx
deleted file mode 100644
index 3798eb0d9d4..00000000000
--- a/src/internal-packages/crud/lib/component/remove-action.jsx
+++ /dev/null
@@ -1,51 +0,0 @@
-const React = require('react');
-const PropTypes = require('prop-types');
-
-/**
- * The actions class.
- */
-const ACTIONS = 'editable-element-actions';
-
-/**
- * General element action component.
- */
-class RemoveAction extends React.Component {
-
- /**
- * The component constructor.
- *
- * @param {Object} props - The properties.
- */
- constructor(props) {
- super(props);
- this.element = props.element;
- }
-
- /**
- * Remove the change.
- */
- handleClick() {
- this.element.remove();
- }
-
- /**
- * Render a single editable key.
- *
- * @returns {React.Component} The element component.
- */
- render() {
- return (
-
-
-
- );
- }
-}
-
-RemoveAction.displayName = 'RemoveAction';
-
-RemoveAction.propTypes = {
- element: PropTypes.object.isRequired
-};
-
-module.exports = RemoveAction;
diff --git a/src/internal-packages/crud/lib/component/remove-document-footer.jsx b/src/internal-packages/crud/lib/component/remove-document-footer.jsx
deleted file mode 100644
index 5e195f7ecb1..00000000000
--- a/src/internal-packages/crud/lib/component/remove-document-footer.jsx
+++ /dev/null
@@ -1,163 +0,0 @@
-const React = require('react');
-const PropTypes = require('prop-types');
-const { TextButton } = require('hadron-react-buttons');
-
-/**
- * The progress mode.
- */
-const PROGRESS = 'Progress';
-
-/**
- * The error mode.
- */
-const ERROR = 'Error';
-
-/**
- * The editing mode.
- */
-const DELETING = 'Deleting';
-
-/**
- * Map of modes to styles.
- */
-const MODES = {
- 'Progress': 'is-in-progress',
- 'Success': 'is-success',
- 'Error': 'is-error',
- 'Deleting': 'is-error'
-};
-
-/**
- * The modified message.
- */
-const MODIFIED = 'Document Flagged For Deletion.';
-
-/**
- * The updating message.
- */
-const UPDATING = 'Deleting Document.';
-
-/**
- * The updated message.
- */
-const UPDATED = 'Document Deleted.';
-
-/**
- * Component for a the remove document footer.
- */
-class RemoveDocumentFooter extends React.Component {
-
- /**
- * The component constructor.
- *
- * @param {Object} props - The properties.
- */
- constructor(props) {
- super(props);
- this.doc = props.doc;
- this.actions = props.actions;
- this.removeStore = props.removeStore;
- this.state = { mode: DELETING, message: MODIFIED };
- }
-
- /**
- * Subscribe to the remove store on mount.
- */
- componentDidMount() {
- this.unsubscribeRemove = this.removeStore.listen(this.handleStoreRemove.bind(this));
- }
-
- /**
- * Unsubscribe from the remove store on unmount.
- */
- componentWillUnmount() {
- this.unsubscribeRemove();
- }
-
- /**
- * Handle an error with the document update.
- *
- * @param {Error} error - The error.
- */
- handleError(error) {
- this.setState({ mode: ERROR, message: error.message });
- }
-
- /**
- * Handle the user clicking the update button.
- */
- handleRemove() {
- this.setState({ mode: PROGRESS, message: UPDATING });
- this.actions.remove(this.doc);
- }
-
- /**
- * Handle a successful document update.
- */
- handleSuccess() {
- this.setState({ mode: DELETING, message: UPDATED });
- }
-
- /**
- * Handles a trigger from the store.
- *
- * @param {Boolean} success - If the delete succeeded.
- * @param {Object} object - The error or document.
- */
- handleStoreRemove(success, object) {
- if (success) {
- this.handleSuccess();
- } else {
- this.handleError(object);
- }
- }
-
- /**
- * Get the style of the footer based on the current mode.
- *
- * @returns {String} The style.
- */
- style() {
- return `document-footer document-footer-${MODES[this.state.mode]}`;
- }
-
- /**
- * Render the footer.
- *
- * @returns {Component} The footer component.
- */
- render() {
- return (
-
-
- {this.state.message}
-
-
-
-
-
-
- );
- }
-}
-
-RemoveDocumentFooter.displayName = 'RemoveDocumentFooter';
-
-RemoveDocumentFooter.propTypes = {
- doc: PropTypes.object.isRequired,
- actions: PropTypes.object.isRequired,
- removeStore: PropTypes.object.isRequired,
- cancelHandler: PropTypes.func.isRequired
-};
-
-module.exports = RemoveDocumentFooter;
diff --git a/src/internal-packages/crud/lib/component/revert-action.jsx b/src/internal-packages/crud/lib/component/revert-action.jsx
deleted file mode 100644
index 83300d9bf84..00000000000
--- a/src/internal-packages/crud/lib/component/revert-action.jsx
+++ /dev/null
@@ -1,51 +0,0 @@
-const React = require('react');
-const PropTypes = require('prop-types');
-
-/**
- * The actions class.
- */
-const ACTIONS = 'editable-element-actions';
-
-/**
- * General element action component.
- */
-class RevertAction extends React.Component {
-
- /**
- * The component constructor.
- *
- * @param {Object} props - The properties.
- */
- constructor(props) {
- super(props);
- this.element = props.element;
- }
-
- /**
- * Revert the change.
- */
- handleClick() {
- this.element.revert();
- }
-
- /**
- * Render a single editable key.
- *
- * @returns {React.Component} The element component.
- */
- render() {
- return (
-
-
-
- );
- }
-}
-
-RevertAction.displayName = 'RevertAction';
-
-RevertAction.propTypes = {
- element: PropTypes.object.isRequired
-};
-
-module.exports = RevertAction;
diff --git a/src/internal-packages/crud/lib/component/types.jsx b/src/internal-packages/crud/lib/component/types.jsx
deleted file mode 100644
index 2c72c215e53..00000000000
--- a/src/internal-packages/crud/lib/component/types.jsx
+++ /dev/null
@@ -1,174 +0,0 @@
-const _ = require('lodash');
-const app = require('hadron-app');
-const React = require('react');
-const PropTypes = require('prop-types');
-const TypeChecker = require('hadron-type-checker');
-const { DateEditor } = require('./editor');
-
-require('bootstrap/js/dropdown');
-
-/**
- * Object constant.
- */
-const OBJECT = 'Object';
-
-/**
- * Array constant.
- */
-const ARRAY = 'Array';
-
-/**
- * The version at which high precision values are available.
- */
-const HP_VERSION = '3.4.0';
-
-/**
- * General types component.
- */
-class Types extends React.Component {
-
- /**
- * The component constructor.
- *
- * @param {Object} props - The properties.
- */
- constructor(props) {
- super(props);
- this.state = { isOpen: false };
- this.element = props.element;
- this._version = app.instance.build.version;
- }
-
- /**
- * Get the class name for the dropdown.
- *
- * @returns {String} The class name.
- */
- getClassName() {
- let className = 'editable-element-types dropdown';
- if (this.element.currentType !== this.element.type) {
- className = `${className} editable-element-types-is-edited`;
- }
- return this.state.isOpen ? `${className}` : `${className} closed`;
- }
-
- /**
- * Get the castable value for this value.
- *
- * @returns {Object} The cast value.
- */
- castableValue() {
- return this.element.generateObject();
- }
-
- /**
- * Handles a change in the type.
- *
- * @param {Event} evt - The event.
- */
- handleTypeChange(evt) {
- const newType = evt.target.innerText;
- if (newType === OBJECT) {
- this.element.edit('{');
- this.element.next();
- } else if (newType === ARRAY) {
- this.element.edit('[');
- this.element.next();
- } else {
- try {
- if (newType === 'Date') {
- const editor = new DateEditor(this.element);
- editor.edit(this.castableValue());
- editor.complete();
- } else {
- const value = TypeChecker.cast(this.castableValue(), newType);
- this.element.edit(value);
- }
- } catch (e) {
- this.element.setInvalid(this.element.currentValue, newType, e.message);
- }
- }
- }
-
- /**
- * Are high precision values available?
- *
- * @returns {boolean} if high precision values are available.
- */
- isHighPrecision() {
- return this._version >= HP_VERSION;
- }
-
- /**
- * Is the type changeable?
- *
- * @returns {Boolean} If the type is changeable.
- */
- isTypeChangeable() {
- return this.element.isValueEditable() || this.element.isAdded();
- }
-
- removeOpenClass() {
- this.setState({ isOpen: !this.state.isOpen });
- }
-
- /**
- * Render the type list dropdown.
- *
- * @returns {Component} The react component.
- */
- renderDropdown() {
- return (
-
-
-
-
- );
- }
-
- /**
- * Render the types
- *
- * @returns {Component} The react component.
- */
- renderTypes() {
- return _.map(TypeChecker.castableTypes(this.isHighPrecision()), (type) => {
- return (
-
- {type}
-
- );
- });
- }
-
- /**
- * Render a type list.
- *
- * @returns {React.Component} The element component.
- */
- render() {
- return this.renderDropdown();
- }
-}
-
-Types.displayName = 'Types';
-
-Types.propTypes = {
- element: PropTypes.object.isRequired
-};
-
-module.exports = Types;
diff --git a/src/internal-packages/crud/lib/component/utils.js b/src/internal-packages/crud/lib/component/utils.js
deleted file mode 100644
index b3eed393d4e..00000000000
--- a/src/internal-packages/crud/lib/component/utils.js
+++ /dev/null
@@ -1,13 +0,0 @@
-/**
- * Get the size for the string value.
- *
- * @param {Object} value - The value.
- *
- * @return {Number} The size.
- */
-const size = (value) => {
- const length = String(value).length;
- return length === 0 ? 1 : length;
-};
-
-module.exports = size;
diff --git a/src/internal-packages/crud/lib/store/insert-document-store.js b/src/internal-packages/crud/lib/store/insert-document-store.js
deleted file mode 100644
index 9c63bbfaf65..00000000000
--- a/src/internal-packages/crud/lib/store/insert-document-store.js
+++ /dev/null
@@ -1,59 +0,0 @@
-const Reflux = require('reflux');
-const app = require('hadron-app');
-const toNS = require('mongodb-ns');
-const Actions = require('../actions');
-
-/**
- * The reflux store for inserting documents.
- */
-const InsertDocumentStore = Reflux.createStore({
-
- /**
- * Initialize the insert document list store.
- */
- init: function() {
- this.filter = {};
- this.listenToExternalStore('Query.ChangedStore', this.onQueryChanged.bind(this));
- this.listenTo(Actions.insertDocument, this.insertDocument);
- this.NamespaceStore = app.appRegistry.getStore('App.NamespaceStore');
- },
-
- /**
- * Insert the document.
- *
- * @param {Document} doc - The document to insert.
- */
- insertDocument: function(doc) {
- app.dataService.insertOne(this.NamespaceStore.ns, doc, {}, (error) => {
- if (error) {
- return this.trigger(false, error);
- }
- // check if the newly inserted document matches the current filter, by
- // running the same filter but targeted only to the doc's _id.
- const filter = Object.assign({}, this.filter, { _id: doc._id });
- app.dataService.count(this.NamespaceStore.ns, filter, {}, (err, count) => {
- if (err) {
- return this.trigger(false, err);
- }
- // count is either 0 or 1, if 1 then the new doc matches the filter
- if (count > 0) {
- return this.trigger(true, doc);
- }
- Actions.closeInsertDocumentDialog();
- });
- });
- },
-
- /**
- * Fires when the query is changed.
- *
- * @param {Object} state - The query state.
- */
- onQueryChanged: function(state) {
- if (state.ns && toNS(state.ns).collection && state.filter) {
- this.filter = state.filter;
- }
- }
-});
-
-module.exports = InsertDocumentStore;
diff --git a/src/internal-packages/crud/lib/store/load-more-documents-store.js b/src/internal-packages/crud/lib/store/load-more-documents-store.js
deleted file mode 100644
index 12791959d3f..00000000000
--- a/src/internal-packages/crud/lib/store/load-more-documents-store.js
+++ /dev/null
@@ -1,77 +0,0 @@
-const Reflux = require('reflux');
-const app = require('hadron-app');
-const toNS = require('mongodb-ns');
-const Actions = require('../actions');
-const _ = require('lodash');
-
-// const debug = require('debug')('mongodb-compass:crud:load-more-store');
-
-const NUM_PAGE_DOCS = 20;
-/**
- * The reflux store for loading more documents.
- */
-const LoadMoreDocumentsStore = Reflux.createStore({
-
- /**
- * Initialize the reset document list store.
- */
- init: function() {
- this.filter = {};
- this.sort = [[ '_id', 1 ]];
- this.limit = 0;
- this.skip = 0;
- this.project = null;
- this.counter = 0;
-
- this.NamespaceStore = app.appRegistry.getStore('App.NamespaceStore');
- this.listenToExternalStore('Query.ChangedStore', this.onQueryChanged.bind(this));
- this.listenTo(Actions.fetchNextDocuments, this.fetchNextDocuments.bind(this));
- },
-
- /**
- * Fires when the query is changed. Need to copy the latest query details
- * and reset the counter.
- *
- * @param {Object} state - The query state.
- */
- onQueryChanged: function(state) {
- if (state.ns && toNS(state.ns).collection) {
- this.filter = state.filter || {};
- this.sort = _.pairs(state.sort);
- this.limit = state.limit;
- this.skip = state.skip;
- this.project = state.project;
- this.counter = 0;
- }
- },
-
- /**
- * Fetch the next page of documents. Increase the counter by the page size
- * (20 documents) until we reach the user-specified limit. Also take into
- * account user-specified skip.
- *
- * @param {Integer} skip - The number of documents to skip.
- */
- fetchNextDocuments: function(skip) {
- this.counter += NUM_PAGE_DOCS;
- let nextPageCount = 20;
- if (this.limit > 0) {
- nextPageCount = Math.min(Math.max(0, this.limit - this.counter), NUM_PAGE_DOCS);
- if (nextPageCount === 0) {
- return;
- }
- }
- const options = {
- skip: skip + this.skip,
- limit: nextPageCount,
- sort: this.sort,
- fields: this.project,
- promoteValues: false
- };
- app.dataService.find(this.NamespaceStore.ns, this.filter, options, (error, documents) => {
- this.trigger(error, documents);
- });
- }
-});
-
-module.exports = LoadMoreDocumentsStore;
diff --git a/src/internal-packages/crud/lib/store/open-insert-document-dialog-store.js b/src/internal-packages/crud/lib/store/open-insert-document-dialog-store.js
deleted file mode 100644
index ca7618357bd..00000000000
--- a/src/internal-packages/crud/lib/store/open-insert-document-dialog-store.js
+++ /dev/null
@@ -1,46 +0,0 @@
-const ipc = require('hadron-ipc');
-const Reflux = require('reflux');
-const ObjectId = require('bson').ObjectId;
-const Actions = require('../actions');
-const HadronDocument = require('hadron-document');
-
-// const debug = require('debug')('mongodb-compass:crud:store:open-insert-doc');
-
-/**
- * The reflux store for opening the insert document dialog.
- */
-const OpenInsertDocumentDialogStore = Reflux.createStore({
-
- /**
- * Initialize the reset document list store.
- */
- init: function() {
- this.listenTo(Actions.openInsertDocumentDialog, this.openInsertDocumentDialog.bind(this));
- ipc.on('window:menu-open-insert-document-dialog', () => {
- this.openInsertDocumentDialog({ _id: new ObjectId(), '': '' }, false);
- });
- },
-
- /**
- * Open the insert document dialog.
- *
- * @param {Object} doc - The document to open the dialog with.
- * @param {Boolean} clone - If the operation is a clone.
- */
- openInsertDocumentDialog: function(doc, clone) {
- const hadronDoc = new HadronDocument(doc, true);
- if (clone) {
- // We need to remove the _id or we will get an duplicate key error on
- // insert, and we currently do not allow editing of the _id field.
- for (const element of hadronDoc.elements) {
- if (element.currentKey === '_id') {
- hadronDoc.elements.remove(element);
- break;
- }
- }
- }
- this.trigger(hadronDoc);
- }
-});
-
-module.exports = OpenInsertDocumentDialogStore;
diff --git a/src/internal-packages/crud/lib/store/remove-document-store.js b/src/internal-packages/crud/lib/store/remove-document-store.js
deleted file mode 100644
index 7e6ac453351..00000000000
--- a/src/internal-packages/crud/lib/store/remove-document-store.js
+++ /dev/null
@@ -1,26 +0,0 @@
-const Reflux = require('reflux');
-const Actions = require('../actions');
-
-/**
- * The reflux store for removing a document from the list.
- */
-const RemoveDocumentStore = Reflux.createStore({
-
- /**
- * Initialize the reset document list store.
- */
- init: function() {
- this.listenTo(Actions.documentRemoved, this.remove);
- },
-
- /**
- * This function is called when when a document is deleted.
- *
- * @param {Object} id - The document id.
- */
- remove: function(id) {
- this.trigger(id);
- }
-});
-
-module.exports = RemoveDocumentStore;
diff --git a/src/internal-packages/crud/lib/store/reset-document-list-store.js b/src/internal-packages/crud/lib/store/reset-document-list-store.js
deleted file mode 100644
index f4d7d911c84..00000000000
--- a/src/internal-packages/crud/lib/store/reset-document-list-store.js
+++ /dev/null
@@ -1,86 +0,0 @@
-const Reflux = require('reflux');
-const app = require('hadron-app');
-const toNS = require('mongodb-ns');
-const Actions = require('../actions');
-const _ = require('lodash');
-
-// const debug = require('debug')('mongodb-compass:crud:reset-store');
-
-/**
- * The reflux store for resetting the document list.
- */
-const ResetDocumentListStore = Reflux.createStore({
-
- /**
- * Initialize the reset document list store.
- */
- init: function() {
- this.filter = {};
- this.sort = [[ '_id', 1 ]];
- this.limit = 0;
- this.skip = 0;
- this.project = null;
- this.ns = '';
-
- // listen for query changes
- this.listenToExternalStore('Query.ChangedStore', this.onQueryChanged.bind(this));
-
- Actions.refreshDocuments.listen(this.reset.bind(this));
- },
-
- /**
- * Fires when the query is changed.
- *
- * @param {Object} state - The query state.
- */
- onQueryChanged: function(state) {
- if (state.ns && toNS(state.ns).collection) {
- this.filter = state.filter || {};
- this.sort = _.pairs(state.sort);
- this.limit = state.limit;
- this.skip = state.skip;
- this.project = state.project;
- this.ns = state.ns;
- this.reset();
- }
- },
-
- /**
- * This function is called when the collection filter changes.
- *
- * @param {Object} filter - The query filter.
- */
- reset: function() {
- const countOptions = {
- skip: this.skip
- };
-
- const findOptions = {
- sort: this.sort,
- fields: this.project,
- skip: this.skip,
- limit: 20,
- promoteValues: false
- };
-
- // only set limit if it's > 0, read-only views cannot handle 0 limit.
- if (this.limit > 0) {
- countOptions.limit = this.limit;
- findOptions.limit = Math.min(20, this.limit);
- }
-
- app.dataService.count(this.ns, this.filter, countOptions, (err, count) => {
- if (!err) {
- app.dataService.find(this.ns, this.filter, findOptions, (error, documents) => {
- this.trigger(error, documents, count);
- });
- } else {
- // If the count gets an error we need to display this to the user since
- // they have the wrong privs.
- this.trigger(err);
- }
- });
- }
-});
-
-module.exports = ResetDocumentListStore;
diff --git a/src/internal-packages/crud/package.json b/src/internal-packages/crud/package.json
deleted file mode 100644
index 36bfd4d93ff..00000000000
--- a/src/internal-packages/crud/package.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "name": "crud",
- "productName": "Compass CRUD Support",
- "description": "CRUD support for Compass as an internal package.",
- "version": "0.0.1",
- "authors": "MongoDB Inc.",
- "private": true,
- "main": "./index.js"
-}
diff --git a/src/internal-packages/crud/styles/document-actions.less b/src/internal-packages/crud/styles/document-actions.less
deleted file mode 100644
index 28c994ca052..00000000000
--- a/src/internal-packages/crud/styles/document-actions.less
+++ /dev/null
@@ -1,29 +0,0 @@
-.document-actions {
- position: absolute;
- width: 100%;
- top: 15px;
- padding: 0px 20px 0px 20px;
-
- &-button {
- visibility: hidden;
- transition: none;
- z-index: 200;
- position: relative;
- }
-
- &-expand-button {
- padding: 0px 5px 0px 5px;
-
- .fa {
- height: 12px;
- width: 12px;
- }
- }
-
- &-right {
- float: right;
- }
- &-left {
- float: left;
- }
-}
diff --git a/src/internal-packages/crud/styles/document-elements.less b/src/internal-packages/crud/styles/document-elements.less
deleted file mode 100644
index f15b7e9a50c..00000000000
--- a/src/internal-packages/crud/styles/document-elements.less
+++ /dev/null
@@ -1,53 +0,0 @@
-.document-elements {
-
- counter-reset: document-line-number;
- display: block;
- list-style: none;
- text-overflow: ellipsis;
- white-space: nowrap;
- max-width: 100%;
-
- .line-number {
- position: absolute;
- left: 21px;
- }
-
- .editable-element-types-label {
- position: absolute;
- right: 0px;
- display: inline-block;
- width: 120px;
- color: @gray3;
- height: 17px;
- padding-left: 12px;
- }
-
- editable-expandable-element-header:hover {
- background-color: #ebebed !important;
-
- input {
- background-color: #ebebed !important;
- }
-
- .editable-element-actions {
- opacity: 1;
- }
-
- .editable-element-types {
- .btn {
- border-color: #8c8c8c;
- }
- .caret {
- visibility: visible;
- }
-
- &-is-edited {
- .btn {
- color: #000000;
- font-weight: bold;
- }
- }
- }
- }
-}
-
diff --git a/src/internal-packages/crud/styles/document-footer.less b/src/internal-packages/crud/styles/document-footer.less
deleted file mode 100644
index ed4607881aa..00000000000
--- a/src/internal-packages/crud/styles/document-footer.less
+++ /dev/null
@@ -1,107 +0,0 @@
-.document-footer {
- font-family: "Akzidenz", "Helvetica Neue", Helvetica, Arial, sans-serif;
- height: 28px;
- vertical-align: middle;
- top: 20px;
- position: relative;
-
- &-message {
- position: absolute;
- right: 150px;
- left: 10px;
- font-size: 14px;
- font-style: italic;
- padding-left: 10px;
- padding-top: 4px;
- color: @pw;
- overflow: hidden;
- height: 28px;
- }
-
- &-is-modified {
- background-color: @alertOrange;
-
- .document-footer-actions {
-
- .cancel {
- color: @alertOrangeBorder;
- }
-
- .btn-default {
- color: @alertOrangeBorder;
- border-color: @alertOrangeBorder;
- background: none;
- box-shadow: inset 0 -1px 0 0 @alertOrangeBorder;
- transition: none;
- }
- }
- }
-
- &-is-in-progress {
- background-color: @chart1;
- }
-
- &-is-success {
- background-color: @green2;
-
- .document-footer-actions {
-
- .cancel {
- color: white;
- }
-
- .btn-default {
- color: white;
- border-color: white;
- background: none;
- box-shadow: inset 0 -1px 0 0 white;
- transition: none;
- }
- }
-
- }
-
- &-is-error {
- background-color: @alertRed;
-
- .document-footer-actions {
-
- .cancel {
- color: @alertRedBg;
- }
-
- .error {
- color: @pw;
- background: rgba(255,255,255,0.2);
- border: 1px solid rgba(255,255,255,0.4);
-
- &:hover {
- background: rgba(255,255,255,0.4);
- border: 1px solid rgba(255,255,255,0.6);
- }
- }
- }
- }
-
- &-is-viewing {
- background-color: #F8F8F8;
-
- .document-footer-actions {
-
- .cancel {
- color: #B8B8B8;
- }
- }
- }
-
- &-actions {
- position: absolute;
- right: 10px;
- top: 2px;
- padding-top: 1px;
-
- .cancel {
- font-weight: bold;
- }
- }
-}
diff --git a/src/internal-packages/crud/styles/document-list.less b/src/internal-packages/crud/styles/document-list.less
deleted file mode 100644
index f012438f5a9..00000000000
--- a/src/internal-packages/crud/styles/document-list.less
+++ /dev/null
@@ -1,19 +0,0 @@
-.document-list {
- .list-unstyled;
- padding-top: 0;
- padding-bottom: 10px;
- position: relative;
-
- &-item {
- position: relative;
- font-family: @font-family-monospace;
- font-size: 11px;
- margin-bottom: 5px;
- background: @pw;
-
- &:last-child {
- margin-bottom: 0;
- border-bottom: 0 solid transparent;
- }
- }
-}
diff --git a/src/internal-packages/crud/styles/document.less b/src/internal-packages/crud/styles/document.less
deleted file mode 100644
index 0aada2aff0a..00000000000
--- a/src/internal-packages/crud/styles/document.less
+++ /dev/null
@@ -1,31 +0,0 @@
-.document {
- font-family: @font-family-monospace;
- font-size: 11px;
- list-style: none;
- text-overflow: ellipsis;
- white-space: nowrap;
- max-width: 100%;
- padding-top: 20px;
- padding-bottom: 20px;
-
- &-elements {
- position: relative;
-
- .btn {
- margin: 10px 0px 0px 22px;
-
- i {
- margin-right: 5px;
- }
- }
- }
-
- &-is-deleting {
- box-shadow: 2px 5px 8px rgba(0, 0, 0, 0.2);
- border: 1px solid @alertRed;
- }
-
- &-is-editing {
- box-shadow: 2px 5px 8px rgba(0, 0, 0, 0.2);
- }
-}
diff --git a/src/internal-packages/crud/styles/editable-element-field.less b/src/internal-packages/crud/styles/editable-element-field.less
deleted file mode 100644
index 331cf845cd8..00000000000
--- a/src/internal-packages/crud/styles/editable-element-field.less
+++ /dev/null
@@ -1,23 +0,0 @@
-.editable-element-field {
- font-weight: bold;
- border: none;
- padding-left: 1px;
- -webkit-user-select: text;
- max-width: 15vw;
- text-overflow: ellipsis;
- white-space: nowrap;
- overflow: hidden;
-
- &-is-editing {
- border: 1px solid @gray3;
- box-shadow: 0px 2px 4px 0px rgba(0,0,0,0.2);
- z-index: 10;
- margin-top: -1px;
- margin-bottom: -1px;
- }
-
- &-is-duplicate {
- border: 1px solid red;
- color: red;
- }
-}
diff --git a/src/internal-packages/crud/styles/editable-element-value.less b/src/internal-packages/crud/styles/editable-element-value.less
deleted file mode 100644
index b14766d21ce..00000000000
--- a/src/internal-packages/crud/styles/editable-element-value.less
+++ /dev/null
@@ -1,94 +0,0 @@
-.editable-element-value {
- display: inline-block;
- border: none;
- padding-left: 1px;
- text-overflow: ellipsis;
- white-space: nowrap;
- overflow: hidden;
- max-width: ~"calc(85vw - 260px);";
-
- &-tooltip {
- height: 20px !important;
- font-size: 11px !important;
- opacity: 1 !important;
- padding: 3px 6px !important;
- }
-
- &-is-string {
- white-space: pre-line;
- word-break: break-all;
- padding-right: 0px;
- }
-
- &-is-int32 {
- color: #145a32;
- }
-
- &-is-int64 {
- color: #196f3d;
- }
-
- &-is-double {
- color: #1e8449;
- }
-
- &-is-decimal128 {
- color: #229954;
- }
-
- &-is-date {
- color: firebrick;
- }
-
- &-is-boolean {
- color: purple;
- }
-
- &-is-objectid {
- color: orangered;
- &::before {
- content: "ObjectID('";
- }
- &::after {
- content: "')";
- }
- }
-
- &-is-editing {
- border: 1px solid @gray3;
- box-shadow: 0px 2px 4px 0px rgba(0,0,0,0.2);
- z-index: 10;
- margin-top: -1px;
- margin-bottom: -1px;
- }
-
- &-is-invalid-type {
- background-color: #F88379 !important;
- color: #FFFFFF !important;
- }
-
- &-wrapper {
- flex-grow: 3;
- z-index: 100;
-
- &-is-string {
- color: steelblue;
- &::before {
- content: "\"";
- }
- &::after {
- content: "\"";
- }
- }
-
- &-is-objectid {
- color: orangered;
- &::before {
- content: "ObjectID('";
- }
- &::after {
- content: "')";
- }
- }
- }
-}
diff --git a/src/internal-packages/crud/styles/editable-element.less b/src/internal-packages/crud/styles/editable-element.less
deleted file mode 100644
index b2253d1d028..00000000000
--- a/src/internal-packages/crud/styles/editable-element.less
+++ /dev/null
@@ -1,299 +0,0 @@
-.editable-element {
- width: 100%;
- display: flex;
- flex-direction: row;
- flex-wrap: nowrap;
- align-items: center;
-
- &-field {
- display: inline-block;
- vertical-align: top;
- margin-left: 22px;
- }
-
- &-expand-button {
- position: absolute;
- padding: 2px 6px 0px 5px;
- }
-
- &-separator {
- padding-right: 2px;
- vertical-align: top;
- }
-
- &-is-editing {
-
- .line-number:focus {
- outline: 0;
- color: #494747;
- font-weight: bold;
- border: 1px solid #494747;
- border-radius: 2px;
-
- &:before {
- content: '+';
- }
-
- &-is-selected {
- &:before {
- content: '-';
- }
- }
- }
-
- &:hover {
- background-color: @gray8;
-
- &::before {
- background-color: @gray8;
- }
-
- input {
- background-color: @gray8;
-
- &:focus {
- background-color: @pw;
- }
- }
-
- .line-number {
- color: #494747;
- font-weight: bold;
- border: 1px solid #494747;
- border-radius: 2px;
-
- &:before {
- content: '+';
- }
-
- &-is-selected {
- &:before {
- content: '-';
- }
- }
- }
-
- .editable-element-actions {
- opacity: 1;
- }
-
- .editable-element-types {
- .btn {
- background-color: @gray6;
- color: @gray0;
- }
- .caret {
- visibility: visible;
- }
-
- &-is-edited {
- .btn {
- font-weight: bold;
- color: #000000;
- }
- }
- }
- }
- }
-
- &-is-edited {
- background-color: @alertOrangeBg;
-
- &:hover {
- .line-number {
- color: @pw;
- border: 1px solid @pw;
-
- &-is-selected {
- border: 1px solid @pw;
- }
- }
- }
-
- .line-number {
- background-color: @alertOrange;
- color: @pw;
- border: 1px solid @pw;
-
- &-is-selected {
- border: 1px solid @pw;
- }
- }
-
- input {
- background-color: @alertOrangeBg;
- }
-
- .editable-element-field {
- background-color: @alertOrangeBg;
-
- &:focus {
- background-color: @pw;
- }
-
- &::before {
- background-color: @alertOrangeBg;
- }
- }
- }
-
- &-is-added {
- background-color: @greenBg;
-
- .editable-element-field {
- background-color: @greenBg;
-
- &:focus {
- background-color: @pw;
- }
- }
-
- &:hover {
- .line-number {
- color: @pw;
- border: 1px solid @pw;
-
- &-is-selected {
- border: 1px solid @pw;
- }
- }
- }
-
- .line-number {
- background-color: @green2;
- color: @pw;
- border: 1px solid @pw;
-
- &-is-selected {
- border: 1px solid @pw;
- }
- }
-
- input {
- background-color: @greenBg;
- }
- }
-
- &-is-removed {
- background-color: @alertRedBg;
-
- .editable-element-field {
- background-color: @alertRedBg;
-
- &:focus {
- background-color: @pw;
- }
- }
-
- &:hover {
- .line-number {
- color: @pw;
- border: 1px solid @pw;
-
- &-is-selected {
- border: 1px solid @pw;
- }
- }
- }
-
- .line-number {
- background-color: @alertRed;
- color: @pw;
- border: 1px solid @pw;
-
- &-is-selected {
- border: 1px solid @pw;
- }
- }
-
- input {
- background-color: @alertRedBg;
- }
- }
-
- &-actions {
- display: inline-block;
- opacity: 0;
- width: 18px;
- font-size: 13px;
- line-height: 11px;
- margin-top: 1px;
- text-align: center;
- color: @gray3;
- position: absolute;
- left: 3px;
-
- i:hover {
- cursor: pointer;
- }
- }
-
- &-types {
- display: inline-block;
- width: 120px;
- color: @gray3;
- height: 17px;
- flex-shrink: 0;
-
- .closed > .dropdown-menu {
- display: none;
- }
-
- .type-label {
- padding: 1px 12px;
- }
-
- .btn {
- background-color: transparent;
- color: @gray4;
- border: none;
- text-transform: none;
- font-size: 11px;
- border-radius: 8px;
- padding: 1px 12px;
- }
-
- .caret {
- visibility: hidden;
- }
-
- &-is-edited {
- .btn {
- color: #000000;
- font-weight: bold;
- }
- }
-
- .dropdown-menu {
- min-width: 120px;
-
- li {
- span {
- display: block;
- padding: 3px 20px;
- clear: both;
- font-weight: normal;
- font-size: 11px;
- color: #333333;
- white-space: nowrap;
- }
- span:hover {
- color: #313030;
- text-decoration: none;
- background: #e6e6e6;
- }
- }
- }
- }
-
- &-value {
- position: relative;
- vertical-align: top;
- z-index: 1;
- }
-
- &-field {
- position: relative;
- z-index: 1;
- }
-}
diff --git a/src/internal-packages/crud/styles/editable-expandable-element.less b/src/internal-packages/crud/styles/editable-expandable-element.less
deleted file mode 100644
index 0f4dc630906..00000000000
--- a/src/internal-packages/crud/styles/editable-expandable-element.less
+++ /dev/null
@@ -1,225 +0,0 @@
-.editable-expandable-element {
- width: 100%;
- display: block;
- font-size: 11px;
-
- &-is-edited {
- background-color: @alertOrangeBg;
-
- .line-number {
- background-color: @alertOrange;
- color: @pw;
-
- &-is-selected {
- border: 1px solid @pw;
- border-radius: 2px;
- }
- }
-
- input {
- background-color: @alertOrangeBg;
- }
-
- .editable-element-field {
- background-color: @alertOrangeBg;
-
- &:focus {
- background-color: @pw;
- }
-
- &::before {
- background-color: @alertOrangeBg;
- }
- }
- }
-
- &-is-added {
- background-color: @greenBg;
-
- .editable-element-field {
- background-color: @greenBg;
-
- &:focus {
- background-color: @pw;
- }
- }
-
- .line-number {
- background-color: @green2;
- color: @pw;
-
- &-is-selected {
- border: 1px solid @pw;
- border-radius: 2px;
- }
- }
-
- input {
- background-color: @greenBg;
- }
- }
-
- &-is-removed {
- background-color: @alertRedBg;
-
- .editable-element-field {
- background-color: @alertRedBg;
-
- &:focus {
- background-color: @pw;
- }
- }
-
- .line-number {
- background-color: @alertRed;
- color: @pw;
-
- &-is-selected {
- border: 1px solid @pw;
- border-radius: 2px;
- }
- }
-
- input {
- background-color: @alertRedBg;
- }
- }
-
- &-header {
- display: flex;
- flex-direction: row;
- flex-wrap: nowrap;
- align-items: center;
- cursor: pointer;
-
- &-label {
- display: inline-block;
- flex-grow: 3;
- }
-
- &-is-editing {
-
- .line-number:focus {
- outline: 0;
- color: #494747;
- font-weight: bold;
- border: 1px solid #494747;
- border-radius: 2px;
-
- &:before {
- content: '+';
- }
-
- &-is-selected {
- &:before {
- content: '-';
- }
- }
- }
-
- &:hover {
- background-color: @gray8;
-
- &::before {
- background-color: @gray8;
- }
-
- .line-number {
- color: #494747;
- font-weight: bold;
- border: 1px solid #494747;
- border-radius: 2px;
-
- &:before {
- content: '+';
- }
-
- &-is-selected {
- &:before {
- content: '-';
- }
- }
- }
-
- input {
- background-color: @gray8;
-
- &:focus {
- background-color: @pw;
- }
- }
-
- .editable-element-actions {
- opacity: 1;
- }
-
- .editable-element-types {
- .btn {
- background-color: @gray6;
- color: @gray0;
- }
- .caret {
- visibility: visible;
- }
- &-is-edited {
- .btn {
- color: #000000;
- font-weight: bold;
- }
- }
- }
- }
- }
-
- &-is-edited {
-
- &:hover {
- .line-number {
- color: @pw;
- border: 1px solid @pw;
-
- &-is-selected {
- border: 1px solid @pw;
- }
- }
- }
- }
-
- &-is-added {
-
- &:hover {
- .line-number {
- color: @pw;
- border: 1px solid @pw;
-
- &-is-selected {
- border: 1px solid @pw;
- }
- }
- }
- }
-
- &-is-removed {
-
- &:hover {
- .line-number {
- color: @pw;
- border: 1px solid @pw;
-
- &-is-selected {
- border: 1px solid @pw;
- }
- }
- }
- }
- }
-
- &-children {
- display: none;
- padding-left: 0px;
-
- &-is-expanded {
- display: block;
- }
- }
-}
diff --git a/src/internal-packages/crud/styles/element.less b/src/internal-packages/crud/styles/element.less
deleted file mode 100644
index 0df383230bf..00000000000
--- a/src/internal-packages/crud/styles/element.less
+++ /dev/null
@@ -1,66 +0,0 @@
-.element {
-
- width: 100%;
- display: block;
- font-size: 11px;
-
- &-field {
- display: inline-block;
- font-weight: bold;
- vertical-align: top;
- -webkit-user-select: text;
- }
-
- &-separator {
- padding-right: 2px;
- vertical-align: top;
- -webkit-user-select: text;
- }
-
- &-value {
- display: inline-block;
- vertical-align: top;
- -webkit-user-select: text;
- flex-grow: 3;
-
- &-is-string {
- color: steelblue;
- white-space: pre-line;
- word-break: break-all;
- }
-
- &-is-int32 {
- color: #145a32;
- }
-
- &-is-int64 {
- color: #196f3d;
- }
-
- &-is-double {
- color: #1e8449;
- }
-
- &-is-decimal128 {
- color: #229954;
- }
-
- &-is-date {
- color: firebrick;
- }
-
- &-is-boolean {
- color: purple;
- }
-
- &-is-objectid {
- color: orangered;
- &::before {
- content: "ObjectID('";
- }
- &::after {
- content: "')";
- }
- }
- }
-}
diff --git a/src/internal-packages/crud/styles/expandable-element.less b/src/internal-packages/crud/styles/expandable-element.less
deleted file mode 100644
index 6ec6c0b8d66..00000000000
--- a/src/internal-packages/crud/styles/expandable-element.less
+++ /dev/null
@@ -1,52 +0,0 @@
-.expandable-element {
-
- width: 100%;
- display: block;
- font-size: 11px;
-
- &-header {
-
- cursor: pointer;
-
- &-field {
- display: inline-block;
- font-weight: bold;
- }
-
- &-separator {
- padding-right: 2px;
- }
-
- &-label {
- display: inline-block;
- }
-
- &-toggle {
- display: inline-block;
- width: 0;
- height: 0;
- vertical-align: middle;
- border-left: @caret-width-base solid;
- border-right: 0;
- border-top: @caret-width-base solid transparent;
- border-bottom: @caret-width-base solid transparent;
- }
-
- &-is-expanded {
- .expandable-element-header-toggle {
- border-top: @caret-width-base solid;
- border-right: @caret-width-base solid transparent;
- border-left: @caret-width-base solid transparent;
- }
- }
- }
-
- &-children {
- display: none;
- padding-left: 15px;
-
- &-is-expanded {
- display: block;
- }
- }
-}
diff --git a/src/internal-packages/crud/styles/index.less b/src/internal-packages/crud/styles/index.less
deleted file mode 100644
index 58602eec04b..00000000000
--- a/src/internal-packages/crud/styles/index.less
+++ /dev/null
@@ -1,42 +0,0 @@
-@import "./document-list.less";
-@import "./element.less";
-@import "./expandable-element.less";
-@import "./document-actions.less";
-@import "./document.less";
-@import "./document-elements.less";
-@import "./editable-expandable-element.less";
-@import "./editable-element.less";
-@import "./editable-element-field.less";
-@import "./editable-element-value.less";
-@import "./line-number.less";
-@import "./loading-indicator.less";
-@import "./document-footer.less";
-@import "./insert-document-dialog.less";
-
-.expandable-element-header {
-
- &-toggle {
- margin-left: -10px;
- margin-right: 6px;
- }
-
- &-is-expanded {
- .expandable-element-header-toggle {
- margin-left: -14px;
- }
- }
-}
-
-.document {
-
- &:hover {
- .document-actions-button {
- visibility: visible;
- }
- }
-}
-
-.document-actions-button {
- visibility: hidden;
- margin-left: 3px;
-}
diff --git a/src/internal-packages/crud/styles/insert-document-dialog.less b/src/internal-packages/crud/styles/insert-document-dialog.less
deleted file mode 100644
index 5e4746c01fa..00000000000
--- a/src/internal-packages/crud/styles/insert-document-dialog.less
+++ /dev/null
@@ -1,116 +0,0 @@
-.modal-body {
- .document {
- .document-elements {
- width: 100%;
-
- .editable-element-actions {
- display: inline-block;
- opacity: 0;
- width: 18px;
- line-height: 11px;
- margin-right: 35px;
- text-align: center;
- cursor: pointer;
- color: @gray3;
- }
-
- .editable-element-field {
- max-width: 10vw;
- }
-
- .editable-element-value {
- max-width: 20vw;
- }
-
- .editable-element-is-added, .editable-expandable-element-header-is-added {
- background-color: @pw;
-
- input {
- background-color: @pw;
-
- &:focus {
- background-color: @pw;
- }
- }
-
- .line-number {
- background-color: @pw;
- color: @gray3;
- }
- }
-
- .editable-element {
-
- &:hover {
- background-color: @gray8;
-
- &::before {
- background-color: @gray8;
- }
-
- input {
- background-color: @gray8;
-
- &:focus {
- background-color: @pw;
- }
- }
-
- .editable-element-actions {
- opacity: 1;
- }
-
- .editable-element-types {
- .btn {
- background-color: @gray6;
- color: @gray0;
- }
- .caret {
- visibility: visible;
- }
-
- &-is-edited {
- .btn {
- color: #000000;
- font-weight: bold;
- }
- }
- }
- }
- }
-
- .editable-expandable-element-header {
-
- &:hover {
- background-color: @gray8;
-
- &::before {
- background-color: @gray8;
- }
-
- input {
- background-color: @gray8;
-
- &:focus {
- background-color: @pw;
- }
- }
-
- .editable-element-actions {
- opacity: 1;
- }
-
- .editable-element-types {
- .btn {
- background-color: @gray6;
- color: @gray0;
- }
- .caret {
- visibility: visible;
- }
- }
- }
- }
- }
- }
-}
diff --git a/src/internal-packages/crud/styles/line-number.less b/src/internal-packages/crud/styles/line-number.less
deleted file mode 100644
index 5b9b0dd4dda..00000000000
--- a/src/internal-packages/crud/styles/line-number.less
+++ /dev/null
@@ -1,65 +0,0 @@
-.line-number {
-
- display: inline-block;
- color: @gray4;
- width: 18px;
- height: 17px;
- text-align: center;
- cursor: pointer;
-
- &::before {
- counter-increment: document-line-number;
- content: counter(document-line-number);
- }
-
- &-is-selected {
- color: #494747;
- font-weight: bold;
- border: 1px solid #494747;
- border-radius: 2px;
-
- &:before {
- content: '-';
- }
- }
-
- &-menu {
- display: none;
- color: @gray3;
-
- li {
- span {
- display: block;
- padding: 3px 20px;
- clear: both;
- font-weight: normal;
- font-size: 11px;
- color: #333333;
- white-space: nowrap;
-
- .fa-level-down {
- margin-right: 12px;
- }
-
- .fa-plus-square-o {
- margin-right: 10px;
- }
- }
- span:hover {
- color: #313030;
- text-decoration: none;
- background: #e6e6e6;
- }
- }
-
- &-field {
- display: inline-block !important;
- padding: 0px !important;
- font-weight: bold !important;
- }
-
- &-is-visible {
- display: block;
- }
- }
-}
diff --git a/src/internal-packages/crud/styles/loading-indicator.less b/src/internal-packages/crud/styles/loading-indicator.less
deleted file mode 100644
index 92cce6554d1..00000000000
--- a/src/internal-packages/crud/styles/loading-indicator.less
+++ /dev/null
@@ -1,15 +0,0 @@
-.loading-indicator {
- display: none;
- width: 100%;
- text-align: center;
- vertical-align: middle;
-
- &-is-loading {
- display: block;
- }
-
- i {
- font-size: 25px;
- color: #CCCCCC;
- }
-}
diff --git a/test/enzyme/crud.editable-document-component.test.js b/test/enzyme/crud.editable-document-component.test.js
deleted file mode 100644
index e345308b715..00000000000
--- a/test/enzyme/crud.editable-document-component.test.js
+++ /dev/null
@@ -1,70 +0,0 @@
-/* eslint no-unused-vars: 0, no-unused-expressions: 0 */
-const app = require('hadron-app');
-const chai = require('chai');
-const chaiEnzyme = require('chai-enzyme');
-const expect = chai.expect;
-const React = require('react');
-const { mount } = require('enzyme');
-const AppRegistry = require('hadron-app-registry');
-
-const EditableDocument = require('../../src/internal-packages/crud/lib/component/editable-document');
-const EditableElement = require('../../src/internal-packages/crud/lib/component/editable-element');
-
-// use chai-enzyme assertions, see https://github.com/producthunt/chai-enzyme
-chai.use(chaiEnzyme());
-
-describe('', function() {
- let appRegistry = app.appRegistry;
- let appInstance = app.instance;
- beforeEach(() => {
- // Mock the AppRegistry with a new one so tests don't complain about
- // appRegistry.getComponent (i.e. appRegistry being undefined)
- app.appRegistry = new AppRegistry();
- app.instance = {build: {version: '3.2.0'}};
- });
- afterEach(() => {
- // Restore properties on the global app, so they don't affect other tests
- app.appRegistry = appRegistry;
- app.instance = appInstance;
- });
-
- const doc = {a: {b: {c: {d: 1}}}};
- it('if expandAll is true, renders children', () => {
- const component = mount();
- component.setState({
- expandAll: true
- });
- const children = component.find(EditableElement);
- expect(children).to.be.of.length(4);
- });
- context('COMPASS_1306, if expandAll is false', () => {
- it('if expandAll is false, does not render children', () => {
- const component = mount(
-
- );
- component.setState({
- expandAll: false
- });
- const children = component.find(EditableElement);
- expect(children).to.be.of.length(1);
- });
- it('if expandAll is false but expand true, renders another child', () => {
- // Work around https://github.com/airbnb/enzyme/issues/361
- // by mounting the EditableElement rather than the EditableDocument,
- // note this requires the HadronDocument constructor
- const document = EditableDocument.loadDocument(doc);
- for (const element of document.elements) {
- const component = mount(
-
- );
- let children = component.find(EditableElement);
- expect(children).to.be.of.length(1);
- component.setState({
- expanded: true
- });
- children = component.find(EditableElement);
- expect(children).to.be.of.length(2);
- }
- });
- });
-});
diff --git a/test/functional/crud.test.js b/test/functional/crud.test.js
deleted file mode 100644
index 781c5719aaa..00000000000
--- a/test/functional/crud.test.js
+++ /dev/null
@@ -1,156 +0,0 @@
-const Connection = require('mongodb-connection-model');
-const DataService = require('mongodb-data-service');
-const { launchCompass, quitCompass} = require('./support/spectron-support');
-
-/**
- * Global connection model for this test.
- */
-const CONNECTION = new Connection({ hostname: '127.0.0.1', port: 27018, ns: 'music' });
-
-describe.skip('#crud #race', function() {
- this.slow(30000);
- this.timeout(60000);
- let app = null;
- let client = null;
-
- before(function() {
- return launchCompass()
- .then(function(application) {
- app = application;
- client = application.client;
- return client.connectToCompass({ hostname: 'localhost', port: 27018 });
- });
- });
-
- after(function() {
- return quitCompass(app);
- });
-
- context('when manipulating documents in the crud view', function() {
- const dataService = new DataService(CONNECTION);
-
- before(function(done) {
- dataService.connect(function() {
- dataService.createCollection('music.artists', {}, function() {
- return client
- .goToCollection('music', 'artists').then(function() {
- done();
- });
- });
- });
- });
-
- after(function(done) {
- dataService.dropDatabase('music', function() {
- dataService.disconnect();
- done();
- });
- });
-
- context('when inserting a document', function() {
- context('when the document is valid', function() {
- it('creates the document #race', function() {
- return client
- .clickDocumentsTab()
- .clickInsertDocumentButton()
- .waitForInsertDocumentModal()
- .inputNewDocumentDetails({
- 'name': 'Aphex Twin',
- 'genre': 'Electronic',
- 'location': 'London'
- })
- .clickInsertDocumentModalButton()
- .waitForDocumentInsert(1)
- .getDocumentValues(1)
- .should.eventually.include('\"Aphex Twin\"');
- });
- });
-
- context('when pressing escape key twice', function() {
- it('does not close the insert documents modal on first press', function() {
- return client
- .clickInsertDocumentButton()
- .waitForInsertDocumentModal()
- .pressEscape()
- .waitForInsertDocumentModal()
- .should.eventually.be.true;
- });
- it('closes the insert documents modal on second press', function() {
- return client
- .pressEscape()
- .waitForInsertDocumentModalHidden()
- .should.eventually.be.true;
- });
- });
- });
-
- context('when editing a document', function() {
- it.skip('saves the changes to the document #race', function() {
- return client
- .clickEditDocumentButton(1)
- .inputDocumentValueChange(1, 'Aphex Twin', 'Aphex Twin (edited)')
- .clickUpdateDocumentButton(1)
- .waitForDocumentUpdate(1)
- .getDocumentValues(1)
- .should.eventually.include('\"Aphex Twin (edited)\"');
- });
- });
-
- context('when cloning a document', function() {
- it('creates the cloned document', function() {
- return client
- .clickCloneDocumentButton(1)
- .waitForInsertDocumentModal()
- .inputClonedDocumentValueChange(1, 'London', 'Essex')
- .clickInsertDocumentModalButton()
- .waitForDocumentInsert(2)
- .getDocumentValues(2)
- .should.eventually.include('\"Essex\"');
- });
- });
-
- context('when double clicking a field', function() {
- it('opens document edit dialog and focuses cursor on the field', function() {
- return client
- .doubleClickDocumentField(2, 2)
- .inputDocumentFieldChange(2, 'genre', 'category')
- .clickUpdateDocumentButton(2)
- .waitForDocumentUpdate(2)
- .getDocumentFields(2)
- .should.eventually.include('category');
- });
-
- it('opens document edit dialog and focuses cursor on the value', function() {
- return client
- .doubleClickDocumentValue(2, 2)
- .inputDocumentValueChange(2, 'Electronic', 'ska')
- .clickUpdateDocumentButton(2)
- .waitForDocumentUpdate(2)
- .getDocumentValues(2)
- .should.eventually.include('\"ska\"');
- });
- });
-
- context('when deleting a document', function() {
- it('deletes upon confirmation #race', function() {
- return client
- .clickDeleteDocumentButton(2)
- .clickConfirmDeleteDocumentButton(2)
- .waitForDocumentDeletionToComplete(2)
- .getSamplingMessageFromDocumentsTab()
- .should.eventually.include('Query returned 1 document.');
- });
- });
-
- context('when applying a filter', function() {
- const filter = '{"name":"Bonobo"}';
- it('updates the document list', function() {
- return client
- .inputFilterFromDocumentsTab(filter)
- .clickApplyFilterButtonFromDocumentsTab()
- .getSamplingMessageFromDocumentsTab()
- .should.eventually.include('Query returned 0 documents.');
- });
- });
- });
-});
diff --git a/test/functional/support/packages/spectron-crud.js b/test/functional/support/packages/spectron-crud.js
index d331e2de970..9170cd3165f 100644
--- a/test/functional/support/packages/spectron-crud.js
+++ b/test/functional/support/packages/spectron-crud.js
@@ -1,7 +1,6 @@
const _ = require('lodash');
const { selector } = require('hadron-spectron');
-
function addWaitCRUDCommands(client) {
/**
* Wait for the insert document modal to open.
@@ -358,5 +357,4 @@ function addCRUDCommands(client) {
addInputCRUDCommands(client);
}
-
module.exports = addCRUDCommands;
diff --git a/test/renderer/crud.open-insert-document-dialog-store.test.js b/test/renderer/crud.open-insert-document-dialog-store.test.js
deleted file mode 100644
index 68f28a22a36..00000000000
--- a/test/renderer/crud.open-insert-document-dialog-store.test.js
+++ /dev/null
@@ -1,59 +0,0 @@
-/* eslint no-unused-expressions: 0 */
-
-const expect = require('chai').expect;
-
-// const debug = require('debug')('mongodb-compass:test:query-changed-store');
-
-let OpenInsertDocumentDialogStore = require('../../src/internal-packages/crud/lib/store/open-insert-document-dialog-store');
-
-describe('OpenInsertDocumentDialogStore', () => {
- let unsubscribe = () => {};
-
- afterEach(() => {
- unsubscribe();
- unsubscribe = () => {};
- });
-
- context('when inserting a new document', () => {
- it('keeps the document as is without modifications', (done) => {
- const doc = {
- _id: 'foo',
- field: 'bar'
- };
- unsubscribe = OpenInsertDocumentDialogStore.listen((hadronDoc) => {
- expect(hadronDoc.generateObject()).to.be.deep.equal(doc);
- done();
- });
- OpenInsertDocumentDialogStore.openInsertDocumentDialog(doc, false);
- });
- });
-
- context('when cloning a document', () => {
- it('removes the _id element when it is at the first position', (done) => {
- const doc = {
- _id: 'foo',
- field: 'bar'
- };
- unsubscribe = OpenInsertDocumentDialogStore.listen((hadronDoc) => {
- expect(hadronDoc.generateObject()).to.be.deep.equal({field: 'bar'});
- done();
- });
- OpenInsertDocumentDialogStore.openInsertDocumentDialog(doc, true);
- });
- it('removes the _id element when it is not at the first position', (done) => {
- const doc = {
- _a_surprise_: 'indeed',
- _id: 'foo',
- field: 'bar'
- };
- unsubscribe = OpenInsertDocumentDialogStore.listen((hadronDoc) => {
- expect(hadronDoc.generateObject()).to.be.deep.equal({
- _a_surprise_: 'indeed',
- field: 'bar'
- });
- done();
- });
- OpenInsertDocumentDialogStore.openInsertDocumentDialog(doc, true);
- });
- });
-});