diff --git a/client/app/main/main.jade b/client/app/main/main.jade index 9097617..380f66d 100644 --- a/client/app/main/main.jade +++ b/client/app/main/main.jade @@ -1,23 +1,23 @@ div(ng-include='"components/navbar/navbar.html"') header#banner.hero-unit(ng-hide='isLoggedIn() ') .container h1 Manticore p.lead Realtime collaboration for rich office documents. img(src='assets/images/manticore.jpg', alt='Manticore') .container(ng-hide='!isLoggedIn()') .row .col-lg-12 h1.page-header Documents ul.nav.nav-tabs.nav-stacked.col-md-4.col-lg-4.col-sm-6(ng-repeat='document in documents') li a(href='#', tooltip='{{document.info}}') - | {{document.name}} + | {{document.title}} //- footer.footer .container p | Manticore = ' | ' a(href='https://github.com/adityab/Manticure/issues?state=open') Issues diff --git a/client/components/import/import.controller.js b/client/components/import/import.controller.js index 4b36bee..9f61d73 100644 --- a/client/components/import/import.controller.js +++ b/client/components/import/import.controller.js @@ -1,25 +1,28 @@ 'use strict'; angular.module('manticoreApp') - .controller('ImportCtrl', function ($scope, FileUploader) { + .controller('ImportCtrl', function ($scope, FileUploader, Auth) { var uploader = new FileUploader({ url: '/upload', removeAfterUpload: true, - autoUpload: true + autoUpload: true, + headers: { + 'Authorization': 'Bearer ' + Auth.getToken() + } }); uploader.filters.push({ name: 'sizeFilter', fn: function (item) { return item.size <= 10485760; // 10 Megabytes } }); uploader.filters.push({ name: 'typeFilter', fn: function (item) { return item.type === 'application/vnd.oasis.opendocument.text'; } }); $scope.uploader = uploader; }); diff --git a/server/api/document/document.controller.js b/server/api/document/document.controller.js index 7029351..ddc16d7 100644 --- a/server/api/document/document.controller.js +++ b/server/api/document/document.controller.js @@ -1,68 +1,68 @@ /** * Using Rails-like standard naming convention for endpoints. * GET /documents -> index * POST /documents -> create * GET /documents/:id -> show * PUT /documents/:id -> update * DELETE /documents/:id -> destroy */ 'use strict'; var _ = require('lodash'); -var Document = require('./document.model'); +var Document = require('./document.model').Document; // Get list of documents exports.index = function(req, res) { Document.find(function (err, documents) { if(err) { return handleError(res, err); } return res.json(200, documents); }); }; // Get a single document exports.show = function(req, res) { Document.findById(req.params.id, function (err, document) { if(err) { return handleError(res, err); } if(!document) { return res.send(404); } return res.json(document); }); }; // Creates a new document in the DB. exports.create = function(req, res) { Document.create(req.body, function(err, document) { if(err) { return handleError(res, err); } return res.json(201, document); }); }; // Updates an existing document in the DB. exports.update = function(req, res) { if(req.body._id) { delete req.body._id; } Document.findById(req.params.id, function (err, document) { if (err) { return handleError(res, err); } if(!document) { return res.send(404); } var updated = _.merge(document, req.body); updated.save(function (err) { if (err) { return handleError(res, err); } return res.json(200, document); }); }); }; // Deletes a document from the DB. exports.destroy = function(req, res) { Document.findById(req.params.id, function (err, document) { if(err) { return handleError(res, err); } if(!document) { return res.send(404); } document.remove(function(err) { if(err) { return handleError(res, err); } return res.send(204); }); }); }; function handleError(res, err) { return res.send(500, err); } diff --git a/server/api/document/document.model.js b/server/api/document/document.model.js index a35e88b..1415c9c 100644 --- a/server/api/document/document.model.js +++ b/server/api/document/document.model.js @@ -1,14 +1,25 @@ 'use strict'; var mongoose = require('mongoose'), Schema = mongoose.Schema; +/* + * Each Document Chunk has an associated ODF snapshot file within + * GridFS of the same ID. + */ +var DocumentChunk = new Schema({ + operations: { type: Array, default: [] } +}); + var DocumentSchema = new Schema({ - name: String, - created: { type: Date, default: Date.now, required: true }, - updated: Date, - active: { type: Boolean, default: false, required: true }, - editors: { type: [{type: Schema.Types.ObjectId, ref: 'User'}], default: [] } + title: String, + created: { type: Date, default: Date.now, required: true }, + creator: { type: Schema.Types.ObjectId, ref: 'User' }, + editors: { type: [{type: Schema.Types.ObjectId, ref: 'User'}], default: [] }, + chunks: { type: [{type: Schema.Types.ObjectId, ref: 'DocumentChunk'}], required: true } }); -module.exports = mongoose.model('Document', DocumentSchema); +module.exports = { + DocumentChunk: mongoose.model('DocumentChunk', DocumentChunk), + Document: mongoose.model('Document', DocumentSchema) +}; diff --git a/server/api/upload/index.js b/server/api/upload/index.js index 0c777a5..cfbbf50 100644 --- a/server/api/upload/index.js +++ b/server/api/upload/index.js @@ -1,46 +1,57 @@ 'use strict'; var express = require('express'); var multer = require('multer'); var _ = require('lodash'); var Grid = require('gridfs-stream'); var mongoose = require('mongoose'); -var Document = require('../document/document.model'); +var auth = require('../../auth/auth.service'); +var DocumentChunk = require('../document/document.model').DocumentChunk; +var Document = require('../document/document.model').Document; var gfs = Grid(mongoose.connection.db, mongoose.mongo); var router = express.Router(); -router.post('/', function (req, res, next) { console.log('here'); next(); }, multer({ - upload: null, - limits: { - fileSize: 1024 * 1024 * 20, // 20 Megabytes - files: 5 - }, - onFileUploadStart: function (file) { - var newDocument = new Document({ - name: file.originalname - }); - this.upload = gfs.createWriteStream({ - _id: mongoose.Types.ObjectId(newDocument._id), - filename: file.originalname, - mode: 'w', - chunkSize: 1024 * 4, - content_type: file.mimetype, - root: 'fs' - }); - this.upload.on('finish', function () { - newDocument.save(); - }); - }, - onFileUploadData: function (file, data) { - this.upload.write(data); - }, - onFileUploadComplete: function (file) { - this.upload.end(); - } -}), function (req, res) { +router.post('/', auth.isAuthenticated(), function (req, res, next) { + multer({ + upload: null, + limits: { + fileSize: 1024 * 1024 * 20, // 20 Megabytes + files: 5 + }, + onFileUploadStart: function (file) { + var firstChunk = new DocumentChunk(); + var newDocument = new Document({ + title: file.originalname, + creator: req.user._id, + chunks: [firstChunk._id] + }); + this.upload = gfs.createWriteStream({ + _id: mongoose.Types.ObjectId(firstChunk._id), + filename: file.originalname, + mode: 'w', + chunkSize: 1024 * 4, + content_type: file.mimetype, + root: 'fs' + }); + this.upload.on('finish', function () { + firstChunk.save(function (err) { + if (!err) { + newDocument.save(); + } + }); + }); + }, + onFileUploadData: function (file, data) { + this.upload.write(data); + }, + onFileUploadComplete: function (file) { + this.upload.end(); + } + })(req, res, next); +}, function (req, res) { res.status(200).send("OK"); }); module.exports = router; diff --git a/server/config/seed.js b/server/config/seed.js index 614d8f9..1c5e880 100644 --- a/server/config/seed.js +++ b/server/config/seed.js @@ -1,42 +1,33 @@ /** * Populate DB with sample data on server start * to disable, edit config/environment/index.js, and set `seedDB: false` */ 'use strict'; -var Document = require('../api/document/document.model'); +var Document = require('../api/document/document.model').Document; +var DocumentChunk = require('../api/document/document.model').DocumentChunk; var User = require('../api/user/user.model'); -Document.find({}).remove(function() { - Document.create({ - name: 'Trip Budget' - }, { - name: 'Vacation Spots' - }, { - name: 'Voucher Codes' - }, { - name: 'Backpacks' - }, function () { - console.log('finished populating documents') - } - ); +DocumentChunk.find({}).remove(function() { + Document.find({}).remove(function() { + }); }); User.find({}).remove(function() { User.create({ provider: 'local', name: 'Test User', email: 'test@test.com', password: 'test' }, { provider: 'local', role: 'admin', name: 'Admin', email: 'admin@admin.com', password: 'admin' }, function() { console.log('finished populating users'); } ); });