Stackedit/src/services/providers/googleDriveProvider.js

213 lines
7.0 KiB
JavaScript
Raw Normal View History

import store from '../../store';
import googleHelper from './helpers/googleHelper';
2018-04-27 14:37:05 +00:00
import Provider from './common/Provider';
import utils from '../utils';
2018-04-27 14:37:05 +00:00
export default new Provider({
2017-09-23 19:01:50 +00:00
id: 'googleDrive',
getToken(location) {
const token = store.getters['data/googleTokens'][location.sub];
return token && token.isDrive ? token : null;
},
getUrl(location) {
return `https://docs.google.com/file/d/${location.driveFileId}/edit`;
},
getDescription(location) {
const token = this.getToken(location);
return `${location.driveFileId}${token.name}`;
},
2018-01-04 20:19:10 +00:00
initAction() {
const state = googleHelper.driveState || {};
return state.userId && Promise.resolve()
.then(() => {
// Try to find the token corresponding to the user ID
const token = store.getters['data/googleTokens'][state.userId];
// If not found or not enough permission, popup an OAuth2 window
return token && token.isDrive ? token : store.dispatch('modal/open', {
type: 'googleDriveAccount',
onResolve: () => googleHelper.addDriveAccount(
!store.getters['data/localSettings'].googleDriveRestrictedAccess,
state.userId,
),
});
})
.then((token) => {
const openWorkspaceIfExists = (file) => {
const folderId = file
&& file.appProperties
&& file.appProperties.folderId;
if (folderId) {
// See if we have the corresponding workspace
const workspaceParams = {
providerId: 'googleDriveWorkspace',
folderId,
};
const workspaceId = utils.makeWorkspaceId(workspaceParams);
const workspace = store.getters['data/sanitizedWorkspaces'][workspaceId];
// If we have the workspace, open it by changing the current URL
if (workspace) {
utils.setQueryParams(workspaceParams);
}
}
};
2018-01-04 20:19:10 +00:00
switch (state.action) {
case 'create':
default:
// See if folder is part of a workspace we can open
return googleHelper.getFile(token, state.folderId)
.then((folder) => {
folder.appProperties = folder.appProperties || {};
googleHelper.driveActionFolder = folder;
openWorkspaceIfExists(folder);
2018-01-04 20:19:10 +00:00
}, (err) => {
if (!err || err.status !== 404) {
throw err;
}
// We received an HTTP 404 meaning we have no permission to read the folder
2018-01-04 20:19:10 +00:00
googleHelper.driveActionFolder = { id: state.folderId };
});
case 'open': {
const getOneFile = (ids = state.ids || []) => {
2018-01-04 20:19:10 +00:00
const id = ids.shift();
return id && googleHelper.getFile(token, id)
.then((file) => {
file.appProperties = file.appProperties || {};
googleHelper.driveActionFiles.push(file);
return getOneFile(ids);
});
};
return getOneFile()
// Check if first file is part of a workspace
.then(() => openWorkspaceIfExists(googleHelper.driveActionFiles[0]));
2018-01-04 20:19:10 +00:00
}
}
});
},
performAction() {
return Promise.resolve()
2018-01-04 20:19:10 +00:00
.then(() => {
const state = googleHelper.driveState || {};
const token = store.getters['data/googleTokens'][state.userId];
switch (token && state.action) {
2018-01-04 20:19:10 +00:00
case 'create':
return store.dispatch('createFile')
.then((file) => {
store.commit('file/setCurrentId', file.id);
// Return a new syncLocation
return this.makeLocation(token, null, googleHelper.driveActionFolder.id);
});
case 'open':
return store.dispatch('queue/enqueue',
() => this.openFiles(token, googleHelper.driveActionFiles));
default:
return null;
2018-01-04 20:19:10 +00:00
}
});
},
downloadContent(token, syncLocation) {
return googleHelper.downloadFile(token, syncLocation.driveFileId)
2018-04-27 14:37:05 +00:00
.then(content => Provider.parseContent(content, `${syncLocation.fileId}/content`));
},
2017-09-23 19:01:50 +00:00
uploadContent(token, content, syncLocation, ifNotTooLate) {
const file = store.state.file.itemMap[syncLocation.fileId];
const name = utils.sanitizeName(file && file.name);
const parents = [];
if (syncLocation.driveParentId) {
parents.push(syncLocation.driveParentId);
}
2017-09-23 19:01:50 +00:00
return googleHelper.uploadFile(
token,
name,
parents,
2017-12-10 23:49:20 +00:00
undefined,
2018-04-27 14:37:05 +00:00
Provider.serializeContent(content),
2017-09-23 19:01:50 +00:00
undefined,
syncLocation.driveFileId,
undefined,
ifNotTooLate,
)
.then(driveFile => ({
...syncLocation,
driveFileId: driveFile.id,
}));
},
2017-09-23 19:01:50 +00:00
publish(token, html, metadata, publishLocation) {
return googleHelper.uploadFile(
token,
metadata.title,
[],
2017-12-10 23:49:20 +00:00
undefined,
2017-09-23 19:01:50 +00:00
html,
publishLocation.templateId ? 'text/html' : undefined,
publishLocation.driveFileId,
)
.then(driveFile => ({
...publishLocation,
driveFileId: driveFile.id,
}));
},
openFiles(token, driveFiles) {
const openOneFile = () => {
2018-01-04 20:19:10 +00:00
const driveFile = driveFiles.shift();
if (!driveFile) {
return null;
}
2018-04-27 14:37:05 +00:00
if (Provider.openFileWithLocation(store.getters['syncLocation/items'], {
providerId: this.id,
driveFileId: driveFile.id,
})) {
// File exists and has just been opened. Next...
return openOneFile();
}
// Download content from Google Drive and create the file
const syncLocation = {
driveFileId: driveFile.id,
2017-09-23 19:01:50 +00:00
providerId: this.id,
sub: token.sub,
};
return this.downloadContent(token, syncLocation)
.then((content) => {
const id = utils.uid();
delete content.history;
store.commit('content/setItem', {
...content,
id: `${id}/content`,
});
store.commit('file/setItem', {
id,
name: utils.sanitizeName(driveFile.name),
parentId: store.getters['file/current'].parentId,
});
store.commit('syncLocation/setItem', {
...syncLocation,
id: utils.uid(),
fileId: id,
});
store.commit('file/setCurrentId', id);
2017-09-23 19:01:50 +00:00
store.dispatch('notification/info', `${store.getters['file/current'].name} was imported from Google Drive.`);
}, () => {
store.dispatch('notification/error', `Could not open file ${driveFile.id}.`);
})
.then(() => openOneFile());
};
return Promise.resolve()
.then(() => openOneFile());
},
2017-09-23 19:01:50 +00:00
makeLocation(token, fileId, folderId) {
const location = {
providerId: this.id,
sub: token.sub,
};
if (fileId) {
location.driveFileId = fileId;
}
if (folderId) {
location.driveParentId = folderId;
}
return location;
},
});