| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916 |
- /**
- * 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 DrawioFile.RESTRICT_EXPORT || (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.getFileUrl = function()
- {
- return 'https://drive.google.com/open?authuser=0&id=' + this.getId();
- };
- /**
- * Returns true if copy, export and print are not allowed for this file.
- */
- DriveFile.prototype.getFolderUrl = function()
- {
- if (this.desc.labels != null && this.desc.labels.trashed)
- {
- return 'https://drive.google.com/drive/trash';
- }
- else
- {
- return (this.desc.parents != null && this.desc.parents.length > 0) ?
- 'https://drive.google.com/drive/folders/' +
- this.desc.parents[0].id : null;
- }
- };
- /**
- * 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;
-
- if (this.sync != null)
- {
- this.sync.fileSaving();
- }
-
- this.ui.drive.saveFile(this, realRevision, mxUtils.bind(this, function(resp, savedData, pages, checksum)
- {
- 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;
-
- this.fileSaved(savedData, lastDesc, mxUtils.bind(this, function()
- {
- this.contentChanged();
-
- if (success != null)
- {
- success(resp);
- }
- }), error, token, pages, checksum);
- }
- 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.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 rev = this.getCurrentRevisionId();
-
- 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(rev);
- }
-
- this.save(true, success, error);
- }
- else
- {
- this.desc = desc;
- this.descriptorChanged();
-
- if (this.sync != null)
- {
- this.sync.descriptorChanged(rev);
- }
-
- 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(), this);
- };
- /**
- * 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.isRealtimeSupported = function()
- {
- return true;
- };
- /**
- * Returns true if all changes should be sent out immediately.
- */
- DriveFile.prototype.isRealtimeOptional = function()
- {
- return this.sync != null && this.sync.isConnected();
- };
- /**
- * Returns true if all changes should be sent out immediately.
- */
- DriveFile.prototype.setRealtimeEnabled = function(value, success, error)
- {
- if (this.sync != null)
- {
- this.ui.drive.executeRequest({
- 'url': '/files/' + this.getId() + '/properties?alt=json&supportsAllDrives=true',
- 'method': 'POST',
- 'contentType': 'application/json; charset=UTF-8',
- 'params': {
- 'key': 'collaboration',
- 'value': (value) ? 'enabled' :
- ((urlParams['fast-sync'] != '0') ?
- 'disabled' : '')
- }
- }, mxUtils.bind(this, function()
- {
- this.loadDescriptor(mxUtils.bind(this, function(desc)
- {
- if (desc != null)
- {
- this.sync.descriptorChanged(this.getCurrentEtag());
- this.sync.updateDescriptor(desc);
- success();
- }
- else
- {
- error();
- }
- }), error);
- }), error);
- }
- else
- {
- error();
- }
- };
- /**
- * Returns true if all changes should be sent out immediately.
- */
- DriveFile.prototype.isRealtimeEnabled = function()
- {
- var collab = this.ui.drive.getCustomProperty(this.desc, 'collaboration');
- return (DrawioFile.prototype.isRealtimeEnabled.apply(this, arguments) &&
- collab != 'disabled') || (Editor.enableRealtime && collab == 'enabled');
- };
- /**
- * 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 checksum from the given descriptor.
- */
- DriveFile.prototype.getDescriptorChecksum = function(desc)
- {
- var value = this.ui.drive.getCustomProperty(desc, 'checksum');
- var secret = this.getDescriptorSecret(desc);
- var result = null;
- if (value != null && secret != null)
- {
- tokens = value.split(':');
- // Checks if checksum matches current secret
- if (tokens.length == 2 && tokens[0] == secret)
- {
- result = tokens[1];
- }
- }
- return result;
- };
- /**
- * Returns the secret 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);
- };
|