2018-01-24 07:31:54 +00:00
|
|
|
import store from '../../store';
|
|
|
|
import couchdbHelper from './helpers/couchdbHelper';
|
2018-04-27 14:37:05 +00:00
|
|
|
import Provider from './common/Provider';
|
2018-01-24 07:31:54 +00:00
|
|
|
import utils from '../utils';
|
|
|
|
|
2018-04-27 14:37:05 +00:00
|
|
|
let syncLastSeq;
|
|
|
|
|
|
|
|
export default new Provider({
|
2018-01-24 07:31:54 +00:00
|
|
|
id: 'couchdbWorkspace',
|
|
|
|
getToken() {
|
|
|
|
return store.getters['workspace/syncToken'];
|
|
|
|
},
|
2018-05-13 13:27:33 +00:00
|
|
|
async initWorkspace() {
|
2018-01-24 07:31:54 +00:00
|
|
|
const dbUrl = (utils.queryParams.dbUrl || '').replace(/\/?$/, ''); // Remove trailing /
|
2018-04-27 14:37:05 +00:00
|
|
|
const workspaceParams = {
|
2018-01-24 07:31:54 +00:00
|
|
|
providerId: this.id,
|
|
|
|
dbUrl,
|
|
|
|
};
|
2018-04-27 14:37:05 +00:00
|
|
|
const workspaceId = utils.makeWorkspaceId(workspaceParams);
|
2018-01-24 07:31:54 +00:00
|
|
|
const getToken = () => store.getters['data/couchdbTokens'][workspaceId];
|
|
|
|
const getWorkspace = () => store.getters['data/sanitizedWorkspaces'][workspaceId];
|
|
|
|
|
|
|
|
if (!getToken()) {
|
|
|
|
// Create token
|
|
|
|
store.dispatch('data/setCouchdbToken', {
|
|
|
|
sub: workspaceId,
|
|
|
|
dbUrl,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-05-13 13:27:33 +00:00
|
|
|
// Create the workspace
|
|
|
|
let workspace = getWorkspace();
|
|
|
|
if (!workspace) {
|
|
|
|
// Make sure the database exists and retrieve its name
|
|
|
|
let db;
|
|
|
|
try {
|
|
|
|
db = await couchdbHelper.getDb(getToken());
|
|
|
|
} catch (e) {
|
|
|
|
throw new Error(`${dbUrl} is not accessible. Make sure you have the proper permissions.`);
|
|
|
|
}
|
|
|
|
store.dispatch('data/patchWorkspaces', {
|
|
|
|
[workspaceId]: {
|
|
|
|
id: workspaceId,
|
|
|
|
name: db.db_name,
|
|
|
|
providerId: this.id,
|
|
|
|
dbUrl,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
workspace = getWorkspace();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fix the URL hash
|
|
|
|
utils.setQueryParams(workspaceParams);
|
|
|
|
if (workspace.url !== window.location.href) {
|
|
|
|
store.dispatch('data/patchWorkspaces', {
|
|
|
|
[workspace.id]: {
|
|
|
|
...workspace,
|
|
|
|
url: window.location.href,
|
|
|
|
},
|
2018-01-24 07:31:54 +00:00
|
|
|
});
|
2018-05-13 13:27:33 +00:00
|
|
|
}
|
|
|
|
return getWorkspace();
|
2018-01-24 07:31:54 +00:00
|
|
|
},
|
2018-05-13 13:27:33 +00:00
|
|
|
async getChanges() {
|
2018-01-24 07:31:54 +00:00
|
|
|
const syncToken = store.getters['workspace/syncToken'];
|
|
|
|
const lastSeq = store.getters['data/localSettings'].syncLastSeq;
|
2018-05-13 13:27:33 +00:00
|
|
|
const result = await couchdbHelper.getChanges(syncToken, lastSeq);
|
|
|
|
const changes = result.changes.filter((change) => {
|
|
|
|
if (!change.deleted && change.doc) {
|
|
|
|
change.item = change.doc.item;
|
|
|
|
if (!change.item || !change.item.id || !change.item.type) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
// Build sync data
|
|
|
|
change.syncData = {
|
|
|
|
id: change.id,
|
|
|
|
itemId: change.item.id,
|
|
|
|
type: change.item.type,
|
|
|
|
hash: change.item.hash,
|
|
|
|
rev: change.doc._rev, // eslint-disable-line no-underscore-dangle
|
|
|
|
};
|
|
|
|
}
|
|
|
|
change.syncDataId = change.id;
|
|
|
|
return true;
|
|
|
|
});
|
|
|
|
syncLastSeq = result.lastSeq;
|
|
|
|
return changes;
|
2018-01-24 07:31:54 +00:00
|
|
|
},
|
2018-04-27 14:37:05 +00:00
|
|
|
onChangesApplied() {
|
2018-01-30 07:36:33 +00:00
|
|
|
store.dispatch('data/patchLocalSettings', {
|
2018-04-27 14:37:05 +00:00
|
|
|
syncLastSeq,
|
2018-01-30 07:36:33 +00:00
|
|
|
});
|
|
|
|
},
|
2018-06-07 23:56:11 +00:00
|
|
|
async saveWorkspaceItem(item, syncData) {
|
2018-01-30 07:36:33 +00:00
|
|
|
const syncToken = store.getters['workspace/syncToken'];
|
2018-05-13 13:27:33 +00:00
|
|
|
const { id, rev } = couchdbHelper.uploadDocument({
|
|
|
|
token: syncToken,
|
2018-01-30 07:36:33 +00:00
|
|
|
item,
|
2018-05-13 13:27:33 +00:00
|
|
|
documentId: syncData && syncData.id,
|
|
|
|
rev: syncData && syncData.rev,
|
|
|
|
});
|
|
|
|
return {
|
|
|
|
// Build sync data
|
|
|
|
id,
|
|
|
|
itemId: item.id,
|
|
|
|
type: item.type,
|
|
|
|
hash: item.hash,
|
|
|
|
rev,
|
|
|
|
};
|
2018-01-30 07:36:33 +00:00
|
|
|
},
|
2018-06-07 23:56:11 +00:00
|
|
|
removeWorkspaceItem(syncData) {
|
2018-01-30 07:36:33 +00:00
|
|
|
const syncToken = store.getters['workspace/syncToken'];
|
|
|
|
return couchdbHelper.removeDocument(syncToken, syncData.id, syncData.rev);
|
|
|
|
},
|
2018-06-07 23:56:11 +00:00
|
|
|
async downloadWorkspaceContent(token, syncData) {
|
|
|
|
const body = await couchdbHelper.retrieveDocumentWithAttachments(token, syncData.id);
|
|
|
|
const rev = body._rev; // eslint-disable-line no-underscore-dangle
|
|
|
|
const item = Provider.parseContent(body.attachments.data, body.item.id);
|
|
|
|
return {
|
|
|
|
item,
|
|
|
|
syncData: {
|
|
|
|
...syncData,
|
|
|
|
hash: item.hash,
|
|
|
|
rev,
|
|
|
|
},
|
|
|
|
};
|
2018-01-30 07:36:33 +00:00
|
|
|
},
|
2018-06-07 23:56:11 +00:00
|
|
|
async downloadWorkspaceData(token, dataId, syncData) {
|
2018-01-30 07:36:33 +00:00
|
|
|
if (!syncData) {
|
2018-06-07 23:56:11 +00:00
|
|
|
return {};
|
2018-05-13 13:27:33 +00:00
|
|
|
}
|
2018-06-07 23:56:11 +00:00
|
|
|
|
|
|
|
const body = await couchdbHelper.retrieveDocumentWithAttachments(token, syncData.id);
|
|
|
|
const item = utils.addItemHash(JSON.parse(body.attachments.data));
|
2018-05-13 13:27:33 +00:00
|
|
|
const rev = body._rev; // eslint-disable-line no-underscore-dangle
|
2018-06-07 23:56:11 +00:00
|
|
|
return {
|
|
|
|
item,
|
|
|
|
syncData: {
|
|
|
|
...syncData,
|
|
|
|
hash: item.hash,
|
|
|
|
rev,
|
|
|
|
},
|
|
|
|
};
|
2018-01-30 07:36:33 +00:00
|
|
|
},
|
2018-06-07 23:56:11 +00:00
|
|
|
async uploadWorkspaceContent(token, item, syncData) {
|
|
|
|
const res = await couchdbHelper.uploadDocument({
|
|
|
|
token,
|
|
|
|
item: {
|
|
|
|
id: item.id,
|
|
|
|
type: item.type,
|
|
|
|
hash: item.hash,
|
|
|
|
},
|
|
|
|
data: Provider.serializeContent(item),
|
|
|
|
dataType: 'text/plain',
|
|
|
|
documentId: syncData && syncData.id,
|
|
|
|
rev: syncData && syncData.rev,
|
|
|
|
});
|
|
|
|
|
|
|
|
// Return new sync data
|
|
|
|
return {
|
|
|
|
id: res.id,
|
|
|
|
itemId: item.id,
|
|
|
|
type: item.type,
|
|
|
|
hash: item.hash,
|
|
|
|
rev: res.rev,
|
|
|
|
};
|
2018-01-30 07:36:33 +00:00
|
|
|
},
|
2018-06-07 23:56:11 +00:00
|
|
|
async uploadWorkspaceData(token, item, syncData) {
|
|
|
|
const res = await couchdbHelper.uploadDocument({
|
|
|
|
token,
|
|
|
|
item: {
|
|
|
|
id: item.id,
|
|
|
|
type: item.type,
|
|
|
|
hash: item.hash,
|
|
|
|
},
|
|
|
|
data: JSON.stringify(item),
|
|
|
|
dataType: 'application/json',
|
|
|
|
documentId: syncData && syncData.id,
|
|
|
|
rev: syncData && syncData.rev,
|
|
|
|
});
|
|
|
|
|
|
|
|
// Return new sync data
|
|
|
|
return {
|
|
|
|
id: res.id,
|
|
|
|
itemId: item.id,
|
|
|
|
type: item.type,
|
|
|
|
hash: item.hash,
|
|
|
|
rev: res.rev,
|
|
|
|
};
|
2018-01-30 07:36:33 +00:00
|
|
|
},
|
2018-05-13 13:27:33 +00:00
|
|
|
async listRevisions(token, fileId) {
|
|
|
|
const syncData = Provider.getContentSyncData(fileId);
|
|
|
|
const body = await couchdbHelper.retrieveDocumentWithRevisions(token, syncData.id);
|
|
|
|
const revisions = [];
|
|
|
|
body._revs_info.forEach((revInfo) => { // eslint-disable-line no-underscore-dangle
|
|
|
|
if (revInfo.status === 'available') {
|
|
|
|
revisions.push({
|
|
|
|
id: revInfo.rev,
|
|
|
|
sub: null,
|
|
|
|
created: null,
|
2018-01-30 07:36:33 +00:00
|
|
|
});
|
2018-05-13 13:27:33 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
return revisions;
|
2018-01-30 07:36:33 +00:00
|
|
|
},
|
2018-05-13 13:27:33 +00:00
|
|
|
async loadRevision(token, fileId, revision) {
|
|
|
|
const syncData = Provider.getContentSyncData(fileId);
|
|
|
|
const body = await couchdbHelper.retrieveDocument(token, syncData.id, revision.id);
|
|
|
|
revision.sub = body.sub;
|
|
|
|
revision.created = body.time || 1; // Has to be truthy to prevent from loading several times
|
2018-01-30 07:36:33 +00:00
|
|
|
},
|
2018-05-13 13:27:33 +00:00
|
|
|
async getRevisionContent(token, fileId, revisionId) {
|
|
|
|
const syncData = Provider.getContentSyncData(fileId);
|
|
|
|
const body = await couchdbHelper
|
|
|
|
.retrieveDocumentWithAttachments(token, syncData.id, revisionId);
|
|
|
|
return Provider.parseContent(body.attachments.data, body.item.id);
|
2018-01-30 07:36:33 +00:00
|
|
|
},
|
2018-01-24 07:31:54 +00:00
|
|
|
});
|