mirror of
https://github.com/kuaifan/dootask.git
synced 2026-02-23 09:20:44 +00:00
808 lines
17 KiB
JavaScript
Vendored
808 lines
17 KiB
JavaScript
Vendored
/**
|
|
* Copyright (c) 2006-2017, JGraph Ltd
|
|
* Copyright (c) 2006-2017, Gaudenz Alder
|
|
*/
|
|
DriveFile = function(ui, data, desc)
|
|
{
|
|
DrawioFile.call(this, ui, data);
|
|
|
|
this.desc = desc;
|
|
};
|
|
|
|
//Extends mxEventSource
|
|
mxUtils.extend(DriveFile, DrawioFile);
|
|
|
|
/**
|
|
* Delay for last save in ms.
|
|
*/
|
|
DriveFile.prototype.saveDelay = 0;
|
|
|
|
/**
|
|
* Delay for last save in ms.
|
|
*/
|
|
DriveFile.prototype.allChangesSavedKey = 'allChangesSavedInDrive';
|
|
|
|
/**
|
|
* Specifies if notify events should be ignored.
|
|
*/
|
|
DriveFile.prototype.getSize = function()
|
|
{
|
|
return this.desc.fileSize;
|
|
};
|
|
|
|
/**
|
|
* Returns true if copy, export and print are not allowed for this file.
|
|
*/
|
|
DriveFile.prototype.isRestricted = function()
|
|
{
|
|
return this.desc.userPermission != null && this.desc.labels != null &&
|
|
this.desc.userPermission.role == 'reader' && this.desc.labels.restricted;
|
|
};
|
|
|
|
/**
|
|
* Adds the listener for automatically saving the diagram for local changes.
|
|
*/
|
|
DriveFile.prototype.isConflict = function(err)
|
|
{
|
|
return err != null && err.error != null && err.error.code == 412;
|
|
};
|
|
|
|
/**
|
|
* Returns the current etag.
|
|
*/
|
|
DriveFile.prototype.getCurrentUser = function()
|
|
{
|
|
return (this.ui.drive != null) ? this.ui.drive.user : null;
|
|
};
|
|
|
|
/**
|
|
* Translates this point by the given vector.
|
|
*
|
|
* @param {number} dx X-coordinate of the translation.
|
|
* @param {number} dy Y-coordinate of the translation.
|
|
*/
|
|
DriveFile.prototype.getMode = function()
|
|
{
|
|
return App.MODE_GOOGLE;
|
|
};
|
|
|
|
/**
|
|
* Returns true if copy, export and print are not allowed for this file.
|
|
*/
|
|
DriveFile.prototype.getPublicUrl = function(fn)
|
|
{
|
|
this.ui.drive.executeRequest({
|
|
url: '/files/' + this.desc.id + '/permissions?supportsAllDrives=true'
|
|
},
|
|
mxUtils.bind(this, function(resp)
|
|
{
|
|
if (resp != null && resp.items != null)
|
|
{
|
|
for (var i = 0; i < resp.items.length; i++)
|
|
{
|
|
if (resp.items[i].id === 'anyoneWithLink' ||
|
|
resp.items[i].id === 'anyone')
|
|
{
|
|
fn(this.desc.webContentLink);
|
|
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
fn(null);
|
|
}), mxUtils.bind(this, function()
|
|
{
|
|
fn(null)
|
|
}));
|
|
};
|
|
|
|
/**
|
|
* Overridden to enable the autosave option in the document properties dialog
|
|
* if realtime is not used.
|
|
*/
|
|
DriveFile.prototype.isAutosaveOptional = function()
|
|
{
|
|
return true;
|
|
};
|
|
|
|
/**
|
|
* Translates this point by the given vector.
|
|
*
|
|
* @param {number} dx X-coordinate of the translation.
|
|
* @param {number} dy Y-coordinate of the translation.
|
|
*/
|
|
DriveFile.prototype.isRenamable = function()
|
|
{
|
|
return this.isEditable() && DrawioFile.prototype.isEditable.apply(this, arguments);
|
|
};
|
|
|
|
/**
|
|
* Translates this point by the given vector.
|
|
*
|
|
* @param {number} dx X-coordinate of the translation.
|
|
* @param {number} dy Y-coordinate of the translation.
|
|
*/
|
|
DriveFile.prototype.isMovable = function()
|
|
{
|
|
return this.isEditable();
|
|
};
|
|
|
|
/**
|
|
* Translates this point by the given vector.
|
|
*
|
|
* @param {number} dx X-coordinate of the translation.
|
|
* @param {number} dy Y-coordinate of the translation.
|
|
*/
|
|
DriveFile.prototype.isTrashed = function()
|
|
{
|
|
return this.desc.labels.trashed;
|
|
};
|
|
|
|
/**
|
|
* Translates this point by the given vector.
|
|
*
|
|
* @param {number} dx X-coordinate of the translation.
|
|
* @param {number} dy Y-coordinate of the translation.
|
|
*/
|
|
DriveFile.prototype.save = function(revision, success, error, unloading, overwrite)
|
|
{
|
|
DrawioFile.prototype.save.apply(this, [revision, mxUtils.bind(this, function()
|
|
{
|
|
this.saveFile(null, revision, success, error, unloading, overwrite);
|
|
}), error, unloading, overwrite]);
|
|
};
|
|
|
|
/**
|
|
* Translates this point by the given vector.
|
|
*
|
|
* @param {number} dx X-coordinate of the translation.
|
|
* @param {number} dy Y-coordinate of the translation.
|
|
*/
|
|
DriveFile.prototype.saveFile = function(title, revision, success, error, unloading, overwrite)
|
|
{
|
|
try
|
|
{
|
|
if (!this.isEditable())
|
|
{
|
|
if (success != null)
|
|
{
|
|
success();
|
|
}
|
|
}
|
|
else if (!this.savingFile)
|
|
{
|
|
// Sets shadow modified state during save
|
|
this.savingFileTime = new Date();
|
|
this.setShadowModified(false);
|
|
this.savingFile = true;
|
|
|
|
this.createSecret(mxUtils.bind(this, function(secret, token)
|
|
{
|
|
var doSave = mxUtils.bind(this, function(realOverwrite, realRevision)
|
|
{
|
|
try
|
|
{
|
|
var lastDesc = this.desc;
|
|
|
|
this.ui.drive.saveFile(this, realRevision, mxUtils.bind(this, function(resp, savedData)
|
|
{
|
|
try
|
|
{
|
|
this.savingFile = false;
|
|
|
|
// Handles special case where resp is false eg
|
|
// if the old file was converted to realtime
|
|
if (resp != false)
|
|
{
|
|
// Checks for changes during save
|
|
this.setModified(this.getShadowModified());
|
|
|
|
if (revision)
|
|
{
|
|
this.lastAutosaveRevision = new Date().getTime();
|
|
}
|
|
|
|
// Adaptive autosave delay
|
|
this.autosaveDelay = Math.round(Math.min(10000,
|
|
Math.max(DriveFile.prototype.autosaveDelay,
|
|
this.saveDelay)));
|
|
this.desc = resp;
|
|
|
|
// Shows possible errors but keeps the modified flag as the
|
|
// file was saved but the cache entry could not be written
|
|
if (token != null)
|
|
{
|
|
this.fileSaved(savedData, lastDesc, mxUtils.bind(this, function()
|
|
{
|
|
this.contentChanged();
|
|
|
|
if (success != null)
|
|
{
|
|
success(resp);
|
|
}
|
|
}), error, token);
|
|
}
|
|
else if (success != null)
|
|
{
|
|
success(resp);
|
|
}
|
|
}
|
|
else if (error != null)
|
|
{
|
|
error(resp);
|
|
}
|
|
}
|
|
catch (e)
|
|
{
|
|
this.savingFile = false;
|
|
|
|
if (error != null)
|
|
{
|
|
error(e);
|
|
}
|
|
else
|
|
{
|
|
throw e;
|
|
}
|
|
}
|
|
}), mxUtils.bind(this, function(err, desc)
|
|
{
|
|
try
|
|
{
|
|
this.savingFile = false;
|
|
|
|
if (this.isConflict(err))
|
|
{
|
|
this.inConflictState = true;
|
|
|
|
if (this.sync != null)
|
|
{
|
|
this.savingFile = true;
|
|
|
|
this.sync.fileConflict(desc, mxUtils.bind(this, function()
|
|
{
|
|
// Adds random cool-off
|
|
window.setTimeout(mxUtils.bind(this, function()
|
|
{
|
|
this.updateFileData();
|
|
this.setShadowModified(false);
|
|
doSave(realOverwrite, true);
|
|
}), 100 + Math.random() * 500);
|
|
}), mxUtils.bind(this, function()
|
|
{
|
|
this.savingFile = false;
|
|
|
|
if (error != null)
|
|
{
|
|
error();
|
|
}
|
|
}));
|
|
}
|
|
else if (error != null)
|
|
{
|
|
error();
|
|
}
|
|
}
|
|
else if (error != null)
|
|
{
|
|
error(err);
|
|
}
|
|
}
|
|
catch (e)
|
|
{
|
|
this.savingFile = false;
|
|
|
|
if (error != null)
|
|
{
|
|
error(e);
|
|
}
|
|
else
|
|
{
|
|
throw e;
|
|
}
|
|
}
|
|
}), unloading, unloading, realOverwrite, null, secret);
|
|
}
|
|
catch (e)
|
|
{
|
|
this.savingFile = false;
|
|
|
|
if (error != null)
|
|
{
|
|
error(e);
|
|
}
|
|
else
|
|
{
|
|
throw e;
|
|
}
|
|
}
|
|
});
|
|
|
|
doSave(overwrite, revision);
|
|
}));
|
|
}
|
|
}
|
|
catch (e)
|
|
{
|
|
if (error != null)
|
|
{
|
|
error(e);
|
|
}
|
|
else
|
|
{
|
|
throw e;
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Shows a conflict dialog to the user.
|
|
*/
|
|
DriveFile.prototype.copyFile = function(success, error)
|
|
{
|
|
if (!this.isRestricted())
|
|
{
|
|
this.makeCopy(mxUtils.bind(this, function()
|
|
{
|
|
if (this.ui.spinner.spin(document.body, mxResources.get('saving')))
|
|
{
|
|
try
|
|
{
|
|
this.save(true, success, error)
|
|
}
|
|
catch (e)
|
|
{
|
|
error(e);
|
|
}
|
|
}
|
|
}), error, true);
|
|
}
|
|
else
|
|
{
|
|
DrawioFile.prototype.copyFile.apply(this, arguments);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Shows a conflict dialog to the user.
|
|
*/
|
|
DriveFile.prototype.makeCopy = function(success, error, timestamp)
|
|
{
|
|
if (this.ui.spinner.spin(document.body, mxResources.get('saving')))
|
|
{
|
|
// Uses copyFile internally which is a remote REST call with the advantage of keeping
|
|
// the parents of the file in-place, but copies the remote file contents so needs to
|
|
// be updated as soon as we have the ID.
|
|
this.saveAs(this.ui.getCopyFilename(this, timestamp), mxUtils.bind(this, function(resp)
|
|
{
|
|
this.desc = resp;
|
|
this.ui.spinner.stop();
|
|
this.setModified(false);
|
|
|
|
this.backupPatch = null;
|
|
this.invalidChecksum = false;
|
|
this.inConflictState = false;
|
|
|
|
this.descriptorChanged();
|
|
success();
|
|
}), mxUtils.bind(this, function()
|
|
{
|
|
this.ui.spinner.stop();
|
|
|
|
if (error != null)
|
|
{
|
|
error();
|
|
}
|
|
}));
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Translates this point by the given vector.
|
|
*
|
|
* @param {number} dx X-coordinate of the translation.
|
|
* @param {number} dy Y-coordinate of the translation.
|
|
*/
|
|
DriveFile.prototype.saveAs = function(filename, success, error)
|
|
{
|
|
this.ui.drive.copyFile(this.getId(), filename, success, error);
|
|
};
|
|
|
|
/**
|
|
* Translates this point by the given vector.
|
|
*
|
|
* @param {number} dx X-coordinate of the translation.
|
|
* @param {number} dy Y-coordinate of the translation.
|
|
*/
|
|
DriveFile.prototype.rename = function(title, success, error)
|
|
{
|
|
var etag = this.getCurrentEtag();
|
|
|
|
this.ui.drive.renameFile(this.getId(), title, mxUtils.bind(this, function(desc)
|
|
{
|
|
if (!this.hasSameExtension(title, this.getTitle()))
|
|
{
|
|
this.desc = desc;
|
|
|
|
if (this.sync != null)
|
|
{
|
|
this.sync.descriptorChanged(etag);
|
|
}
|
|
|
|
this.save(true, success, error);
|
|
}
|
|
else
|
|
{
|
|
this.desc = desc;
|
|
this.descriptorChanged();
|
|
|
|
if (this.sync != null)
|
|
{
|
|
this.sync.descriptorChanged(etag);
|
|
}
|
|
|
|
if (success != null)
|
|
{
|
|
success(desc);
|
|
}
|
|
}
|
|
}), error);
|
|
};
|
|
|
|
/**
|
|
* Translates this point by the given vector.
|
|
*
|
|
* @param {number} dx X-coordinate of the translation.
|
|
* @param {number} dy Y-coordinate of the translation.
|
|
*/
|
|
DriveFile.prototype.move = function(folderId, success, error)
|
|
{
|
|
this.ui.drive.moveFile(this.getId(), folderId, mxUtils.bind(this, function(resp)
|
|
{
|
|
this.desc = resp;
|
|
this.descriptorChanged();
|
|
|
|
if (success != null)
|
|
{
|
|
success(resp);
|
|
}
|
|
}), error);
|
|
};
|
|
|
|
/**
|
|
* Translates this point by the given vector.
|
|
*
|
|
* @param {number} dx X-coordinate of the translation.
|
|
* @param {number} dy Y-coordinate of the translation.
|
|
*/
|
|
DriveFile.prototype.share = function()
|
|
{
|
|
this.ui.drive.showPermissions(this.getId());
|
|
};
|
|
|
|
/**
|
|
* Translates this point by the given vector.
|
|
*
|
|
* @param {number} dx X-coordinate of the translation.
|
|
* @param {number} dy Y-coordinate of the translation.
|
|
*/
|
|
DriveFile.prototype.getTitle = function()
|
|
{
|
|
return this.desc.title;
|
|
};
|
|
|
|
/**
|
|
* Translates this point by the given vector.
|
|
*
|
|
* @param {number} dx X-coordinate of the translation.
|
|
* @param {number} dy Y-coordinate of the translation.
|
|
*/
|
|
DriveFile.prototype.getHash = function()
|
|
{
|
|
return 'G' + this.getId();
|
|
};
|
|
|
|
/**
|
|
* Translates this point by the given vector.
|
|
*
|
|
* @param {number} dx X-coordinate of the translation.
|
|
* @param {number} dy Y-coordinate of the translation.
|
|
*/
|
|
DriveFile.prototype.getId = function()
|
|
{
|
|
return this.desc.id;
|
|
};
|
|
|
|
/**
|
|
* Translates this point by the given vector.
|
|
*
|
|
* @param {number} dx X-coordinate of the translation.
|
|
* @param {number} dy Y-coordinate of the translation.
|
|
*/
|
|
DriveFile.prototype.isEditable = function()
|
|
{
|
|
return DrawioFile.prototype.isEditable.apply(this, arguments) &&
|
|
this.desc.editable;
|
|
};
|
|
|
|
/**
|
|
* Hook for subclassers.
|
|
*/
|
|
DriveFile.prototype.isSyncSupported = function()
|
|
{
|
|
return true;
|
|
};
|
|
|
|
/**
|
|
* Hook for subclassers.
|
|
*/
|
|
DriveFile.prototype.isRevisionHistorySupported = function()
|
|
{
|
|
return true;
|
|
};
|
|
|
|
/**
|
|
* Hook for subclassers.
|
|
*/
|
|
DriveFile.prototype.getRevisions = function(success, error)
|
|
{
|
|
this.ui.drive.executeRequest(
|
|
{
|
|
url: '/files/' + this.getId() + '/revisions'
|
|
},
|
|
mxUtils.bind(this, function(resp)
|
|
{
|
|
for (var i = 0; i < resp.items.length; i++)
|
|
{
|
|
(mxUtils.bind(this, function(item)
|
|
{
|
|
// Redirects title to originalFilename to
|
|
// match expected descriptor interface
|
|
item.title = item.originalFilename;
|
|
|
|
item.getXml = mxUtils.bind(this, function(itemSuccess, itemError)
|
|
{
|
|
this.ui.drive.getXmlFile(item, mxUtils.bind(this, function(file)
|
|
{
|
|
itemSuccess(file.getData());
|
|
}), itemError);
|
|
});
|
|
|
|
item.getUrl = mxUtils.bind(this, function(page)
|
|
{
|
|
return this.ui.getUrl(window.location.pathname + '?rev=' + item.id +
|
|
'&chrome=0&nav=1&layers=1&edit=_blank' + ((page != null) ?
|
|
'&page=' + page : '')) + window.location.hash;
|
|
});
|
|
}))(resp.items[i]);
|
|
}
|
|
|
|
success(resp.items);
|
|
}), error);
|
|
};
|
|
|
|
/**
|
|
* Adds the listener for automatically saving the diagram for local changes.
|
|
*/
|
|
DriveFile.prototype.getLatestVersion = function(success, error)
|
|
{
|
|
this.ui.drive.getFile(this.getId(), success, error, true);
|
|
};
|
|
|
|
/**
|
|
* Adds all listeners.
|
|
*/
|
|
DriveFile.prototype.getChannelId = function()
|
|
{
|
|
var chan = this.ui.drive.getCustomProperty(this.desc, 'channel');
|
|
|
|
if (chan != null)
|
|
{
|
|
chan = 'G-' + this.getId() + '.' + chan;
|
|
}
|
|
|
|
return chan;
|
|
};
|
|
|
|
/**
|
|
* Gets the channel ID from the given descriptor.
|
|
*/
|
|
DriveFile.prototype.getChannelKey = function()
|
|
{
|
|
return this.ui.drive.getCustomProperty(this.desc, 'key');
|
|
};
|
|
|
|
/**
|
|
* Adds all listeners.
|
|
*/
|
|
DriveFile.prototype.getLastModifiedDate = function()
|
|
{
|
|
return new Date(this.desc.modifiedDate);
|
|
};
|
|
|
|
/**
|
|
* Adds all listeners.
|
|
*/
|
|
DriveFile.prototype.getDescriptor = function()
|
|
{
|
|
return this.desc;
|
|
};
|
|
|
|
/**
|
|
* Updates the descriptor of this file with the one from the given file.
|
|
*/
|
|
DriveFile.prototype.setDescriptor = function(desc)
|
|
{
|
|
this.desc = desc;
|
|
};
|
|
|
|
/**
|
|
* Returns the etag from the given descriptor.
|
|
*/
|
|
DriveFile.prototype.getDescriptorSecret = function(desc)
|
|
{
|
|
return this.ui.drive.getCustomProperty(desc, 'secret');
|
|
};
|
|
|
|
/**
|
|
* Updates the revision ID on the given descriptor.
|
|
*/
|
|
DriveFile.prototype.setDescriptorRevisionId = function(desc, id)
|
|
{
|
|
desc.headRevisionId = id;
|
|
};
|
|
|
|
/**
|
|
* Returns the revision ID from the given descriptor.
|
|
*/
|
|
DriveFile.prototype.getDescriptorRevisionId = function(desc)
|
|
{
|
|
return desc.headRevisionId;
|
|
};
|
|
|
|
/**
|
|
* Adds all listeners.
|
|
*/
|
|
DriveFile.prototype.getDescriptorEtag = function(desc)
|
|
{
|
|
return desc.etag;
|
|
};
|
|
|
|
/**
|
|
* Adds the listener for automatically saving the diagram for local changes.
|
|
*/
|
|
DriveFile.prototype.setDescriptorEtag = function(desc, etag)
|
|
{
|
|
desc.etag = etag;
|
|
};
|
|
|
|
/**
|
|
* Adds the listener for automatically saving the diagram for local changes.
|
|
*/
|
|
DriveFile.prototype.loadPatchDescriptor = function(success, error)
|
|
{
|
|
this.ui.drive.executeRequest(
|
|
{
|
|
url: '/files/' + this.getId() + '?supportsAllDrives=true&fields=' + this.ui.drive.catchupFields
|
|
},
|
|
mxUtils.bind(this, function(desc)
|
|
{
|
|
success(desc);
|
|
}), error);
|
|
};
|
|
|
|
/**
|
|
* Adds the listener for automatically saving the diagram for local changes.
|
|
*/
|
|
DriveFile.prototype.patchDescriptor = function(desc, patch)
|
|
{
|
|
desc.headRevisionId = patch.headRevisionId;
|
|
desc.modifiedDate = patch.modifiedDate;
|
|
|
|
DrawioFile.prototype.patchDescriptor.apply(this, arguments);
|
|
};
|
|
|
|
/**
|
|
* Adds the listener for automatically saving the diagram for local changes.
|
|
*/
|
|
DriveFile.prototype.loadDescriptor = function(success, error)
|
|
{
|
|
this.ui.drive.loadDescriptor(this.getId(), success, error);
|
|
};
|
|
|
|
/**
|
|
* Are comments supported
|
|
*/
|
|
DriveFile.prototype.commentsSupported = function()
|
|
{
|
|
return true;
|
|
};
|
|
|
|
/**
|
|
* Get comments of the file
|
|
*/
|
|
DriveFile.prototype.getComments = function(success, error)
|
|
{
|
|
var currentUser = this.ui.getCurrentUser();
|
|
|
|
function driveCommentToDrawio(file, gComment, pCommentId)
|
|
{
|
|
if (gComment.deleted) return null; //skip deleted comments
|
|
|
|
var comment = new DriveComment(file, gComment.commentId || gComment.replyId, gComment.content,
|
|
gComment.modifiedDate, gComment.createdDate, gComment.status == 'resolved',
|
|
gComment.author.isAuthenticatedUser? currentUser :
|
|
new DrawioUser(gComment.author.permissionId, gComment.author.emailAddress,
|
|
gComment.author.displayName, gComment.author.picture.url), pCommentId);
|
|
|
|
for (var i = 0; gComment.replies != null && i < gComment.replies.length; i++)
|
|
{
|
|
comment.addReplyDirect(driveCommentToDrawio(file, gComment.replies[i], gComment.commentId));
|
|
}
|
|
|
|
return comment;
|
|
};
|
|
|
|
this.ui.drive.executeRequest(
|
|
{
|
|
url: '/files/' + this.getId() + '/comments'
|
|
},
|
|
mxUtils.bind(this, function(resp)
|
|
{
|
|
var comments = [];
|
|
|
|
for (var i = 0; i < resp.items.length; i++)
|
|
{
|
|
var comment = driveCommentToDrawio(this, resp.items[i]);
|
|
|
|
if (comment != null) comments.push(comment);
|
|
}
|
|
|
|
success(comments);
|
|
}), error);
|
|
};
|
|
|
|
/**
|
|
* Add a comment to the file
|
|
*/
|
|
DriveFile.prototype.addComment = function(comment, success, error)
|
|
{
|
|
var body = {'content': comment.content};
|
|
|
|
this.ui.drive.executeRequest(
|
|
{
|
|
url: '/files/' + this.getId() + '/comments',
|
|
method: 'POST',
|
|
params: body
|
|
},
|
|
mxUtils.bind(this, function(resp)
|
|
{
|
|
success(resp.commentId); //pass comment id
|
|
}), error);
|
|
};
|
|
|
|
/**
|
|
* Can add a reply to a reply
|
|
*/
|
|
DriveFile.prototype.canReplyToReplies = function()
|
|
{
|
|
return false;
|
|
};
|
|
|
|
/**
|
|
* Can add comments (The permission to comment to this file)
|
|
*/
|
|
DriveFile.prototype.canComment = function()
|
|
{
|
|
return this.desc.canComment;
|
|
};
|
|
|
|
/**
|
|
* Get a new comment object
|
|
*/
|
|
DriveFile.prototype.newComment = function(content, user)
|
|
{
|
|
return new DriveComment(this, null, content, Date.now(), Date.now(), false, user);
|
|
};
|