Fixed publishing

This commit is contained in:
Benoit Schweblin 2018-08-17 11:13:08 +01:00
parent bdb01f407b
commit d4624eba9d
13 changed files with 121 additions and 69 deletions

View File

@ -8,7 +8,9 @@ ENV V4_VERSION 4.3.22
RUN npm pack stackedit@$V4_VERSION \
&& tar xzf stackedit-*.tgz --strip 1 \
&& yarn \
&& yarn cache clean
&& yarn cache clean \
&& rm -rf ~/.cache/bower \
&& rm -rf ~/.local/share/bower
WORKDIR /opt/stackedit

View File

@ -53,7 +53,9 @@ export default {
this.ready = true;
tempFileSvc.setReady();
} catch (err) {
if (err && err.message !== 'RELOAD') {
if (err && err.message === 'RELOAD') {
window.location.reload();
} else if (err && err.message !== 'RELOAD') {
console.error(err); // eslint-disable-line no-console
this.$store.dispatch('notification/error', err);
}

View File

@ -12,7 +12,7 @@
</div>
<div class="tour-step__inner" v-else-if="step === 'editor'">
<h2>Your Markdown editor</h2>
<p>StackEdit renders your Markdown into HTML in real-time.</p>
<p>StackEdit converts your Markdown to HTML in real-time.</p>
<p>Click <icon-side-preview></icon-side-preview> to toggle the side preview.</p>
<div class="tour-step__button-bar">
<button class="button" @click="finish">Skip</button>
@ -144,7 +144,7 @@ $tour-step-width: 240px;
.tour-step__inner {
position: absolute;
background-color: $tour-step-background;
padding: 1em;
padding: 1.5em;
font-size: 0.9em;
line-height: 1.33;
width: $tour-step-width;
@ -213,8 +213,10 @@ $tour-step-width: 240px;
}
.tour-step__button-bar {
margin-top: 1.75em;
text-align: right;
margin-top: 1.5em;
display: flex;
flex-direction: row;
justify-content: flex-end;
.button {
font-size: 1.1em;

View File

@ -7,7 +7,7 @@
</div>
<div class="flex flex--column">
<div>Import Markdown</div>
<span>Open a plain text file.</span>
<span>Import a plain text file.</span>
</div>
</label>
<input class="hidden-file" id="import-html-file-input" type="file" @change="onImportHtml">

View File

@ -77,11 +77,8 @@ export default {
...utils.queryParams,
exportWorkspace: true,
}, true);
const iframeElt = utils.createHiddenIframe(url);
document.body.appendChild(iframeElt);
setTimeout(() => {
document.body.removeChild(iframeElt);
}, 60000);
window.location.href = url;
window.location.reload(true);
},
async settings() {
try {

View File

@ -24,7 +24,7 @@
span {
display: inline-block;
font-size: 0.75rem;
opacity: 0.6;
opacity: 0.67;
line-height: 1.3;
.menu-entry__label {

View File

@ -7,20 +7,32 @@
<p v-if="publishLocations.length"><b>{{currentFileName}}</b> is published to the following location(s):</p>
<p v-else><b>{{currentFileName}}</b> is not published yet.</p>
<div>
<div class="publish-entry flex flex--row flex--align-center" v-for="location in publishLocations" :key="location.id">
<div class="publish-entry__icon flex flex--column flex--center">
<icon-provider :provider-id="location.providerId"></icon-provider>
<div class="publish-entry flex flex--column" v-for="location in publishLocations" :key="location.id">
<div class="publish-entry__header flex flex--row flex--align-center">
<div class="publish-entry__icon flex flex--column flex--center">
<icon-provider :provider-id="location.providerId"></icon-provider>
</div>
<div class="publish-entry__description">
{{location.description}}
</div>
<div class="publish-entry__buttons flex flex--row flex--center">
<button class="publish-entry__button button" @click="remove(location)" v-title="'Remove location'">
<icon-delete></icon-delete>
</button>
</div>
</div>
<div class="publish-entry__description">
{{location.description}}
</div>
<div class="publish-entry__buttons flex flex--row flex--center">
<a class="publish-entry__button button" :href="location.url" target="_blank" v-title="'Open location'">
<icon-open-in-new></icon-open-in-new>
</a>
<button class="publish-entry__button button" @click="remove(location)" v-title="'Remove location'">
<icon-delete></icon-delete>
</button>
<div class="publish-entry__row flex flex--row flex--align-center">
<div class="publish-entry__url">
{{location.url}}
</div>
<div class="publish-entry__buttons flex flex--row flex--center" v-if="location.url">
<button class="publish-entry__button button" v-clipboard="location.url" @click="info('Location URL copied to clipboard!')" v-title="'Copy URL'">
<icon-content-copy></icon-content-copy>
</button>
<a class="publish-entry__button button" v-if="location.url" :href="location.url" target="_blank" v-title="'Open location'">
<icon-open-in-new></icon-open-in-new>
</a>
</div>
</div>
</div>
</div>
@ -35,7 +47,7 @@
</template>
<script>
import { mapGetters } from 'vuex';
import { mapGetters, mapActions } from 'vuex';
import ModalInner from './common/ModalInner';
export default {
@ -54,6 +66,9 @@ export default {
},
},
methods: {
...mapActions('notification', [
'info',
]),
remove(location) {
this.$store.commit('publishLocation/deleteItem', location.id);
},
@ -65,40 +80,70 @@ export default {
@import '../../styles/variables.scss';
.publish-entry {
padding: 0.5rem 0.25rem;
border-bottom: 1px solid $hr-color;
margin: 1.5em 0;
height: auto;
font-size: 17px;
line-height: 1.5;
}
&:last-child {
border-bottom: none;
}
$button-size: 30px;
$small-button-size: 22px;
.publish-entry__header {
line-height: $button-size;
}
.publish-entry__row {
margin-top: 1px;
padding-top: 1px;
border-top: 1px solid rgba(128, 128, 128, 0.15);
line-height: $small-button-size;
}
.publish-entry__icon {
height: 30px;
width: 30px;
height: 22px;
width: 22px;
margin-right: 0.75rem;
flex: none;
}
.publish-entry__description {
opacity: 0.5;
line-height: 1.4;
font-size: 0.9em;
width: 100%;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.publish-entry__url {
width: 100%;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
opacity: 0.5;
font-size: 0.67em;
}
.publish-entry__buttons {
margin-left: 0.75rem;
.publish-entry__row & {
margin-left: 0.5rem;
}
}
.publish-entry__button {
width: 38px;
height: 38px;
padding: 6px;
width: $button-size;
height: $button-size;
padding: 4px;
background-color: transparent;
opacity: 0.75;
.publish-entry__row & {
width: $small-button-size;
height: $small-button-size;
padding: 4px;
}
&:active,
&:focus,
&:hover {

View File

@ -32,7 +32,7 @@
</label>
</div>
</div>
<form-entry label="Template">
<form-entry label="Template" v-if="format === 'html'">
<select slot="field" class="textfield" v-model="selectedTemplate" @keydown.enter="resolve()">
<option v-for="(template, id) in allTemplatesById" :key="id" :value="id">
{{ template.name }}
@ -84,7 +84,7 @@ export default modalTemplate({
resolve() {
// Return new location
const location = googleDriveProvider.makeLocation(this.config.token, this.fileId);
if (this.format) {
if (this.format === 'html') {
location.templateId = this.selectedTemplate;
}
this.config.resolve(location);

View File

@ -9,7 +9,7 @@
<input slot="field" class="textfield" type="text" v-model.trim="domain" @keydown.enter="resolve()">
<div class="form-entry__info">
<b>Example:</b> example.wordpress.com<br>
<b>Jetpack plugin</b> is required for self-hosted sites.
<b>Note:</b> Jetpack is required for self-hosted sites.
</div>
</form-entry>
<form-entry label="Existing post ID" info="optional">

View File

@ -332,7 +332,6 @@ const localDbSvc = {
// Clean data stored in localStorage
localStorage.removeItem(`data/${id}`);
});
window.location.reload();
throw new Error('RELOAD');
}
@ -349,7 +348,7 @@ const localDbSvc = {
type: 'text/plain;charset=utf-8',
});
FileSaver.saveAs(blob, 'StackEdit workspace.json');
return;
throw new Error('RELOAD');
}
// Watch workspace deletions and persist them as soon as possible

View File

@ -87,7 +87,7 @@ export default {
date,
}) {
const refreshedToken = await this.refreshToken(token);
await request(refreshedToken, {
return request(refreshedToken, {
method: 'POST',
url: `https://public-api.wordpress.com/rest/v1.2/sites/${siteId || domain}/posts/${postId || 'new'}`,
body: {

View File

@ -122,6 +122,7 @@ export default {
});
// Build the tree
const parentsMap = {};
Object.entries(nodeMap).forEach(([, node]) => {
let parentNode = nodeMap[node.item.parentId];
if (!parentNode || !parentNode.isFolder) {
@ -129,6 +130,18 @@ export default {
return;
}
parentNode = rootNode;
} else if (node.isFolder) {
// Detect circular reference
const parentParents = parentsMap[node.item.parentId] || {};
if (parentParents[node.item.id]) {
// Node is already a parent of its supposed parent
parentNode = rootNode;
} else {
parentsMap[node.item.id] = {
...parentParents,
[node.item.parentId]: true,
};
}
}
if (node.isFolder) {
parentNode.folders.push(node);

View File

@ -83,33 +83,25 @@ const store = new Vuex.Store({
},
pathsByItemId: (state, getters) => {
const result = {};
const foldersById = state.folder.itemsById;
const getPath = (item) => {
let itemPath = result[item.id];
if (!itemPath) {
if (item.parentId === 'trash') {
itemPath = `.stackedit-trash/${item.name}`;
} else {
let { name } = item;
if (foldersById[item.id]) {
name += '/';
}
const parentFolder = foldersById[item.parentId];
if (parentFolder) {
itemPath = getPath(parentFolder) + name;
} else {
itemPath = name;
}
const processNode = (node, parentPath = '') => {
let path = parentPath;
if (node.item.id) {
path += node.item.name;
if (node.isTrash) {
path = '.stackedit-trash/';
} else if (node.isFolder) {
path += '/';
}
result[node.item.id] = path;
}
if (node.isFolder) {
node.folders.forEach(child => processNode(child, path));
node.files.forEach(child => processNode(child, path));
}
result[item.id] = itemPath;
return itemPath;
};
[
...getters['folder/items'],
...getters['file/items'],
].forEach(item => getPath(item));
processNode(getters['explorer/rootNode']);
return result;
},
itemsByPath: (state, { allItemsById, pathsByItemId }) => {