Temporary folder (part 2)
This commit is contained in:
parent
53f2076585
commit
88cf11972f
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 79 KiB After Width: | Height: | Size: 79 KiB |
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="button-bar">
|
||||
<div class="button-bar__inner button-bar__inner--top">
|
||||
<button class="button-bar__button button" :class="{ 'button-bar__button--on': layoutSettings.showNavigationBar }" @click="toggleNavigationBar()" v-title="'Toggle navigation bar'">
|
||||
<button class="button-bar__button button" :class="{ 'button-bar__button--on': layoutSettings.showNavigationBar }" v-if="!light" @click="toggleNavigationBar()" v-title="'Toggle navigation bar'">
|
||||
<icon-navigation-bar></icon-navigation-bar>
|
||||
</button>
|
||||
<button class="button-bar__button button" :class="{ 'button-bar__button--on': layoutSettings.showSidePreview }" tour-step-anchor="editor" @click="toggleSidePreview()" v-title="'Toggle side preview'">
|
||||
@ -26,12 +26,17 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters, mapActions } from 'vuex';
|
||||
import { mapState, mapGetters, mapActions } from 'vuex';
|
||||
|
||||
export default {
|
||||
computed: mapGetters('data', [
|
||||
'layoutSettings',
|
||||
]),
|
||||
computed: {
|
||||
...mapState([
|
||||
'light',
|
||||
]),
|
||||
...mapGetters('data', [
|
||||
'layoutSettings',
|
||||
]),
|
||||
},
|
||||
methods: mapActions('data', [
|
||||
'toggleNavigationBar',
|
||||
'toggleEditor',
|
||||
|
@ -19,7 +19,7 @@
|
||||
<icon-close></icon-close>
|
||||
</button>
|
||||
</div>
|
||||
<div class="explorer__tree" :class="{'explorer__tree--new-item': !newChildNode.isNil}" v-if="!light" tabindex="0">
|
||||
<div class="explorer__tree" :class="{'explorer__tree--new-item': !newChildNode.isNil}" v-if="!light" tabindex="0" @keyup.delete="deleteItem()">
|
||||
<explorer-node :node="rootNode" :depth="0"></explorer-node>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -169,7 +169,7 @@ export default {
|
||||
perform: () => this.newItem(false),
|
||||
}, {
|
||||
name: 'New folder',
|
||||
disabled: !this.node.isFolder || this.node.isTrash,
|
||||
disabled: !this.node.isFolder || this.node.isTrash || this.node.isTemp,
|
||||
perform: () => this.newItem(true),
|
||||
}, {
|
||||
type: 'separator',
|
||||
@ -179,7 +179,6 @@ export default {
|
||||
perform: () => this.setEditingId(this.node.item.id),
|
||||
}, {
|
||||
name: 'Delete',
|
||||
disabled: this.node.isTrash || this.node.item.parentId === 'trash',
|
||||
perform: () => this.deleteItem(),
|
||||
}],
|
||||
})
|
||||
|
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="modal" @keydown.esc="onEscape" @keydown.tab="onTab">
|
||||
<component :is="currentModalComponent" v-if="currentModalComponent"></component>
|
||||
<component v-if="currentModalComponent" :is="currentModalComponent"></component>
|
||||
<modal-inner v-else aria-label="Dialog">
|
||||
<div class="modal__content" v-html="config.content"></div>
|
||||
<div class="modal__button-bar">
|
||||
@ -56,8 +56,6 @@ const getTabbables = container => container.querySelectorAll('a[href], button, .
|
||||
// Filter enabled and visible element
|
||||
.cl_filter(el => !el.disabled && el.offsetParent !== null && !el.classList.contains('not-tabbable'));
|
||||
|
||||
const kebabCase = str => str.replace(/[A-Z\u00C0-\u00D6\u00D8-\u00DE]/g, match => `-${match.toLowerCase()}`);
|
||||
|
||||
export default {
|
||||
components: {
|
||||
ModalInner,
|
||||
@ -102,11 +100,15 @@ export default {
|
||||
'config',
|
||||
]),
|
||||
currentModalComponent() {
|
||||
if (!this.condig.modal) {
|
||||
return '';
|
||||
if (this.config.type) {
|
||||
let componentName = this.config.type[0].toUpperCase();
|
||||
componentName += this.config.type.slice(1);
|
||||
componentName += 'Modal';
|
||||
if (this.$options.components[componentName]) {
|
||||
return componentName;
|
||||
}
|
||||
}
|
||||
|
||||
return `${kebabCase(this.config.modal)}-modal`;
|
||||
return null;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
|
@ -108,9 +108,7 @@ export default {
|
||||
}
|
||||
this.titleFakeElt.textContent = this.title;
|
||||
const width = this.titleFakeElt.getBoundingClientRect().width + 2; // 2px for the caret
|
||||
return width < this.styles.titleMaxWidth
|
||||
? width
|
||||
: this.styles.titleMaxWidth;
|
||||
return Math.min(width, this.styles.titleMaxWidth);
|
||||
},
|
||||
titleScrolling() {
|
||||
const result = this.titleHover && !this.titleFocus;
|
||||
@ -220,7 +218,7 @@ export default {
|
||||
float: left;
|
||||
|
||||
&.navigation-bar__inner--button {
|
||||
margin-right: 15px;
|
||||
margin-right: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,7 @@ export default {
|
||||
]),
|
||||
showSponsorButton() {
|
||||
const type = this.$store.getters['modal/config'].type;
|
||||
return !this.$store.getters.isSponsor && type !== 'sponsor' && type !== 'signInForSponsorship';
|
||||
return !this.$store.getters.isSponsor && type !== 'SponsorModal' && type !== 'signInForSponsorship';
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
|
@ -5,7 +5,6 @@ import welcomeFile from '../data/welcomeFile.md';
|
||||
|
||||
const dbVersion = 1;
|
||||
const dbStoreName = 'objects';
|
||||
const fileIdToOpen = utils.queryParams.fileId;
|
||||
const exportWorkspace = utils.queryParams.exportWorkspace;
|
||||
const resetApp = utils.queryParams.reset;
|
||||
const deleteMarkerMaxAge = 1000;
|
||||
@ -100,151 +99,6 @@ const localDbSvc = {
|
||||
hashMap,
|
||||
connection: null,
|
||||
|
||||
/**
|
||||
* Create the connection and start syncing.
|
||||
*/
|
||||
init() {
|
||||
return Promise.resolve()
|
||||
.then(() => {
|
||||
// Reset the app if reset flag was passed
|
||||
if (resetApp) {
|
||||
return Promise.all(
|
||||
Object.keys(store.getters['data/workspaces'])
|
||||
.map(workspaceId => localDbSvc.removeWorkspace(workspaceId)),
|
||||
)
|
||||
.then(() => utils.localStorageDataIds.forEach((id) => {
|
||||
// Clean data stored in localStorage
|
||||
localStorage.removeItem(`data/${id}`);
|
||||
}))
|
||||
.then(() => {
|
||||
location.reload();
|
||||
throw new Error('reload');
|
||||
});
|
||||
}
|
||||
|
||||
// Create the connection
|
||||
this.connection = new Connection();
|
||||
|
||||
// Load the DB
|
||||
return localDbSvc.sync();
|
||||
})
|
||||
.then(() => {
|
||||
// If exportWorkspace parameter was provided
|
||||
if (exportWorkspace) {
|
||||
const backup = JSON.stringify(store.getters.allItemMap);
|
||||
const blob = new Blob([backup], {
|
||||
type: 'text/plain;charset=utf-8',
|
||||
});
|
||||
FileSaver.saveAs(blob, 'StackEdit workspace.json');
|
||||
return;
|
||||
}
|
||||
|
||||
// Save welcome file content hash if not done already
|
||||
const hash = utils.hash(welcomeFile);
|
||||
const welcomeFileHashes = store.getters['data/localSettings'].welcomeFileHashes;
|
||||
if (!welcomeFileHashes[hash]) {
|
||||
store.dispatch('data/patchLocalSettings', {
|
||||
welcomeFileHashes: {
|
||||
...welcomeFileHashes,
|
||||
[hash]: 1,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// If app was last opened 7 days ago and synchronization is off
|
||||
if (!store.getters['workspace/syncToken'] &&
|
||||
(store.state.workspace.lastFocus + utils.cleanTrashAfter < Date.now())
|
||||
) {
|
||||
// Clean files
|
||||
store.getters['file/items']
|
||||
.filter(file => file.parentId === 'trash') // If file is in the trash
|
||||
.forEach(file => store.dispatch('deleteFile', file.id));
|
||||
}
|
||||
|
||||
// Enable sponsorship
|
||||
if (utils.queryParams.paymentSuccess) {
|
||||
location.hash = ''; // PaymentSuccess param is always on its own
|
||||
store.dispatch('modal/paymentSuccess');
|
||||
const sponsorToken = store.getters['workspace/sponsorToken'];
|
||||
// Force check sponsorship after a few seconds
|
||||
const currentDate = Date.now();
|
||||
if (sponsorToken && sponsorToken.expiresOn > currentDate - checkSponsorshipAfter) {
|
||||
store.dispatch('data/setGoogleToken', {
|
||||
...sponsorToken,
|
||||
expiresOn: currentDate - checkSponsorshipAfter,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Sync local DB periodically
|
||||
utils.setInterval(() => localDbSvc.sync(), 1000);
|
||||
|
||||
if (fileIdToOpen) {
|
||||
store.commit('file/setCurrentId', fileIdToOpen);
|
||||
}
|
||||
|
||||
// watch current file changing
|
||||
store.watch(
|
||||
() => store.getters['file/current'].id,
|
||||
() => {
|
||||
// See if currentFile is real, ie it has an ID
|
||||
const currentFile = store.getters['file/current'];
|
||||
// If current file has no ID, get the most recent file
|
||||
if (!currentFile.id) {
|
||||
const recentFile = store.getters['file/lastOpened'];
|
||||
// Set it as the current file
|
||||
if (recentFile.id) {
|
||||
store.commit('file/setCurrentId', recentFile.id);
|
||||
} else {
|
||||
// If still no ID, create a new file
|
||||
store.dispatch('createFile', {
|
||||
name: 'Welcome file',
|
||||
text: welcomeFile,
|
||||
})
|
||||
// Set it as the current file
|
||||
.then(newFile => store.commit('file/setCurrentId', newFile.id));
|
||||
}
|
||||
} else {
|
||||
Promise.resolve()
|
||||
// Load contentState from DB
|
||||
.then(() => localDbSvc.loadContentState(currentFile.id))
|
||||
// Load syncedContent from DB
|
||||
.then(() => localDbSvc.loadSyncedContent(currentFile.id))
|
||||
// Load content from DB
|
||||
.then(() => localDbSvc.loadItem(`${currentFile.id}/content`))
|
||||
.then(
|
||||
() => {
|
||||
// Set last opened file
|
||||
store.dispatch('data/setLastOpenedId', currentFile.id);
|
||||
// Cancel new discussion
|
||||
store.commit('discussion/setCurrentDiscussionId');
|
||||
// Open the gutter if file contains discussions
|
||||
store.commit('discussion/setCurrentDiscussionId',
|
||||
store.getters['discussion/nextDiscussionId']);
|
||||
// Add the fileId to the queryParams
|
||||
utils.setQueryParams({
|
||||
...utils.queryParams,
|
||||
fileId: currentFile.id,
|
||||
});
|
||||
},
|
||||
(err) => {
|
||||
// Failure (content is not available), go back to previous file
|
||||
const lastOpenedFile = store.getters['file/lastOpened'];
|
||||
store.commit('file/setCurrentId', lastOpenedFile.id);
|
||||
throw err;
|
||||
},
|
||||
)
|
||||
.catch((err) => {
|
||||
console.error(err); // eslint-disable-line no-console
|
||||
store.dispatch('notification/error', err);
|
||||
});
|
||||
}
|
||||
}, {
|
||||
immediate: true,
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Sync data items stored in the localStorage.
|
||||
*/
|
||||
@ -485,6 +339,142 @@ const localDbSvc = {
|
||||
localStorage.removeItem(`${id}/lastWindowFocus`);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Create the connection and start syncing.
|
||||
*/
|
||||
init() {
|
||||
return Promise.resolve()
|
||||
.then(() => {
|
||||
// Reset the app if reset flag was passed
|
||||
if (resetApp) {
|
||||
return Promise.all(
|
||||
Object.keys(store.getters['data/workspaces'])
|
||||
.map(workspaceId => localDbSvc.removeWorkspace(workspaceId)),
|
||||
)
|
||||
.then(() => utils.localStorageDataIds.forEach((id) => {
|
||||
// Clean data stored in localStorage
|
||||
localStorage.removeItem(`data/${id}`);
|
||||
}))
|
||||
.then(() => {
|
||||
location.reload();
|
||||
throw new Error('reload');
|
||||
});
|
||||
}
|
||||
|
||||
// Create the connection
|
||||
this.connection = new Connection();
|
||||
|
||||
// Load the DB
|
||||
return localDbSvc.sync();
|
||||
})
|
||||
.then(() => {
|
||||
// If exportWorkspace parameter was provided
|
||||
if (exportWorkspace) {
|
||||
const backup = JSON.stringify(store.getters.allItemMap);
|
||||
const blob = new Blob([backup], {
|
||||
type: 'text/plain;charset=utf-8',
|
||||
});
|
||||
FileSaver.saveAs(blob, 'StackEdit workspace.json');
|
||||
return;
|
||||
}
|
||||
|
||||
// Save welcome file content hash if not done already
|
||||
const hash = utils.hash(welcomeFile);
|
||||
const welcomeFileHashes = store.getters['data/localSettings'].welcomeFileHashes;
|
||||
if (!welcomeFileHashes[hash]) {
|
||||
store.dispatch('data/patchLocalSettings', {
|
||||
welcomeFileHashes: {
|
||||
...welcomeFileHashes,
|
||||
[hash]: 1,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// If app was last opened 7 days ago and synchronization is off
|
||||
if (!store.getters['workspace/syncToken'] &&
|
||||
(store.state.workspace.lastFocus + utils.cleanTrashAfter < Date.now())
|
||||
) {
|
||||
// Clean files
|
||||
store.getters['file/items']
|
||||
.filter(file => file.parentId === 'trash') // If file is in the trash
|
||||
.forEach(file => store.dispatch('deleteFile', file.id));
|
||||
}
|
||||
|
||||
// Enable sponsorship
|
||||
if (utils.queryParams.paymentSuccess) {
|
||||
location.hash = ''; // PaymentSuccess param is always on its own
|
||||
store.dispatch('modal/paymentSuccess');
|
||||
const sponsorToken = store.getters['workspace/sponsorToken'];
|
||||
// Force check sponsorship after a few seconds
|
||||
const currentDate = Date.now();
|
||||
if (sponsorToken && sponsorToken.expiresOn > currentDate - checkSponsorshipAfter) {
|
||||
store.dispatch('data/setGoogleToken', {
|
||||
...sponsorToken,
|
||||
expiresOn: currentDate - checkSponsorshipAfter,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Sync local DB periodically
|
||||
utils.setInterval(() => localDbSvc.sync(), 1000);
|
||||
|
||||
// watch current file changing
|
||||
store.watch(
|
||||
() => store.getters['file/current'].id,
|
||||
() => {
|
||||
// See if currentFile is real, ie it has an ID
|
||||
const currentFile = store.getters['file/current'];
|
||||
// If current file has no ID, get the most recent file
|
||||
if (!currentFile.id) {
|
||||
const recentFile = store.getters['file/lastOpened'];
|
||||
// Set it as the current file
|
||||
if (recentFile.id) {
|
||||
store.commit('file/setCurrentId', recentFile.id);
|
||||
} else {
|
||||
// If still no ID, create a new file
|
||||
store.dispatch('createFile', {
|
||||
name: 'Welcome file',
|
||||
text: welcomeFile,
|
||||
})
|
||||
// Set it as the current file
|
||||
.then(newFile => store.commit('file/setCurrentId', newFile.id));
|
||||
}
|
||||
} else {
|
||||
Promise.resolve()
|
||||
// Load contentState from DB
|
||||
.then(() => localDbSvc.loadContentState(currentFile.id))
|
||||
// Load syncedContent from DB
|
||||
.then(() => localDbSvc.loadSyncedContent(currentFile.id))
|
||||
// Load content from DB
|
||||
.then(() => localDbSvc.loadItem(`${currentFile.id}/content`))
|
||||
.then(
|
||||
() => {
|
||||
// Set last opened file
|
||||
store.dispatch('data/setLastOpenedId', currentFile.id);
|
||||
// Cancel new discussion
|
||||
store.commit('discussion/setCurrentDiscussionId');
|
||||
// Open the gutter if file contains discussions
|
||||
store.commit('discussion/setCurrentDiscussionId',
|
||||
store.getters['discussion/nextDiscussionId']);
|
||||
},
|
||||
(err) => {
|
||||
// Failure (content is not available), go back to previous file
|
||||
const lastOpenedFile = store.getters['file/lastOpened'];
|
||||
store.commit('file/setCurrentId', lastOpenedFile.id);
|
||||
throw err;
|
||||
},
|
||||
)
|
||||
.catch((err) => {
|
||||
console.error(err); // eslint-disable-line no-console
|
||||
store.dispatch('notification/error', err);
|
||||
});
|
||||
}
|
||||
}, {
|
||||
immediate: true,
|
||||
});
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
const loader = type => fileId => localDbSvc.loadItem(`${fileId}/${type}`)
|
||||
|
@ -4,16 +4,17 @@ import utils from './utils';
|
||||
import editorSvc from './editorSvc';
|
||||
|
||||
const origin = utils.queryParams.origin;
|
||||
const existingFileId = utils.queryParams.fileId;
|
||||
const fileName = utils.queryParams.fileName;
|
||||
const contentText = utils.queryParams.contentText;
|
||||
const contentProperties = utils.queryParams.contentProperties;
|
||||
|
||||
export default {
|
||||
closed: false,
|
||||
close() {
|
||||
if (origin && window.parent) {
|
||||
if (!this.closed && origin && window.parent) {
|
||||
window.parent.postMessage({ type: 'close' }, origin);
|
||||
}
|
||||
this.closed = true;
|
||||
},
|
||||
init() {
|
||||
if (!origin || !window.parent) {
|
||||
@ -21,64 +22,39 @@ export default {
|
||||
}
|
||||
|
||||
store.commit('setLight', true);
|
||||
return Promise.resolve()
|
||||
.then(() => {
|
||||
const file = store.state.file.itemMap[existingFileId];
|
||||
if (file) {
|
||||
// If file exists, check that the origin site has created it
|
||||
const fileCreation = store.getters['data/fileCreations'][file.id];
|
||||
if (fileCreation && fileCreation.origin === origin) {
|
||||
return file;
|
||||
}
|
||||
}
|
||||
|
||||
// Create a new temp file
|
||||
return store.dispatch('createFile', {
|
||||
name: fileName,
|
||||
text: contentText,
|
||||
properties: contentProperties,
|
||||
parentId: 'temp',
|
||||
});
|
||||
})
|
||||
return store.dispatch('createFile', {
|
||||
name: fileName,
|
||||
text: contentText,
|
||||
properties: contentProperties,
|
||||
parentId: 'temp',
|
||||
})
|
||||
.then((file) => {
|
||||
const fileItemMap = store.state.file.itemMap;
|
||||
|
||||
// Sanitize file creations
|
||||
const fileCreations = {};
|
||||
Object.entries(store.getters['data/fileCreations']).forEach(([id, fileCreation]) => {
|
||||
if (fileItemMap[id]) {
|
||||
fileCreations[id] = fileCreation;
|
||||
const lastCreated = {};
|
||||
Object.entries(store.getters['data/lastCreated']).forEach(([id, createdOn]) => {
|
||||
if (fileItemMap[id] && fileItemMap[id].parentId === 'temp') {
|
||||
lastCreated[id] = createdOn;
|
||||
}
|
||||
});
|
||||
|
||||
// Track file creation from the origin site
|
||||
fileCreations[file.id] = {
|
||||
// Track file creation from other site
|
||||
lastCreated[file.id] = {
|
||||
created: Date.now(),
|
||||
origin,
|
||||
};
|
||||
|
||||
// List temp files
|
||||
const tempFileCreations = [];
|
||||
Object.entries(fileCreations).forEach(([id, fileCreation]) => {
|
||||
if (fileItemMap[id].parentId === 'temp') {
|
||||
tempFileCreations.push({
|
||||
id,
|
||||
created: fileCreation.created,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Keep only the last 10 temp files
|
||||
tempFileCreations
|
||||
.sort((fileCreation1, fileCreation2) => fileCreation2.created - fileCreation1.created)
|
||||
// Keep only the last 10 temp files created by other sites
|
||||
Object.entries(lastCreated)
|
||||
.sort(([, createdOn1], [, createdOn2]) => createdOn2 - createdOn1)
|
||||
.splice(10)
|
||||
.forEach((fileCreation) => {
|
||||
delete fileCreations[fileCreation.id];
|
||||
store.dispatch('deleteFile', fileCreation.id);
|
||||
.forEach(([id]) => {
|
||||
delete lastCreated[id];
|
||||
store.dispatch('deleteFile', id);
|
||||
});
|
||||
|
||||
// Store file creations and open the file
|
||||
store.dispatch('data/setFileCreations', fileCreations);
|
||||
store.dispatch('data/setLastCreated', lastCreated);
|
||||
store.commit('file/setCurrentId', file.id);
|
||||
|
||||
const onChange = cledit.Utils.debounce(() => {
|
||||
@ -86,7 +62,7 @@ export default {
|
||||
if (currentFile.id !== file.id) {
|
||||
// Close editor if file has changed for some reason
|
||||
this.close();
|
||||
} else if (editorSvc.previewCtx.html != null) {
|
||||
} else if (!this.closed && editorSvc.previewCtx.html != null) {
|
||||
const content = store.getters['content/current'];
|
||||
const properties = utils.computeProperties(content.properties);
|
||||
window.parent.postMessage({
|
||||
|
@ -170,7 +170,7 @@ export default {
|
||||
...getters.templates,
|
||||
...additionalTemplates,
|
||||
}),
|
||||
fileCreations: getter('fileCreations'),
|
||||
lastCreated: getter('lastCreated'),
|
||||
lastOpened: getter('lastOpened'),
|
||||
lastOpenedIds: (state, getters, rootState) => {
|
||||
const lastOpened = {
|
||||
@ -262,7 +262,7 @@ export default {
|
||||
});
|
||||
commit('setItem', itemTemplate('templates', dataToCommit));
|
||||
},
|
||||
setFileCreations: setter('fileCreations'),
|
||||
setLastCreated: setter('lastCreated'),
|
||||
setLastOpenedId: ({ getters, commit, dispatch, rootState }, fileId) => {
|
||||
const lastOpened = { ...getters.lastOpened };
|
||||
lastOpened[fileId] = Date.now();
|
||||
|
@ -69,17 +69,26 @@ export default {
|
||||
},
|
||||
getters: {
|
||||
nodeStructure: (state, getters, rootState, rootGetters) => {
|
||||
const rootNode = new Node(emptyFolder(), [], true, true);
|
||||
|
||||
// Create Trash node
|
||||
const trashFolderNode = new Node(emptyFolder(), [], true);
|
||||
trashFolderNode.item.id = 'trash';
|
||||
trashFolderNode.item.name = 'Trash';
|
||||
trashFolderNode.noDrag = true;
|
||||
trashFolderNode.isTrash = true;
|
||||
trashFolderNode.parentNode = rootNode;
|
||||
|
||||
// Create Temp node
|
||||
const tempFolderNode = new Node(emptyFolder(), [], true);
|
||||
tempFolderNode.item.id = 'temp';
|
||||
tempFolderNode.item.name = 'Temp';
|
||||
tempFolderNode.noDrag = true;
|
||||
tempFolderNode.noDrop = true;
|
||||
tempFolderNode.isTemp = true;
|
||||
tempFolderNode.parentNode = rootNode;
|
||||
|
||||
// Fill nodeMap with all file and folder nodes
|
||||
const nodeMap = {
|
||||
trash: trashFolderNode,
|
||||
temp: tempFolderNode,
|
||||
@ -96,7 +105,8 @@ export default {
|
||||
];
|
||||
nodeMap[item.id] = new Node(item, locations);
|
||||
});
|
||||
const rootNode = new Node(emptyFolder(), [], true, true);
|
||||
|
||||
// Build the tree
|
||||
Object.entries(nodeMap).forEach(([, node]) => {
|
||||
let parentNode = nodeMap[node.item.parentId];
|
||||
if (!parentNode || !parentNode.isFolder) {
|
||||
@ -110,8 +120,11 @@ export default {
|
||||
} else {
|
||||
parentNode.files.push(node);
|
||||
}
|
||||
node.parentNode = parentNode;
|
||||
});
|
||||
rootNode.sortChildren();
|
||||
|
||||
// Add Trash and Temp nodes
|
||||
rootNode.folders.unshift(tempFolderNode);
|
||||
tempFolderNode.files.forEach((node) => {
|
||||
node.noDrop = true;
|
||||
@ -119,7 +132,8 @@ export default {
|
||||
if (trashFolderNode.files.length) {
|
||||
rootNode.folders.unshift(trashFolderNode);
|
||||
}
|
||||
// Add a fake file at the end of the root folder to allow drag and drop into it.
|
||||
|
||||
// Add a fake file at the end of the root folder to allow drag and drop into it
|
||||
rootNode.files.push(fakeFileNode);
|
||||
return {
|
||||
nodeMap,
|
||||
|
@ -1,7 +1,7 @@
|
||||
const minPadding = 20;
|
||||
const editorTopPadding = 10;
|
||||
const navigationBarEditButtonsWidth = (36 * 14) + 8; // 14 buttons + 1 spacer
|
||||
const navigationBarLeftButtonWidth = 38 + 4 + 15;
|
||||
const navigationBarLeftButtonWidth = 38 + 4 + 12;
|
||||
const navigationBarRightButtonWidth = 38 + 8;
|
||||
const navigationBarSpinnerWidth = 24 + 8 + 5; // 5 for left margin
|
||||
const navigationBarLocationWidth = 20;
|
||||
@ -23,7 +23,8 @@ const constants = {
|
||||
function computeStyles(state, getters, layoutSettings = getters['data/layoutSettings'], styles = {
|
||||
showNavigationBar: layoutSettings.showNavigationBar
|
||||
|| !layoutSettings.showEditor
|
||||
|| state.content.revisionContent,
|
||||
|| state.content.revisionContent
|
||||
|| state.light,
|
||||
showStatusBar: layoutSettings.showStatusBar,
|
||||
showEditor: layoutSettings.showEditor,
|
||||
showSidePreview: layoutSettings.showSidePreview && layoutSettings.showEditor,
|
||||
|
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 79 KiB After Width: | Height: | Size: 79 KiB |
Loading…
Reference in New Issue
Block a user