Skip to content

Commit

Permalink
#249 #273 - unified snippet structure; finish html snippet
Browse files Browse the repository at this point in the history
  • Loading branch information
literakl committed Feb 1, 2022
1 parent 921d4e5 commit 667b301
Show file tree
Hide file tree
Showing 8 changed files with 84 additions and 67 deletions.
12 changes: 7 additions & 5 deletions backend/doc/database/snippets.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,29 @@
* code: unique identifier within the item; required
* type: type of the object; values: html, link, meta, script, style; required
* date: timestamp; required
* user: identification of the last user who made a change; required
* object: one of meta, html, link, script or style object

## Meta optional section
## Meta object
* name: value of meta attribute; optional
* property: value of property attribute; optional
* content: value of content attribute; optional

## Html optional section
## Html object
* innerHTML: content to be rendered; required

## Link optional section
## Link object
* rel: value of rel attribute; optional
* href: value of href attribute; optional

## Script optional section
## Script object
* url: value of src attribute; optional
* type: value of type attribute; optional
* innerHTML: content to be rendered inside script tag; optional
* async: boolean value; optional
* defer: boolean value; optional

## Style optional section
## Style object
* type: value of type attribute; optional
* cssText: content to be rendered inside style tag; optional

Expand Down
9 changes: 4 additions & 5 deletions backend/src/handlers/items/snippets.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,7 @@ module.exports = (app) => {
}

const user = auth.getIdentity(req.identity);
const snippet = { code: code.toLowerCase(), type: type.toLowerCase(), date: new Date(), user };
snippet[snippet.type] = object;
const snippet = { code: code.toLowerCase(), type: type.toLowerCase(), date: new Date(), user, object };
snippets.push(snippet);

