-
Notifications
You must be signed in to change notification settings - Fork 150
[WIP] Provide an easy way for user to import a project.. #150
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi and thanks a lot for the PR!
This is looking good overall! made a bunch of initial comments, please address them or reply and then I'll test and look into the manifest / actualIndex thingy you mentioned in #46.
client/src/hub/index.jade
Outdated
button(disabled).open-project= t("hub:openProject") | ||
button(disabled).edit-project= t("hub:editDetails.title") | ||
|
||
form(style="display: none") | ||
input.file-select(type="file", accept="application.zip") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this should be application/zip
instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also maybe we can have a more specific class name like project-archive-select
client/src/hub/index.jade
Outdated
button(disabled).open-project= t("hub:openProject") | ||
button(disabled).edit-project= t("hub:editDetails.title") | ||
|
||
form(style="display: none") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Best to use hidden
rather than CSS
client/src/hub/index.ts
Outdated
let target = event.target as HTMLInputElement; | ||
if (target.files.length === 0) return; | ||
|
||
let reader = new FileReader(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
target
and reader
can be made const too.
client/src/hub/index.ts
Outdated
let reader = new FileReader(); | ||
|
||
reader.onload = function(evnt) { | ||
socket.emit("import:projects", {name: target.files[0].name.split(".")[0], data: (evnt.target as any).result}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make sure to have spaces inside curly brackets
package.json
Outdated
@@ -56,6 +56,7 @@ | |||
"socket.io": "^1.4.4", | |||
"tab-strip": "^2.3.0", | |||
"tv4": "^1.2.7", | |||
"unzip": "^0.1.11", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We already have yauzl
(which stands for "yet another unzip library"), would be better to reuse it rather than add a dependency on another ZIP lib.
server/RemoteHubClient.ts
Outdated
@@ -190,4 +199,29 @@ export default class RemoteHubClient extends BaseRemoteClient { | |||
else callback(null); | |||
}); | |||
}; | |||
|
|||
private onImportProject = (data: ImportProjectData) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's an extra space after the =
server/RemoteHubClient.ts
Outdated
|
||
private onImportProject = (data: ImportProjectData) => { | ||
|
||
fs.writeFile(path.join(this.server.projectsPath, "project.zip"), data.data as string, (err) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A bit dangerous to write the ZIP file directly inside the project folder, since it could be overwritten by another import at the same time. If saving it to disk is actually needed (can't we unzip from memory?), would be best to save it in the system's temporary folder with a random name. We might already do that elsewhere, look for yauzl usage I guess.
server/RemoteHubClient.ts
Outdated
}) | ||
.on("close", () => { | ||
this.server.loadProject(data.name, (err: Error) => { | ||
if (err) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We use explicit if (err != null)
throughout the codebase rather than implicit boolean coercion.
if (err) { | ||
console.log(err); | ||
} | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Regarding #46 (comment):
I think you'll need to change loadProject
in ProjectHub.ts
to pass you the newly initialized project server as a second argument, then you can access the manifest (which contains name, description, etc. to send it to clients for display in the hub).
For actualIndex
, I think after loading the project, we'll need to add the ProjectHub's data.projects
so that it shows up in the list, and that will give you that index. If that's too confusing I can take care of it.
unzip -> yauzl Use node-temp to create a temporary directory Use node-mv to move the directory
@elisee Can you explain what you mean by adding |
- Based on review from elisee - Use copy-dir, temp and yauzl
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking pretty good, listed a few more things to fix and hopefully made it clearer what's required re. the manifest.
@@ -14,6 +21,10 @@ interface ProjectDetails { | |||
icon: Buffer; | |||
} | |||
interface AddProjectCallback { (err: string, projectId?: string): any; }; | |||
interface ImportProjectData { | |||
name: string; | |||
data: string; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this should be a Buffer
not a string? Since it's an ArrayBuffer on the client-side, should be converted to a NodeJS Bon the server-side.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oups, it was an inattention mistake. I change this!
}); | ||
zipFile.on("end", () => { | ||
// move the extracted content into the projects' folder | ||
copydir(path.join(dirPath, rootFolderName), path.join(this.server.projectsPath, rootFolderName), (err: Error) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there any reason why we want to copy rather than just doing fs.rename
on the root dir? Seems better to avoid having a copy lying around, even if it's in a temp folder.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, when I tried with fs.rename I had a crash on the server side with on error like this:
Error: EXDEV: cross-device link not permitted, rename '/tmp/project1161019-14225-1cpphb6/dodgell-master/' -> '/home/ilphrin/Jeux/superpowers/core/projects/dodgell-master/'
I didn't find a solution to this, so I tried copying the folder and then it worked
copydir(path.join(dirPath, rootFolderName), path.join(this.server.projectsPath, rootFolderName), (err: Error) => { | ||
if (err != null) throw err; | ||
this.server.loadProject(rootFolderName, (err: Error, manifest: SupCore.Data.ProjectManifest) => { | ||
if (err != null) throw err; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here we still need to:
- Add the project manifest to
this.server.projects
(see here:this.server.data.projects.add(manifest, sortedIndex, (err: string, actualIndex: number) => { - And then we need to notify all people already connected to the hub of the new project (see
superpowers-core/server/RemoteHubClient.ts
Line 122 in 70f9b5b
this.server.io.in("sub:projects").emit("add:projects", manifest, actualIndex);
Otherwise the new project will be imported but you'll need to restart the server before it can be joined.
Closing since this has seen no activity in years. |
...to fix #46