mirror of https://github.com/perkeep/perkeep.git
Merge "UI: add to set when dropped is a dup but not yet a member of the set"
This commit is contained in:
commit
e67998ee12
|
@ -298,7 +298,7 @@ cam.IndexPage = React.createClass({
|
|||
totalBytesComplete: completedBytes
|
||||
});
|
||||
|
||||
console.log('Uploaded %d of %d bytes', completedBytes, this.state.totalBytesToUpload);
|
||||
console.log('Completed %d of %d bytes', completedBytes, this.state.totalBytesToUpload);
|
||||
},
|
||||
|
||||
onUploadComplete_: function() {
|
||||
|
@ -319,16 +319,18 @@ cam.IndexPage = React.createClass({
|
|||
|
||||
var files = e.nativeEvent.dataTransfer.files;
|
||||
var sc = this.props.serverConnection;
|
||||
var parent = this.getTargetBlobref_();
|
||||
|
||||
this.onUploadStart_(files);
|
||||
|
||||
goog.labs.Promise.all(
|
||||
Array.prototype.map.call(files, function(file) {
|
||||
return uploadFile(file)
|
||||
.then(fetchExistingPermanode)
|
||||
.then(fetchPermanodeIfExists)
|
||||
.then(createPermanodeIfNotExists)
|
||||
.then(nameResults)
|
||||
.then(createPermanodeAssociations.bind(this))
|
||||
.then(updatePermanodeRef)
|
||||
.then(checkExistingCamliMembership)
|
||||
.then(createPermanodeAssociations)
|
||||
.thenCatch(function(e) {
|
||||
console.error('File upload fall down go boom. file: %s, error: %s', file.name, e);
|
||||
})
|
||||
|
@ -339,53 +341,92 @@ cam.IndexPage = React.createClass({
|
|||
}).then(this.onUploadComplete_);
|
||||
|
||||
function uploadFile(file) {
|
||||
|
||||
// capture status of upload promise chain
|
||||
var status = {
|
||||
fileRef: '',
|
||||
isCamliMemberOfParent: false,
|
||||
parentRef: parent,
|
||||
permanodeRef: '',
|
||||
permanodeCreated: false
|
||||
};
|
||||
|
||||
var uploadFile = new goog.labs.Promise(sc.uploadFile.bind(sc, file));
|
||||
return goog.labs.Promise.all([uploadFile]);
|
||||
|
||||
return goog.labs.Promise.all([new goog.labs.Promise.resolve(status), uploadFile]);
|
||||
}
|
||||
|
||||
function fetchExistingPermanode(blobIds) {
|
||||
var fileRef = blobIds[0];
|
||||
var fileUploaded = new goog.labs.Promise.resolve(fileRef);
|
||||
var getPermanode = new goog.labs.Promise(sc.getPermanodeWithContent.bind(sc, fileRef));
|
||||
return goog.labs.Promise.all([fileUploaded, getPermanode]);
|
||||
function fetchPermanodeIfExists(results) {
|
||||
var status = results[0];
|
||||
status.fileRef = results[1];
|
||||
|
||||
var getPermanode = new goog.labs.Promise(sc.getPermanodeWithContent.bind(sc, status.fileRef));
|
||||
|
||||
return goog.labs.Promise.all([new goog.labs.Promise.resolve(status), getPermanode]);
|
||||
}
|
||||
|
||||
function createPermanodeIfNotExists(results) {
|
||||
var fileRef = results[0];
|
||||
var permanode = results[1];
|
||||
if (!permanode) {
|
||||
var fileUploaded = new goog.labs.Promise.resolve(fileRef);
|
||||
var status = results[0];
|
||||
var permanodeRef = results[1];
|
||||
|
||||
if (!permanodeRef) {
|
||||
status.permanodeCreated = true;
|
||||
|
||||
var createPermanode = new goog.labs.Promise(sc.createPermanode.bind(sc));
|
||||
return goog.labs.Promise.all([fileUploaded, createPermanode]);
|
||||
return goog.labs.Promise.all([new goog.labs.Promise.resolve(status), createPermanode]);
|
||||
}
|
||||
// Empty values so the next in chain knows that we're in the "permanode already exists" case.
|
||||
return goog.labs.Promise.resolve(["", ""]);
|
||||
|
||||
return goog.labs.Promise.all([new goog.labs.Promise.resolve(status), new goog.labs.Promise.resolve(permanodeRef)]);
|
||||
}
|
||||
|
||||
// 'readable-ify' the blob references returned from upload/create
|
||||
function nameResults(blobIds) {
|
||||
return {
|
||||
'fileRef': blobIds[0],
|
||||
'permanodeRef': blobIds[1]
|
||||
};
|
||||
function updatePermanodeRef(results) {
|
||||
var status = results[0];
|
||||
status.permanodeRef = results[1];
|
||||
|
||||
return goog.labs.Promise.all([new goog.labs.Promise.resolve(status)]);
|
||||
}
|
||||
|
||||
function createPermanodeAssociations(refs) {
|
||||
if (refs.permanodeRef == "") {
|
||||
// Any value would do, but boolean helps make it clear that we end
|
||||
// here, by resolving the file upload promise chain.
|
||||
return goog.labs.Promise.resolve(true);
|
||||
// TODO(mpl): this implementation means that when we're dropping on a set, we send
|
||||
// one additional query for each permanode that already exists. So in the worst case,
|
||||
// it amounts to one additional query per dropped item (with a small payload/response).
|
||||
// Alternatively, we could ask (either by tweaking the search session, or
|
||||
// "manually") the server for all the set members and cache the response, which means
|
||||
// only one additional query, and we can then do all the tests locally. However, the
|
||||
// response size scales with the number of members in the set, so I don't know if it's
|
||||
// better. A working example is at
|
||||
// https://camlistore-review.googlesource.com/#/c/5345/2 . We should benchmark and/or
|
||||
// ask Brad.
|
||||
|
||||
// check, when appropriate, if the permanode is already part of the set we're dropping in.
|
||||
function checkExistingCamliMembership(results) {
|
||||
var status = results[0];
|
||||
|
||||
// Permanode did not exist before, so it couldn't be a member of any set.
|
||||
if (!status.parentRef || status.permanodeCreated) {
|
||||
return goog.labs.Promise.all([new goog.labs.Promise.resolve(status), new goog.labs.Promise.resolve(false)]);
|
||||
}
|
||||
|
||||
console.log('checking membership');
|
||||
var hasMembership = new goog.labs.Promise(sc.isCamliMember.bind(sc, status.permanodeRef, status.parentRef));
|
||||
return goog.labs.Promise.all([new goog.labs.Promise.resolve(status), hasMembership]);
|
||||
}
|
||||
|
||||
function createPermanodeAssociations(results) {
|
||||
var status = results[0];
|
||||
status.isCamliMemberOfParent = results[1];
|
||||
|
||||
var promises = [];
|
||||
|
||||
// associate uploaded file to new permanode
|
||||
var camliContent = new goog.labs.Promise(sc.newSetAttributeClaim.bind(sc, refs.permanodeRef, 'camliContent', refs.fileRef));
|
||||
var promises = [camliContent];
|
||||
if (status.permanodeCreated) {
|
||||
var setCamliContent = new goog.labs.Promise(sc.newSetAttributeClaim.bind(sc, status.permanodeRef, 'camliContent', status.fileRef));
|
||||
promises.push(setCamliContent);
|
||||
}
|
||||
|
||||
// if currently viewing a set, make new permanode a member of the set
|
||||
var parentPermanodeRef = this.getTargetBlobref_();
|
||||
if (parentPermanodeRef) {
|
||||
var camliMember = new goog.labs.Promise(sc.newAddAttributeClaim.bind(sc, parentPermanodeRef, 'camliMember', refs.permanodeRef));
|
||||
promises.push(camliMember);
|
||||
// add CamliMember relationship if viewing a set
|
||||
if (status.parentRef && !status.isCamliMemberOfParent) {
|
||||
var setCamliMember = new goog.labs.Promise(sc.newAddAttributeClaim.bind(sc, status.parentRef, 'camliMember', status.permanodeRef));
|
||||
promises.push(setCamliMember);
|
||||
}
|
||||
|
||||
return goog.labs.Promise.all(promises);
|
||||
|
|
|
@ -60,7 +60,7 @@ cam.ServerConnection.DESCRIBE_REQUEST = {
|
|||
]
|
||||
};
|
||||
|
||||
cam.ServerConnection.prototype.getPermanodeWithContent = function(contentRef, success, opt_fail) {
|
||||
cam.ServerConnection.prototype.getPermanodeWithContent = function(contentRef, success) {
|
||||
var query = {
|
||||
permanode: {
|
||||
attr: "camliContent",
|
||||
|
@ -77,6 +77,37 @@ cam.ServerConnection.prototype.getPermanodeWithContent = function(contentRef, su
|
|||
this.search(query, null, null, null, callback);
|
||||
};
|
||||
|
||||
// If child is a camliMember of parent success is called with 'true', otherrwise 'false'
|
||||
// @param {string} blobref of the child
|
||||
// @param {string} blobref of the parent
|
||||
// @param {Function} success callback with data.
|
||||
cam.ServerConnection.prototype.isCamliMember = function(child, parent, success) {
|
||||
var query = {
|
||||
logical: {
|
||||
a: {
|
||||
permanode: {
|
||||
attr: "camliMember",
|
||||
ValueInSet: {
|
||||
blobRefPrefix: child,
|
||||
}
|
||||
}
|
||||
},
|
||||
op: "and",
|
||||
b: {
|
||||
blobRefPrefix: parent,
|
||||
}
|
||||
},
|
||||
};
|
||||
var callback = function(result) {
|
||||
if (!result || !result.blobs || result.blobs.length == 0) {
|
||||
success(false);
|
||||
return;
|
||||
}
|
||||
success(true);
|
||||
}
|
||||
this.search(query, null, null, null, callback);
|
||||
};
|
||||
|
||||
cam.ServerConnection.prototype.getWorker_ = function() {
|
||||
if (!this.worker_) {
|
||||
var r = new Date().getTime(); // For cachebusting the worker. Sigh. We need content stamping.
|
||||
|
|
Loading…
Reference in New Issue