const result = await dbClient.db().collection('items').updateOne({ _id: itemId }, { $set: { snippets } });
Expand Down Expand Up @@ -149,14 +148,14 @@ module.exports = (app) => {
async function insertItem(dbClient, itemId, code, type, user, object) {
const snippet = {
code,
type,
date: new Date(),
user: {
nickname: user.nickname,
id: user.userId,
},
type,
date: new Date(),
object,
};
snippet[type] = object;

const result = await dbClient.db().collection('items').updateOne({ _id: itemId }, { $push: {snippets: snippet } });
if (result.modifiedCount === 1) {
Expand Down
6 changes: 3 additions & 3 deletions backend/test/snippets.int.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ test('Item snippets', async () => {
const snippetABody = {
code: 'set_a',
type: 'html',
object: { content: '<b>a=1</b>' },
object: { innerHTML: '<b>a=1</b>' },
};

// create snippet A as Jiri - forbidden (missing role editor in chief)
Expand Down Expand Up @@ -76,6 +76,7 @@ test('Item snippets', async () => {
expect(response.data.length).toBe(2);
expect(response.data[0].code).toBe(snippetABody.code);
expect(response.data[1].code).toBe(snippetCBody.code);
expect(response.data[1].object.content).toBe(snippetCBody.object.content);

response = await api(`content/${blog.data.info.slug}`).json();
expect(response.success).toBe(true);
Expand All @@ -93,8 +94,7 @@ test('Item snippets', async () => {
expect(response.success).toBe(true);
expect(response.data.code).toBe(snippetBBody.code);
expect(response.data.type).toBe(snippetBBody.type);
expect(response.data.meta).toBeUndefined();
expect(response.data.link).toStrictEqual(snippetBBody.object);
expect(response.data.object).toStrictEqual(snippetBBody.object);

const snippetDBody = {
code: 'set_d',
Expand Down
3 changes: 3 additions & 0 deletions spa/src/locales/cs.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
"edit-html-button": "Upravit HTML",
"edit-snippets-button": "Upravit úryvky",
"save-button": "Uložit",
"insert-button": "Přidat",
"delete-button": "Smazat",
"reset-button": "Reset",
"reset-tooltip": "Reset",
Expand Down Expand Up @@ -324,6 +325,8 @@
"cms": {
"snippets": {
"type": "Typ",
"code": "Kód",
"content": "Obsah",
"add-label": "Vložit snippet"
}
},
Expand Down
3 changes: 3 additions & 0 deletions spa/src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
"edit-html-button": "Edit HTML",
"edit-snippets-button": "Edit snippets",
"save-button": "Save",
"insert-button": "Insert",
"delete-button": "Delete",
"reset-button": "Reset",
"reset-tooltip": "Reset",
Expand Down Expand Up @@ -320,6 +321,8 @@
"cms": {
"snippets": {
"type": "Type",
"code": "Code",
"content": "Content",
"add-label": "Add new snippet"
}
},
Expand Down
7 changes: 7 additions & 0 deletions spa/src/modules/vuex/items.js
Original file line number Diff line number Diff line change
Expand Up @@ -211,5 +211,12 @@ export default {
await patch('API', `/posts/${content._id}/hidden`, payload, context);
Vue.set(content.info, 'state', hidden ? 'hidden' : 'published');
},
ADD_SNIPPET: async (context, payload) => {
Vue.$log.debug('ADD_SNIPPET');
const { itemId } = payload;
const response = await post('API', `/items/${itemId}/snippets`, payload, context);
context.commit('CLEAR_CONTENT');
return response;
},
},
};
33 changes: 12 additions & 21 deletions spa/src/views/item/Article.vue
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ export default {
},
metaInfo () {
return {
title: this.article ? this.article.info.caption : '',
title: this.title,
link: [],
meta: [],
script: [],
Expand All @@ -112,11 +112,10 @@ export default {
return this.$store.getters.CONTENT;
},
title() {
let txt = '';
if (this.article !== null) {
txt = this.article.info.caption;
return this.article.info.caption;
}
return txt;
return '';
},
canEdit() {
if (!this.$store.getters.IS_AUTHORIZED) {
Expand Down Expand Up @@ -151,31 +150,23 @@ export default {
return this.article.data.content;
}
let htmlSnippets = [];
let content = this.article.data.content;
this.article.snippets.forEach(snippet => {
if (snippet.type === 'meta') {
this.metaInfo.meta.push(snippet.meta);
this.metaInfo.meta.push(snippet.object);
} else if (snippet.type === 'html') {
htmlSnippets.push(snippet);
const replacer = `[code="${snippet.code}"]`;
const position = content.indexOf(replacer);
content = content.substring(0, position) + `\n${snippet.object.innerHTML}\n` + content.substring(position + replacer.length);
} else if (snippet.type === 'style') {
this.metaInfo.style.push(snippet.style);
this.metaInfo.style.push(snippet.object);
} else if (snippet.type === 'script') {
this.metaInfo.script.push(snippet.script);
this.metaInfo.script.push(snippet.object);
} else if (snippet.type === 'link') {
this.metaInfo.link.push(snippet.link);
this.metaInfo.link.push(snippet.object);
}
});
if (htmlSnippets.length > 0) {
const replacer = (match, foundCode) => {
const snippet = htmlSnippets.find(({ code }) => code === foundCode);
return snippet.html.innerHTML;
};
const html = this.article.data.content;
return html.replace(/\[code="([\w]+)"\]/gm, replacer);
} else {
return this.article.data.content;
}
return content;
},
async toComments() {
this.$scrollTo(document.getElementById('comments'), 500, { easing: 'ease' });
Expand Down
78 changes: 45 additions & 33 deletions spa/src/views/item/EditSnippets.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,16 @@
<div class="pt-3 centerbox m-auto" v-if="item">
<h2>{{ $t('page-title.snippets') }}</h2>

<b-form-textarea
id="textarea"
v-model="snippets"
rows="10"
min-rows="3"
aria-describedby="content-errors"
class="mb-3" />

<b-button variant="post-btn" @click="save()">
{{ $t("generic.save-button") }}
</b-button>
<div class="field-area">
<div>
<label class="d-label">{{ $t('cms.snippets.code') }}</label>
</div>

<div v-if="errors" class="text-danger">
{{ errors[0] }}
<div class="pb-2">
<b-form-input v-model="code" class="w-25"></b-form-input>
</div>
</div>

<h3 class="mt-3">{{ $t('cms.snippets.add-label') }}</h3>

<div class="field-area">
<div>
<label class="d-label" for="type">{{ $t('cms.snippets.type') }}</label>
Expand Down Expand Up @@ -59,14 +51,38 @@
</div>
</div>

<div class="field-area" v-if="type==='html'">
<div>
<label class="d-label" for="content">{{ $t('cms.snippets.content') }}</label>
</div>

<div class="pb-2">
<b-form-textarea
id="content"
v-model="content"
rows="10"
min-rows="3"
class="mb-3" />
</div>
</div>


<b-button variant="post-btn" @click="appendHTML()">
{{ $t("generic.insert-button") }}
</b-button>

<div v-if="errors" class="errors">
{{ errors[0] }}
</div>

</div>
</template>

<script>
import {
BButton,
BFormInvalidFeedback,
BFormGroup,
BFormInput,
BFormTextarea,
} from 'bootstrap-vue';
import Radio from '@/components/atoms/Radio';
Expand All @@ -76,7 +92,7 @@ export default {
components: {
BButton,
BFormGroup,
BFormInvalidFeedback,
BFormInput,
BFormTextarea,
Radio,
},
Expand All @@ -85,7 +101,10 @@ export default {
},
data() {
return {
snippets: [],
type: '',
code: '',
// meta name
name: '',
// meta property
property: '',
Expand All @@ -104,13 +123,11 @@ export default {
item() {
return this.$store.getters.CONTENT;
},
snippets() {
return this.item.snippets;
}
},
methods: {
appendHTML() {
this.append();
async appendHTML() {
await this.append({ innerHTML: this.content });
this.code = this.innerHTML = null;
},
appendLink() {
this.append();
Expand All @@ -124,22 +141,16 @@ export default {
appendStyle() {
this.append();
},
append(snippet) {
if (!this.snippets || this.snippets.length === 0 || this.snippets[0] !== '[') {
this.snippets = `[\n${snippet}\n]`;
} else {
const position = this.snippets.lastIndexOf(']');
this.snippets = this.snippets.substring(0, position) + `\n${snippet}\n]`;
}
},
async save() {
async append(snippet) {
const body = {
itemId: this.item._id,
source: this.html,
code: this.code,
type: this.type,
object: snippet,
};
this.errors = [];
let result = await this.$store.dispatch('UPDATE_CONTENT_HTML', body);
let result = await this.$store.dispatch('ADD_SNIPPET', body);
if (result.success) {
await this.$router.go(-1);
} else {
Expand All @@ -154,6 +165,7 @@ export default {
},
async created() {
await this.$store.dispatch('FETCH_CONTENT', { slug: this.slug });
this.snippets = this.item.snippets;
},
};
</script>
Expand Down

0 comments on commit 667b301

Please sign in to comment.