Fixed location synchronization

This commit is contained in:
benweet 2017-10-05 08:18:21 +01:00
parent 0a2d8396d6
commit cbb44f4ea6
16 changed files with 54 additions and 61 deletions

View File

@ -209,8 +209,8 @@ export default {
color: #de2c00; color: #de2c00;
} }
.modal__tip { .modal__info {
background-color: transparentize(#ffd600, 0.85); background-color: $info-bg;
border-radius: $border-radius-base; border-radius: $border-radius-base;
margin: 1.2em 0; margin: 1.2em 0;
padding: 0.75em 1.25em; padding: 0.75em 1.25em;

View File

@ -143,11 +143,10 @@ export default {
} }
} }
.side-bar__warning { .side-bar__info {
padding: 10px; padding: 10px;
margin: 0 -10px; margin: 0 -10px;
color: darken($error-color, 10); background-color: $info-bg;
background-color: transparentize($error-color, 0.925);
p { p {
margin: 10px; margin: 10px;

View File

@ -4,6 +4,7 @@ $line-height-base: 1.67;
$line-height-title: 1.33; $line-height-title: 1.33;
$font-size-monospace: 0.85em; $font-size-monospace: 0.85em;
$code-bg: rgba(0, 0, 0, 0.05); $code-bg: rgba(0, 0, 0, 0.05);
$info-bg: transparentize(#ffb000, 0.85);
$code-border-radius: 2px; $code-border-radius: 2px;
$link-color: #0c93e4; $link-color: #0c93e4;
$error-color: #f20; $error-color: #f20;

View File

@ -3,7 +3,7 @@
<menu-entry @click.native="exportMarkdown"> <menu-entry @click.native="exportMarkdown">
<icon-download slot="icon"></icon-download> <icon-download slot="icon"></icon-download>
<div>Export as Markdown</div> <div>Export as Markdown</div>
<span>Save file as plain text.</span> <span>Save plain text file.</span>
</menu-entry> </menu-entry>
<menu-entry @click.native="exportHtml"> <menu-entry @click.native="exportHtml">
<icon-download slot="icon"></icon-download> <icon-download slot="icon"></icon-download>

View File

@ -1,11 +1,11 @@
<template> <template>
<div class="side-bar__panel side-bar__panel--menu"> <div class="side-bar__panel side-bar__panel--menu">
<div class="side-bar__warning" v-if="publishLocations.length"> <div class="side-bar__info" v-if="publishLocations.length">
<p><b>{{currentFileName}}</b> is already published.</p> <p><b>{{currentFileName}}</b> is already published.</p>
<menu-entry v-if="!offline" @click.native="requestPublish"> <menu-entry @click.native="requestPublish">
<icon-upload slot="icon"></icon-upload> <icon-upload slot="icon"></icon-upload>
<div>Publish now</div> <div>Publish now</div>
<span>Upload current file to its publication locations.</span> <span>Update current file publications.</span>
</menu-entry> </menu-entry>
<menu-entry @click.native="managePublish"> <menu-entry @click.native="managePublish">
<icon-view-list slot="icon"></icon-view-list> <icon-view-list slot="icon"></icon-view-list>
@ -120,9 +120,6 @@ export default {
MenuEntry, MenuEntry,
}, },
computed: { computed: {
...mapState([
'offline',
]),
...mapState('queue', [ ...mapState('queue', [
'isPublishRequested', 'isPublishRequested',
]), ]),

View File

@ -1,11 +1,11 @@
<template> <template>
<div class="side-bar__panel side-bar__panel--menu"> <div class="side-bar__panel side-bar__panel--menu">
<div class="side-bar__warning" v-if="syncLocations.length"> <div class="side-bar__info" v-if="syncLocations.length">
<p><b>{{currentFileName}}</b> is already synchronized.</p> <p><b>{{currentFileName}}</b> is already synchronized.</p>
<menu-entry v-if="!offline && isSyncPossible" @click.native="requestSync"> <menu-entry v-if="isSyncPossible" @click.native="requestSync">
<icon-sync slot="icon"></icon-sync> <icon-sync slot="icon"></icon-sync>
<div>Synchronize now</div> <div>Synchronize now</div>
<span>Download, merge and upload file changes.</span> <span>Download / upload file changes.</span>
</menu-entry> </menu-entry>
<menu-entry @click.native="manageSync"> <menu-entry @click.native="manageSync">
<icon-view-list slot="icon"></icon-view-list> <icon-view-list slot="icon"></icon-view-list>
@ -13,13 +13,11 @@
<span>Manage current file synchronized locations.</span> <span>Manage current file synchronized locations.</span>
</menu-entry> </menu-entry>
</div> </div>
<div v-else-if="!offline && isSyncPossible"> <menu-entry v-else-if="isSyncPossible" @click.native="requestSync">
<menu-entry @click.native="requestSync"> <icon-sync slot="icon"></icon-sync>
<icon-sync slot="icon"></icon-sync> <div>Synchronize now</div>
<div>Synchronize now</div> <span>Download / upload file changes.</span>
<span>Download, merge and upload file changes.</span> </menu-entry>
</menu-entry>
</div>
<hr> <hr>
<div v-for="token in googleDriveTokens" :key="token.sub"> <div v-for="token in googleDriveTokens" :key="token.sub">
<menu-entry @click.native="openGoogleDrive(token)"> <menu-entry @click.native="openGoogleDrive(token)">
@ -99,9 +97,6 @@ export default {
MenuEntry, MenuEntry,
}, },
computed: { computed: {
...mapState([
'offline',
]),
...mapState('queue', [ ...mapState('queue', [
'isSyncRequested', 'isSyncRequested',
]), ]),

View File

@ -24,7 +24,7 @@
<a href="javascript:void(0)" @click="configureTemplates">Configure templates</a> <a href="javascript:void(0)" @click="configureTemplates">Configure templates</a>
</div> </div>
</form-entry> </form-entry>
<div class="modal__tip"> <div class="modal__info">
<b>ProTip:</b> You can provide a value for <code>title</code> in the <a href="javascript:void(0)" @click="openFileProperties">file properties</a>. <b>ProTip:</b> You can provide a value for <code>title</code> in the <a href="javascript:void(0)" @click="openFileProperties">file properties</a>.
</div> </div>
<div class="modal__button-bar"> <div class="modal__button-bar">

View File

@ -24,7 +24,7 @@
<a href="javascript:void(0)" @click="configureTemplates">Configure templates</a> <a href="javascript:void(0)" @click="configureTemplates">Configure templates</a>
</div> </div>
</form-entry> </form-entry>
<div class="modal__tip"> <div class="modal__info">
<b>ProTip:</b> You can provide values for <code>title</code>, <code>tags</code>, <b>ProTip:</b> You can provide values for <code>title</code>, <code>tags</code>,
<code>status</code> and <code>date</code> in the <a href="javascript:void(0)" @click="openFileProperties">file properties</a>. <code>status</code> and <code>date</code> in the <a href="javascript:void(0)" @click="openFileProperties">file properties</a>.
</div> </div>

View File

@ -31,7 +31,7 @@
<a href="javascript:void(0)" @click="configureTemplates">Configure templates</a> <a href="javascript:void(0)" @click="configureTemplates">Configure templates</a>
</div> </div>
</form-entry> </form-entry>
<div class="modal__tip"> <div class="modal__info">
<b>ProTip:</b> You can provide a value for <code>title</code> in the <a href="javascript:void(0)" @click="openFileProperties">file properties</a>. <b>ProTip:</b> You can provide a value for <code>title</code> in the <a href="javascript:void(0)" @click="openFileProperties">file properties</a>.
</div> </div>
<div class="modal__button-bar"> <div class="modal__button-bar">

View File

@ -42,7 +42,7 @@
<a href="javascript:void(0)" @click="configureTemplates">Configure templates</a> <a href="javascript:void(0)" @click="configureTemplates">Configure templates</a>
</div> </div>
</form-entry> </form-entry>
<div class="modal__tip"> <div class="modal__info">
<b>ProTip:</b> You can provide a value for <code>title</code> in the <a href="javascript:void(0)" @click="openFileProperties">file properties</a>. <b>ProTip:</b> You can provide a value for <code>title</code> in the <a href="javascript:void(0)" @click="openFileProperties">file properties</a>.
</div> </div>
<div class="modal__button-bar"> <div class="modal__button-bar">

View File

@ -25,7 +25,7 @@
<a href="javascript:void(0)" @click="configureTemplates">Configure templates</a> <a href="javascript:void(0)" @click="configureTemplates">Configure templates</a>
</div> </div>
</form-entry> </form-entry>
<div class="modal__tip"> <div class="modal__info">
<b>ProTip:</b> You can provide values for <code>title</code>, <code>tags</code>, <b>ProTip:</b> You can provide values for <code>title</code>, <code>tags</code>,
<code>categories</code>, <code>excerpt</code>, <code>author</code>, <code>featuredImage</code>, <code>categories</code>, <code>excerpt</code>, <code>author</code>, <code>featuredImage</code>,
<code>status</code> and <code>date</code> in the <a href="javascript:void(0)" @click="openFileProperties">file properties</a>. <code>status</code> and <code>date</code> in the <a href="javascript:void(0)" @click="openFileProperties">file properties</a>.

View File

@ -30,7 +30,7 @@
<a href="javascript:void(0)" @click="configureTemplates">Configure templates</a> <a href="javascript:void(0)" @click="configureTemplates">Configure templates</a>
</div> </div>
</form-entry> </form-entry>
<div class="modal__tip"> <div class="modal__info">
<b>ProTip:</b> You can provide values for <code>title</code>, <code>tags</code> and <b>ProTip:</b> You can provide values for <code>title</code>, <code>tags</code> and
<code>status</code> in the <a href="javascript:void(0)" @click="openFileProperties">file properties</a>. <code>status</code> in the <a href="javascript:void(0)" @click="openFileProperties">file properties</a>.
</div> </div>

View File

@ -264,5 +264,8 @@ function checkOffline() {
} }
utils.setInterval(checkOffline, 1000); utils.setInterval(checkOffline, 1000);
window.addEventListener('online', checkOffline); window.addEventListener('online', () => {
isConnectionDown = false;
checkOffline();
});
window.addEventListener('offline', checkOffline); window.addEventListener('offline', checkOffline);

View File

@ -84,10 +84,10 @@ export default providerRegistry.register({
}); });
}, },
uploadContent(token, content, syncLocation, ifNotTooLate) { uploadContent(token, content, syncLocation, ifNotTooLate) {
return this.uploadData(token, undefined, content, `${syncLocation.fileId}/content`, ifNotTooLate) return this.uploadData(token, content, `${syncLocation.fileId}/content`, ifNotTooLate)
.then(() => syncLocation); .then(() => syncLocation);
}, },
uploadData(token, sub, item, dataId, ifNotTooLate) { uploadData(token, item, dataId, ifNotTooLate) {
const syncData = store.getters['data/syncDataByItemId'][dataId]; const syncData = store.getters['data/syncDataByItemId'][dataId];
if (syncData && syncData.hash === item.hash) { if (syncData && syncData.hash === item.hash) {
return Promise.resolve(); return Promise.resolve();
@ -98,7 +98,6 @@ export default providerRegistry.register({
id: item.id, id: item.id,
type: item.type, type: item.type,
hash: item.hash, hash: item.hash,
sub,
}), }),
['appDataFolder'], ['appDataFolder'],
JSON.stringify(item), JSON.stringify(item),

View File

@ -54,37 +54,33 @@ function cleanSyncedContent(syncedContent) {
} }
function applyChanges(changes) { function applyChanges(changes) {
const token = mainProvider.getToken();
const storeItemMap = { ...store.getters.allItemMap }; const storeItemMap = { ...store.getters.allItemMap };
const syncData = { ...store.getters['data/syncData'] }; const syncData = { ...store.getters['data/syncData'] };
let syncDataChanged = false; let syncDataChanged = false;
changes.forEach((change) => { changes.forEach((change) => {
// Ignore items that belong to another user (like settings) const existingSyncData = syncData[change.fileId];
if (!change.item || !change.item.sub || change.item.sub === token.sub) { const existingItem = existingSyncData && storeItemMap[existingSyncData.itemId];
const existingSyncData = syncData[change.fileId]; if (change.removed && existingSyncData) {
const existingItem = existingSyncData && storeItemMap[existingSyncData.itemId]; if (existingItem) {
if (change.removed && existingSyncData) { // Remove object from the store
if (existingItem) { store.commit(`${existingItem.type}/deleteItem`, existingItem.id);
// Remove object from the store delete storeItemMap[existingItem.id];
store.commit(`${existingItem.type}/deleteItem`, existingItem.id);
delete storeItemMap[existingItem.id];
}
delete syncData[change.fileId];
syncDataChanged = true;
} else if (!change.removed && change.item && change.item.hash) {
if (!existingSyncData || (existingSyncData.hash !== change.item.hash && (
!existingItem || existingItem.hash !== change.item.hash
))) {
// Put object in the store
if (change.item.type !== 'content') { // Merge contents later
store.commit(`${change.item.type}/setItem`, change.item);
storeItemMap[change.item.id] = change.item;
}
}
syncData[change.fileId] = change.syncData;
syncDataChanged = true;
} }
delete syncData[change.fileId];
syncDataChanged = true;
} else if (!change.removed && change.item && change.item.hash) {
if (!existingSyncData || (existingSyncData.hash !== change.item.hash && (
!existingItem || existingItem.hash !== change.item.hash
))) {
// Put object in the store
if (change.item.type !== 'content') { // Merge contents later
store.commit(`${change.item.type}/setItem`, change.item);
storeItemMap[change.item.id] = change.item;
}
}
syncData[change.fileId] = change.syncData;
syncDataChanged = true;
} }
}); });
@ -374,7 +370,6 @@ function syncDataItem(dataId) {
} }
return mainProvider.uploadData( return mainProvider.uploadData(
token, token,
dataId === 'settings' ? token.sub : undefined,
mergedItem, mergedItem,
dataId, dataId,
); );

View File

@ -60,6 +60,10 @@ export default {
resolveText: 'Yes, delete', resolveText: 'Yes, delete',
rejectText: 'No', rejectText: 'No',
}), }),
trashDeletion: ({ dispatch }) => dispatch('open', {
content: '<p>Files in the trash are automatically deleted after 7 days of inactivity.</p>',
resolveText: 'Ok',
}),
reset: ({ dispatch }) => dispatch('open', { reset: ({ dispatch }) => dispatch('open', {
content: '<p>This will clean your local files and settings. Are you sure?</p>', content: '<p>This will clean your local files and settings. Are you sure?</p>',
resolveText: 'Yes, clean', resolveText: 'Yes, clean',