diff --git a/frontend/menus/DocumentMenu.js b/frontend/menus/DocumentMenu.js index 11ed5775..e60933f8 100644 --- a/frontend/menus/DocumentMenu.js +++ b/frontend/menus/DocumentMenu.js @@ -16,8 +16,11 @@ import { DropdownMenu, DropdownMenuItem } from 'components/DropdownMenu'; document: Document, }; - onCreateDocument = () => { - this.props.history.push(`${this.props.document.collection.url}/new`); + handleNewChild = () => { + const { history, document } = this.props; + history.push( + `${document.collection.url}/new?parentDocument=${document.id}` + ); }; handleDelete = () => { @@ -52,7 +55,12 @@ import { DropdownMenu, DropdownMenuItem } from 'components/DropdownMenu'; Unstar : Star} - + + New child + Move Export {allowDelete && diff --git a/frontend/models/Document.js b/frontend/models/Document.js index e13df65f..4f4c760e 100644 --- a/frontend/models/Document.js +++ b/frontend/models/Document.js @@ -97,7 +97,7 @@ class Document extends BaseModel { @computed get parentDocumentId(): ?string { return this.pathToDocument.length > 1 - ? this.pathToDocument[this.pathToDocument.length - 1].id + ? this.pathToDocument[this.pathToDocument.length - 2].id : null; } @@ -175,7 +175,6 @@ class Document extends BaseModel { if (this.parentDocument) { data.parentDocument = this.parentDocument; } - debugger; res = await client.post('/documents.create', data); } runInAction('Document#save', () => { diff --git a/package.json b/package.json index bd9d3faa..5af1067d 100644 --- a/package.json +++ b/package.json @@ -4,11 +4,14 @@ "main": "index.js", "scripts": { "clean": "rimraf dist", - "build:webpack": "NODE_ENV=production webpack --config webpack.config.prod.js", - "build:analyze": "NODE_ENV=production webpack --config webpack.config.prod.js --json | webpack-bundle-size-analyzer", + "build:webpack": + "NODE_ENV=production webpack --config webpack.config.prod.js", + "build:analyze": + "NODE_ENV=production webpack --config webpack.config.prod.js --json | webpack-bundle-size-analyzer", "build": "npm run clean && npm run build:webpack", "start": "node index.js", - "dev": "NODE_ENV=development DEBUG=sql,cache,presenters ./node_modules/.bin/nodemon --watch server index.js", + "dev": + "NODE_ENV=development DEBUG=sql,cache,presenters ./node_modules/.bin/nodemon --inspect --watch server index.js", "lint": "npm run lint:flow && npm run lint:js", "lint:js": "eslint frontend", "lint:flow": "flow", @@ -18,39 +21,24 @@ "sequelize:migrate": "sequelize db:migrate", "test": "npm run test:frontend && npm run test:server", "test:frontend": "jest", - "test:server": "jest --config=server/.jestconfig.json --runInBand --forceExit", + "test:server": + "jest --config=server/.jestconfig.json --runInBand --forceExit", "precommit": "lint-staged" }, "lint-staged": { - "*.js": [ - "eslint --fix", - "git add" - ] + "*.js": ["eslint --fix", "git add"] }, "jest": { "verbose": false, - "roots": [ - "frontend" - ], + "roots": ["frontend"], "moduleNameMapper": { "^.*[.](s?css|css)$": "/__mocks__/styleMock.js", "^.*[.](gif|ttf|eot|svg)$": "/__test__/fileMock.js" }, - "moduleFileExtensions": [ - "js", - "jsx", - "json" - ], - "moduleDirectories": [ - "node_modules" - ], - "modulePaths": [ - "frontend" - ], - "setupFiles": [ - "/setupJest.js", - "/__mocks__/window.js" - ] + "moduleFileExtensions": ["js", "jsx", "json"], + "moduleDirectories": ["node_modules"], + "modulePaths": ["frontend"], + "setupFiles": ["/setupJest.js", "/__mocks__/window.js"] }, "engines": { "node": ">= 7.6" @@ -169,7 +157,8 @@ "string-hash": "^1.1.0", "style-loader": "^0.18.2", "styled-components": "^2.0.0", - "truncate-html": "https://github.com/jorilallo/truncate-html/tarball/master", + "truncate-html": + "https://github.com/jorilallo/truncate-html/tarball/master", "url-loader": "0.5.7", "uuid": "2.0.2", "validator": "5.2.0", diff --git a/server/api/documents.test.js b/server/api/documents.test.js index 67cf4488..8f1b7c58 100644 --- a/server/api/documents.test.js +++ b/server/api/documents.test.js @@ -3,6 +3,7 @@ import TestServer from 'fetch-test-server'; import app from '..'; import { View, Star } from '../models'; import { flushdb, seed } from '../test/support'; +import Document from '../models/Document'; const server = new TestServer(app.callback()); @@ -194,6 +195,49 @@ describe('#documents.unstar', async () => { }); }); +describe('#documents.create', async () => { + it('should create as a new document', async () => { + const { user, collection } = await seed(); + const res = await server.post('/api/documents.create', { + body: { + token: user.getJwtToken(), + collection: collection.id, + title: 'new document', + text: 'hello', + }, + }); + const body = await res.json(); + const newDocument = await Document.findOne({ + where: { + id: body.data.id, + }, + }); + + expect(res.status).toEqual(200); + expect(newDocument.parentDocumentId).toBe(null); + expect(newDocument.collection.id).toBe(collection.id); + }); + + it('should create as a child', async () => { + const { user, document, collection } = await seed(); + const res = await server.post('/api/documents.create', { + body: { + token: user.getJwtToken(), + collection: collection.id, + title: 'new document', + text: 'hello', + parentDocument: document.id, + }, + }); + const body = await res.json(); + + expect(res.status).toEqual(200); + expect(body.data.title).toBe('new document'); + expect(body.data.collection.documents.length).toBe(2); + expect(body.data.collection.documents[1].children[0].id).toBe(body.data.id); + }); +}); + describe('#documents.update', async () => { it('should update document details in the root', async () => { const { user, document } = await seed(); diff --git a/server/models/Collection.js b/server/models/Collection.js index 45a36a77..7e2d29c2 100644 --- a/server/models/Collection.js +++ b/server/models/Collection.js @@ -133,16 +133,23 @@ Collection.prototype.addDocumentToStructure = async function(document, index) { // Sequelize doesn't seem to set the value with splice on JSONB field this.documentStructure = this.documentStructure; } else { - this.documentStructure = this.documentStructure.map(childDocument => { - if (document.parentDocumentId === childDocument.id) { - childDocument.children.splice( - index || childDocument.children.length, - 0, - document.toJSON() - ); - } - return childDocument; - }); + // Recursively place document + const placeDocument = documentList => { + return documentList.map(childDocument => { + if (document.parentDocumentId === childDocument.id) { + childDocument.children.splice( + index || childDocument.children.length, + 0, + document.toJSON() + ); + } else { + childDocument.children = placeDocument(childDocument.children); + } + + return childDocument; + }); + }; + this.documentStructure = placeDocument(this.documentStructure); } await this.save();