p5.js-web-editor/server/controllers/project.controller.js
Enrique Piqueras 5e4b076b93 Fixed #158 and #100 (#198)
* Changed unsaved changes asterisk to an svg circle. #158

* Fixed #100
Unmatched routes are handled by react-router on the client side
and a single wildcard route on server.routes.js renders the index
html.
When the /:username/sketches route is matched and the username is not
valid, the user will be redirected to the index route and a toast
will explain what happened. When the username is 'p5' (default when
logged out) it will show all sketches. Maybe this should be changed
to just public or 'local' sketches?

* Moved unsaved changes SVG to a separate file.

* User not found is now a 404 error.

* Added server rendered 404 page.

* Removed console.log

* 404 Page now renders a random p5 sketch. TODO: make 404 sketches.

* Added 404 header
404 page now fetches a random example sketch

* Moved circle closer to file name

* Render 404 page in SketchList route if !user
2017-01-06 13:08:03 -05:00

159 lines
4.7 KiB
JavaScript

import Project from '../models/project';
import User from '../models/user';
import archiver from 'archiver';
import request from 'request';
export function createProject(req, res) {
let projectValues = {
user: req.user ? req.user._id : undefined // eslint-disable-line no-underscore-dangle
};
projectValues = Object.assign(projectValues, req.body);
Project.create(projectValues, (err, newProject) => {
if (err) { return res.json({ success: false }); }
Project.populate(newProject,
{ path: 'user', select: 'username' },
(innerErr, newProjectWithUser) => {
if (innerErr) { return res.json({ success: false }); }
return res.json(newProjectWithUser);
});
});
}
export function updateProject(req, res) {
Project.findByIdAndUpdate(req.params.project_id,
{
$set: req.body
})
.populate('user', 'username')
.exec((err, updatedProject) => {
if (err) {
console.log(err);
return res.json({ success: false });
}
if (updatedProject.files.length !== req.body.files.length) {
const oldFileIds = updatedProject.files.map(file => file.id);
const newFileIds = req.body.files.map(file => file.id);
const staleIds = oldFileIds.filter(id => newFileIds.indexOf(id) === -1);
staleIds.forEach(staleId => {
updatedProject.files.id(staleId).remove();
});
updatedProject.save((innerErr) => {
if (innerErr) {
console.log(innerErr);
return res.json({ success: false });
}
return res.json(updatedProject);
});
}
return res.json(updatedProject);
});
}
export function getProject(req, res) {
Project.findById(req.params.project_id)
.populate('user', 'username')
.exec((err, project) => {
if (err) {
return res.status(404).send({ message: 'Project with that id does not exist' });
}
return res.json(project);
});
}
export function deleteProject(req, res) {
Project.remove({ _id: req.params.project_id }, (err) => {
if (err) {
return res.status(404).send({ message: 'Project with that id does not exist' });
}
return res.json({ success: true });
});
}
export function getProjects(req, res) {
if (req.user) {
Project.find({ user: req.user._id }) // eslint-disable-line no-underscore-dangle
.sort('-createdAt')
.select('name files id createdAt updatedAt')
.exec((err, projects) => {
res.json(projects);
});
} else {
// could just move this to client side
return res.json([]);
}
}
export function getProjectsForUser(req, res) {
if (req.params.username) {
User.findOne({ username: req.params.username }, (err, user) => {
if (!user) {
return res.status(404).json({ message: 'User with that username does not exist.' });
} else {
Project.find({ user: user._id }) // eslint-disable-line no-underscore-dangle
.sort('-createdAt')
.select('name files id createdAt updatedAt')
.exec((err, projects) => res.json(projects));
}
return null;
});
} else {
// could just move this to client side
return res.json([]);
}
return null;
}
function buildZip(project, req, res) {
const zip = archiver('zip');
const rootFile = project.files.find(file => file.name === 'root');
const numFiles = project.files.filter(file => file.fileType !== 'folder').length;
const files = project.files;
const projectName = project.name;
let numCompletedFiles = 0;
zip.on('error', function (err) {
res.status(500).send({ error: err.message });
});
res.attachment(`${project.name}.zip`);
zip.pipe(res);
function addFileToZip(file, path) {
if (file.fileType === 'folder') {
const newPath = file.name === 'root' ? path : `${path}${file.name}/`;
file.children.forEach(fileId => {
const childFile = files.find(f => f.id === fileId);
(() => {
addFileToZip(childFile, newPath);
})();
});
} else {
if (file.url) {
request({ method: 'GET', url: file.url, encoding: null }, (err, response, body) => {
zip.append(body, { name: `${path}${file.name}` });
numCompletedFiles += 1;
if (numCompletedFiles === numFiles) {
zip.finalize();
}
});
} else {
zip.append(file.content, { name: `${path}${file.name}` });
numCompletedFiles += 1;
if (numCompletedFiles === numFiles) {
zip.finalize();
}
}
}
}
addFileToZip(rootFile, '/');
}
export function downloadProjectAsZip(req, res) {
Project.findById(req.params.project_id, (err, project) => {
// save project to some path
buildZip(project, req, res);
});
}