Commit 09b0788c authored by  JosephK's avatar JosephK
Browse files

Merge branch 'master' into 'master'

FAQ-Wiki

See merge request !231
parents 32afe547 7a505109
Pipeline #440446 passed with stages
in 3 minutes and 14 seconds
......@@ -13,6 +13,7 @@ pages:
stage: deploy
script:
- npm run commons
# - npm run sfs
- npm run prod
- rm -r public/ && mv -f dist/$(echo $CI_PAGES_URL | cut -d/ -f4-)/ public/
- find public -type f -iregex '.*\.\(htm\|html\|txt\|text\|js\|css\)$' -execdir gzip -f --keep {} \;
......@@ -32,12 +33,13 @@ pages:
- $DEPLOYEMENT_HOST
production:
stage: deploy
stage: deploy
# before_script:
# - apt-get update
# - apt-get --yes --force-yes install rsync
script:
- npm run commons
# - npm run sfs
- npm run prod
- rm -r public/ && mv dist/ public/
- cp ./public/fr/index.html ./public/index.html
......
......@@ -26,7 +26,7 @@ const env = {
available: [],
enabled: [],
},
date: JSON.stringify(fs.statSync('./src').mtime),
date: fs.statSync('./src').mtime,
dist: path.resolve(__dirname, '../dist'),
img: {
assets: './public/img/',
......
......@@ -12864,7 +12864,7 @@
},
"node_modules/vue-fs-commons": {
"version": "21.7.7",
"resolved": "git+https://git@framagit.org/framasoft/vue-fs/commons.git#6daf28d8fc4d37dd3cddc595bdef6e2cdaf6ca5d"
"resolved": "git+https://git@framagit.org/framasoft/vue-fs/commons.git#0a28763efe85da64c1e999f55146cd753085d1aa"
},
"node_modules/vue-functional-data-merge": {
"version": "3.1.0",
......@@ -22839,7 +22839,7 @@
}
},
"vue-fs-commons": {
"version": "git+https://git@framagit.org/framasoft/vue-fs/commons.git#6daf28d8fc4d37dd3cddc595bdef6e2cdaf6ca5d",
"version": "git+https://git@framagit.org/framasoft/vue-fs/commons.git#0a28763efe85da64c1e999f55146cd753085d1aa",
"from": "vue-fs-commons@git+https://git@framagit.org/framasoft/vue-fs/commons.git#master"
},
"vue-functional-data-merge": {
......
......@@ -7,7 +7,7 @@
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"commons": "rm -rf node_modules/vue-fs-commons && npm i git+https://git@framagit.org/framasoft/vue-fs/commons.git#master && npm i",
"sfs": "node_modules/vue-fs-commons/tools/copy-sfs-locales.sh",
"sfs": "node_modules/vue-fs-commons/tools/copy-sfs-translations.sh",
"dev": "rm -rf dist && cross-env NODE_ENV=development webpack-dev-server",
"prod": "rm -rf dist && cross-env NODE_ENV=production webpack --progress --hide-modules"
},
......
......@@ -21,8 +21,8 @@ export default {
metaInfo() {
/* Prepare meta data */
const info = {
title: this.$te(`meta.${this.$route.meta.id}.title`)
? `${this.$t('meta.title', '-t')} - ${this.$t(`meta.${this.$route.meta.id}.title`, '-t')}`
title: this.$te(`${this.$route.meta.id}.title`)
? `${this.$t('meta.title', '-t')} - ${this.$t(`${this.$route.meta.id}.title`, '-t')}`
: this.$t('meta.title', '-t'),
description: this.$te(`meta.${this.$route.meta.id}.description`)
......
......@@ -26,7 +26,7 @@ meta:
faq:
icon:
asso: fas fa-envelope
les_dons: fas fa-heart
donations: fas fa-heart
benevolat: fas fa-paw
partnership: far fa-handshake
......
@import '~vue-fs-commons/src/scss/frama/colors';
@import '../../commons/scss/frama/colors';
@import '../../commons/scss/frama/shadows';
/* Variables */
/* Brown variant */
$bsColor: (('f', 7), ('m', 7), ('m', 8), ('m', 2), ('b', 7), ('v', 6), ('o', 7), ('r', 8), ('d', 7));
$bgcolor: var(--f-m3);
/* Frameworks */
/* Bootstrap brown variant */
$bsColor: (('f', 7), ('m', 7), ('m', 8), ('m', 2), ('b', 7), ('v', 6), ('o', 7), ('r', 8), ('d', 7));
$secondary: bs(c, 2);
$dark: bs(c, 3);
$light: bs(c, 4);
$secondary: bs(c, 2);
$dark: bs(c, 3);
$light: bs(c, 4);
:root {
--f-secondary: bs(c, 2);
--f-dark: bs(c, 3);
--f-light: bs(c, 4);
--f-secondary: #{$secondary};
--f-dark: #{$dark};
--f-light: #{$light};
}
$ombre: 0px 3px 4px rgba(50, 50, 50, 0.2);
$img-ombre: 0px 2px 6px rgba(50, 50, 50, 0.4);
$carousel-ombre: 0px 3px 3px rgba(50, 50, 50, 0.5);
$button-ombre: 0px 1px 1px rgba(50, 50, 50, 0.5);
/* Frameworks */
@import 'frameworks/bootstrap4';
@import 'frameworks/iconslk';
......@@ -32,7 +24,7 @@ $button-ombre: 0px 1px 1px rgba(50, 50, 50, 0.5);
/* Frama */
@import 'frama/bootstrap4';
@import '~vue-fs-commons/src/scss/frama/common';
@import '../../commons/scss/frama/common';
#f-header {
display: none; // framanav not needed
......@@ -58,4 +50,4 @@ body {
.fc-danger { color: var(--f-danger); }
.fc-warning { color: var(--f-warning); }
.fc-success { color: var(--f-success); }
.fc-soutenir { color: var(--f-j7); }
\ No newline at end of file
.fc-soutenir { color: var(--f-j7); }
This diff is collapsed.
This diff is collapsed.
......@@ -33,36 +33,6 @@
</b-container>
</template>
<style lang="scss">
#faq {
.ombre h2::after {
content: initial;
}
#subfaq {
.list-group-item.active {
background: #FFF8E3;
}
.list-group-item:not(.active),
p.text-right {
display: block;
}
.filter {
h2,
.list-group-item:not(.search) {
display: none;
}
.search h2 {
display: block;
}
}
}
}
</style>
<script>
import Search from './faq/Search.vue';
import TOC from './faq/TOC.vue';
......@@ -93,23 +63,86 @@ export default {
this.lang = this.$i18n.locale;
}
}, 500);
if (window.location.hash === '#edit') {
document.body.classList.add('wiki-edit-enabled');
}
window.onhashchange = () => {
if (window.location.hash === '#edit') {
document.body.classList.add('wiki-edit-enabled');
} else {
document.body.classList.remove('wiki-edit-enabled');
}
};
},
methods: {
loadFaq() {
Object.keys(this.$t('faq')).filter(key => !/(intro|title|icon)/.test(key))
.forEach((key) => {
this.faq[key] = { variant: '' };
const q = Object.keys(this.$t(`faq.${key}`)).filter(i => !/title/.test(i));
for (let i = 0; i < q.length; i += 1) {
this.faq[key][q[i]] = {
q: this.$t(`faq.${key}.${q[i]}.q`),
a: this.$t(`faq.${key}.${q[i]}.a`),
variant: '',
};
}
});
Object.keys(this.$t('faq.ranking')).forEach((key) => {
this.faq[key] = { variant: '' };
const q = this.$t(`faq.ranking.${key}`);
for (let i = 0; i < q.length; i += 1) {
this.faq[key][q[i]] = {
q: this.$t(`faq.${key}.${q[i]}.q`),
a: this.$t(`faq.${key}.${q[i]}.a`),
variant: '',
};
}
});
},
},
};
</script>
<style lang="scss">
#faq {
.ombre h2::after {
content: initial;
}
#subfaq {
.list-group-item.active {
background: #FFF8E3;
}
.list-group-item:not(.active),
p.text-right {
display: block;
}
.filter {
h2,
.list-group-item:not(.search) {
display: none;
}
.search h2 {
display: block;
}
}
}
.btn-wiki-edit {
visibility: hidden;
}
&.wiki-edit-enabled {
.btn-wiki-edit {
visibility: visible;
z-index: 2;
position: absolute;
right: 1rem;
background: #fff;
&:hover {
background: var(--f-secondary);
}
}
.list-group-item.active .btn-wiki-edit {
display: none;
}
}
}
</style>
......@@ -8,6 +8,15 @@
:key="key"
:class="wFaq[key].variant"
>
<b-btn
:href="`${$t('config.wiki.base')}${
$t('lang') === 'fr' ? 'fr' : 'en'}/faq/${key}/Article title`"
size="sm"
variant="outline-secondary float-right mt-4 border-0 btn-wiki-edit"
>
<i class="fas fa-plus"></i>
<span v-html="$t('faq.add')"></span>
</b-btn>
<h2 class="mt-3">
<i :class="`${getSectionIcon(key)} fc-g6`"></i>
<span v-html="getFramaname(key) ? getFramaname(key) : $t(`faq.${key}.title`)"></span>
......@@ -17,6 +26,19 @@
:key="id"
:class="`${toggle === id ? 'active' : ''}${wFaq[key][id].variant}`"
>
<b-btn
:href="`${$t('config.wiki.base')}${
encodeURIComponent($t(`faq.${key}.${id}.e`))}/edit`"
size="sm"
:title="$t('faq.edit')"
variant="outline-secondary badge float-right mt-n3 mr-n2 btn-wiki-edit"
>
<i class="fas fa-pen"></i>
<span
class="sr-only"
v-html="$t('faq.edit')"
></span>
</b-btn>
<a
aria-hidden="true"
:href="`#${id}`"
......
<template>
<div>
<b-list-group-item
v-for="key in Object.keys($t('faq')).filter(key => !/(intro|title|icon|svg)/.test(key))"
v-for="key in Object.keys(this.$t('faq.ranking'))"
:key="key"
:href="`#${getFramaname(key) !== undefined
? $t(getFramaname(key), '-tlL').replace(/[^a-z]/g, '')
......
......@@ -265,7 +265,7 @@ export default {
categoryFaq: [],
faq: [],
search: '',
categories: Object.keys(this.$t('faq')).filter(i => !/title/.test(i)),
categories: Object.keys(this.$t('faq.ranking')),
category: '',
service: this.concern.split(' - ')[2],
state: {
......@@ -292,11 +292,11 @@ export default {
this.id = '0';
switch (this.concern.split(' - ')[0]) {
case 'Soutenir':
this.category = 'les_dons';
this.category = 'donations';
this.bs = 'soutenir';
break;
case 'Invitation à un événement':
this.category = 'autres';
this.category = 'misc';
this.bs = 'danger';
break;
case 'Partenariat':
......@@ -316,7 +316,7 @@ export default {
this.bs = 'info';
break;
case '---': // general
this.category = 'autres';
this.category = 'misc';
this.bs = 'primary';
break;
default:
......@@ -337,11 +337,13 @@ export default {
this.loadFaq();
}
},
search(newValue) {
if (newValue) {
this.searchUpdate();
}
},
status(newValue) {
if (newValue) {
this.faq = this.categoryFaq;
......@@ -357,6 +359,7 @@ export default {
}
},
},
methods: {
getFramaname(key) {
return this.$te(`color.${this.$t(key, '-k~lL@')}`)
......@@ -365,12 +368,12 @@ export default {
},
loadFaq() {
let q = Object.keys(this.$t('faq.autre')).filter(i => !/title/.test(i));
let q = this.$t('faq.ranking.misc');
for (let i = 0; i < q.length; i += 1) {
this.mainFaq[i] = {
id: q[i],
question: this.$t(`faq.autre.${q[i]}.q`),
answer: this.$t(`faq.autre.${q[i]}.a`)
question: this.$t(`faq.misc.${q[i]}.q`),
answer: this.$t(`faq.misc.${q[i]}.a`)
.replace(/<a href="https:\/\/contact.framasoft.org([\S\s]*?)">([\S\s]*?)<\/a>/g, '$2'),
variant: '',
};
......@@ -378,7 +381,7 @@ export default {
/* Site Faq */
if (this.categories.includes(this.category)) {
q = Object.keys(this.$t(`faq.${this.category}`)).filter(i => !/title/.test(i));
q = this.$t(`faq.ranking.${this.category}`);
for (let i = 0; i < q.length; i += 1) {
this.categoryFaq[i] = {
id: q[i],
......
......@@ -10,18 +10,24 @@ function formatWiki(env, data) {
const front = json[i].content.match(/^---([\s\S]*)---/m)
? json[i].content.match(/^---([\s\S]*)---/m)[0]
: '';
const lg = front.match(/lang: ([a-zA-Z_]+)/)
? front.match(/lang: ([a-zA-Z_]+)/)[1]
: '';
const date = front.match(/date: ([0-9]{2}-[0-9]{2}-[0-9]{2})/)
? front.match(/date: ([0-9]{2}-[0-9]{2}-[0-9]{2})/)[1]
: '';
const type = front.match(/type: ([a-z]+)/)
? front.match(/type: ([a-z]+)/)[1]
: '';
const title = front.match(/title: (.+)/)
? front.match(/title: (.+)/)[1] /* alternative title */
: json[i].title; /* tile from .md filename (- and / are not allowed) */
/* settings for news */
const date = front.match(/date: ([0-9]{2}-[0-9]{2}-[0-9]{2})/)
? front.match(/date: ([0-9]{2}-[0-9]{2}-[0-9]{2})/)[1]
: '';
let url = front.match(/url: (.+)/)
? front.match(/url: (.+)/)[1]
: '';
......@@ -29,6 +35,19 @@ function formatWiki(env, data) {
url = `${env.url}news#${date}`;
}
/* setting for FAQ */
const id = front.match(/id: ([a-zA-Z-]+)/)
? front.match(/id: ([a-zA-Z-]+)/)[1]
: '';
const cat = front.match(/cat: ([a-zA-Z-]+)/)
? front.match(/cat: ([a-zA-Z-]+)/)[1]
: '';
const rank = front.match(/rank: ([0-9]+)/)
? front.match(/rank: ([0-9]+)/)[1]
: 99;
/* Format content */
const content = json[i].content
// Replace wiki relative links by local links
......@@ -44,26 +63,56 @@ function formatWiki(env, data) {
.replace(/^(!\[.*\]\((.*)\))/m, '') // remove img
.replace(/^[\s]*\n+/m, ''); // remove spaces & newlines at the begining;
if (/^news/.test(type)) { // news or newsletter
// Publication need a title (else it is a draft)
if (json[i].title !== '') {
if (wiki[lg] === undefined) {
wiki[lg] = {};
wiki[lg][type] = {
posts: {},
};
}
wiki[lg][type].posts[date] = {};
Object.assign(wiki[lg][type].posts[date], {
img,
url,
title: json[i].title,
text,
});
if (wiki[lg] === undefined) {
wiki[lg] = {};
}
if (wiki[lg][type] === undefined) {
wiki[lg][type] = {};
}
/* News or newsletter */
if (/^news/.test(type)) {
if (wiki[lg][type].posts === undefined) {
wiki[lg][type].posts = {};
}
wiki[lg][type].posts[date] = {};
Object.assign(wiki[lg][type].posts[date], {
img,
url,
title,
text,
edit: json[i].slug,
});
}
/* FAQ */
if (/^faq$/.test(type) && cat !== '' && id !== '') {
if (wiki[lg][type].ranking === undefined) {
wiki[lg][type].ranking = {};
}
if (wiki[lg][type][cat] === undefined) {
wiki[lg][type][cat] = {};
wiki[lg][type].ranking[cat] = [];
}
wiki[lg][type][cat][id] = {
q: title,
a: text,
e: json[i].slug,
};
wiki[lg][type].ranking[cat].push([rank, id]);
}
}
/* sort FAQ questions by rank */
Object.keys(wiki).forEach((lg) => {
if (wiki[lg].faq !== undefined) {
Object.keys(wiki[lg].faq.ranking).forEach((key) => {
const mapped = wiki[lg].faq.ranking[key].sort((a, b) => a[0] - b[0]).map(x => x[1]);
wiki[lg].faq.ranking[key] = mapped;
});
}
});
return wiki;
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment