Stackedit/src/services/fileSvc.js

163 lines
5.2 KiB
JavaScript
Raw Normal View History

2018-05-04 18:07:28 +00:00
import store from '../store';
import utils from './utils';
const forbiddenFolderNameMatcher = /^\.stackedit-data$|^\.stackedit-trash$|\.md$|\.sync$|\.publish$/;
export default {
/**
* Create a file in the store with the specified fields.
*/
createFile(fields = {}, background = false) {
const id = utils.uid();
const file = {
id,
name: utils.sanitizeName(fields.name),
parentId: fields.parentId || null,
};
const content = {
id: `${id}/content`,
text: utils.sanitizeText(fields.text || store.getters['data/computedSettings'].newFileContent),
properties: utils.sanitizeText(
fields.properties || store.getters['data/computedSettings'].newFileProperties),
discussions: fields.discussions || {},
comments: fields.comments || {},
};
const nameStripped = file.name !== utils.defaultName && file.name !== fields.name;
// Check if there is a path conflict
const workspaceUniquePaths = store.getters['workspace/hasUniquePaths'];
let pathConflict;
if (workspaceUniquePaths) {
const parentPath = store.getters.itemPaths[file.parentId] || '';
const path = parentPath + file.name;
pathConflict = !!store.getters.pathItems[path];
}
// Show warning dialogs and then save in the store
return Promise.resolve()
.then(() => !background && nameStripped && store.dispatch('modal/stripName', fields.name))
.then(() => !background && pathConflict && store.dispatch('modal/pathConflict', fields.name))
.then(() => {
store.commit('content/setItem', content);
store.commit('file/setItem', file);
if (workspaceUniquePaths) {
this.makePathUnique(id);
}
return store.state.file.itemMap[id];
});
},
/**
* Make sanity checks and then create/update the folder/file in the store.
*/
async storeItem(item, background = false) {
const id = item.id || utils.uid();
const sanitizedName = utils.sanitizeName(item.name);
if (item.type === 'folder' && forbiddenFolderNameMatcher.exec(sanitizedName)) {
if (background) {
return null;
}
await store.dispatch('modal/unauthorizedName', item.name);
throw new Error('Unauthorized name.');
}
const workspaceUniquePaths = store.getters['workspace/hasUniquePaths'];
// Show warning dialogs
if (!background) {
// If name has been stripped
if (sanitizedName !== utils.defaultName && sanitizedName !== item.name) {
await store.dispatch('modal/stripName', item.name);
}
// Check if there is a path conflict
if (workspaceUniquePaths) {
const parentPath = store.getters.itemPaths[item.parentId] || '';
const path = parentPath + sanitizedName;
const pathItems = store.getters.pathItems[path] || [];
if (pathItems.some(itemWithSamePath => itemWithSamePath.id !== id)) {
await store.dispatch('modal/pathConflict', item.name);
}
}
}
// Save item in the store
store.commit(`${item.type}/setItem`, {
id,
parentId: item.parentId || null,
name: sanitizedName,
});
// Ensure path uniqueness
if (workspaceUniquePaths) {
this.makePathUnique(id);
}
return store.getters.allItemMap[id];
},
/**
* Delete a file in the store and all its related items.
*/
deleteFile(fileId) {
// Delete the file
store.commit('file/deleteItem', fileId);
// Delete the content
store.commit('content/deleteItem', `${fileId}/content`);
// Delete the syncedContent
store.commit('syncedContent/deleteItem', `${fileId}/syncedContent`);
// Delete the contentState
store.commit('contentState/deleteItem', `${fileId}/contentState`);
// Delete sync locations
(store.getters['syncLocation/groupedByFileId'][fileId] || [])
.forEach(item => store.commit('syncLocation/deleteItem', item.id));
// Delete publish locations
(store.getters['publishLocation/groupedByFileId'][fileId] || [])
.forEach(item => store.commit('publishLocation/deleteItem', item.id));
},
/**
* Ensure two files/folders don't have the same path if the workspace doesn't support it.
*/
ensureUniquePaths() {
if (store.getters['workspace/hasUniquePaths']) {
if (Object.keys(store.getters.itemPaths).some(id => this.makePathUnique(id))) {
this.ensureUniquePaths();
}
}
},
/**
* Return false if the file/folder path is unique.
* Add a prefix to its name and return true otherwise.
*/
makePathUnique(id) {
const item = store.getters.allItemMap[id];
if (!item) {
return false;
}
let path = store.getters.itemPaths[id];
const pathItems = store.getters.pathItems;
if (pathItems[path].length === 1) {
return false;
}
const isFolder = item.type === 'folder';
if (isFolder) {
// Remove trailing slash
path = path.slice(0, -1);
}
for (let suffix = 1; ; suffix += 1) {
let pathWithPrefix = `${path}.${suffix}`;
if (isFolder) {
pathWithPrefix += '/';
}
if (!pathItems[pathWithPrefix]) {
store.commit(`${item.type}/patchItem`, {
id: item.id,
name: `${item.name}.${suffix}`,
});
return true;
}
}
},
};