Commit 65244116 authored by Jean M's avatar Jean M
Browse files

navbar ready

parents
Multisite navbar
================
This project generates an HTML navigation menu from a JSON file located at a specified URL.
The URL must be set in `nav.js` (`ynh_url` variable).
For presentation and quick howto, please consult https://foss-notes.blog.nomagic.uk/
## Tips
The json file can be generated automatically from a yaml file, if your solution allows it.
- Example with Jekyll:
Content of file nav.html
```
---
layout: none
permalink: /third_party/simple-nav/nav.json
---
{{ site.data.navbar | jsonify }}
```
This will take the content of yaml file `mysite/_data/navbar.yaml` and convert it into json, with the json file available at `http(s)://mysite/third_party/simple-nav/nav.json`.
#[navbar:children]
#codimd
#ethercal
#framadate
# etc.
#
#[codimd]
#
#[ethercalc]
#
#[framadate]
#
#[jitsimeet]
#
#[lstu]
#
#[lufi]
#
#[lutim]
#
#[privatebin]
#
#[seafile]
#
#[sogo]
#
#[wallabag]
#
---
# For this to work, you need to ensure your different servers have
# been assigned in the right group, named after the name of the webapp
# you want to insert the navbar on.
#
# For example, ensure your Framadate server is part of group 'framadate'
- hosts: navbar
become: yes
roles:
- role: navbar
...
---
# For all
navbar_server: example.org
navbar_url: "https://example.org/navbar/nav.js"
navbar_url_regex: 'https://example\.org/navbar/nav\.js'
navbar: '<script src="https://example.org/navbar/nav.js"></script>'
# CodiMD
codimd_path: '/opt/codimd/current'
# Ethercalc
ethercalc_path: '/opt/ethercalc'
# Framadate
framadate_path: '/var/www/framadate/current'
# JitsiMeet
jitsimeet_path: '/usr/share/jitsi-meet'
# LSTU
lstu_path: '/var/www/lstu'
# Lufi
lufi_path: '/var/www/lufi'
# Lutim
lutim_path: '/var/www/lutim'
# Lutim - active theme
lutim_theme: 'default'
# PrivateBin
privatebin_path: '/var/www/privatebin/current'
# Seafile
seafile_path: '/opt/seafile'
# SOGo
sogo_path: '/usr/lib/GNUstep/SOGo'
sogo_conf: '/etc/sogo/sogo.conf'
# Wallabag
wallabag_path: '/var/www/wallabag'
...
---
- name: set the generic navbar common to all sites
lineinfile:
path: '{{ codimd_path }}/public/views/index/body.ejs'
line: '{{ navbar }}'
regexp: 'src="{{ navbar_url_regex }}"'
insertbefore: EOF
backup: yes
...
---
- name: set the generic navbar common to all sites
lineinfile:
path: '{{ ethercalc_path }}/node_modules/ethercalc/index.html'
line: '{{ navbar }}'
regexp: '{{ navbar }}'
insertbefore: '(\s+)?</body>'
backup: yes
- name: set the generic navbar on start page
lineinfile:
path: '{{ ethercalc_path }}/node_modules/ethercalc/start.html'
line: '{{ navbar }}'
regexp: '{{ navbar }}'
insertbefore: '(\s+)?</body>'
backup: yes
...
---
- name: set the generic navbar common to all sites
lineinfile:
path: '{{ framadate_path }}/tpl/page.tpl'
line: '{{ navbar }}'
regexp: '{{ navbar }}'
insertbefore: '(\s+)?</body>'
backup: yes
register: template_updated
- name: remove the cache file if a change was made
command: find {{ framadate_path }}/tpl_c -type f -name "*page*" -delete
when: template_updated.changed
...
---
- name: adapt jitsi-meet css to navbar
blockinfile:
backup: yes
path: '{{ jitsimeet_path }}/interface_config.js'
marker: '/* {mark} ANSIBLE NAVBAR ADJUSTMENT */'
insertafter: EOF
block: |2
/* Without jquery */
const loadScript = (source, beforeEl, async = true, defer = true) => {
return new Promise((resolve, reject) => {
let script = document.createElement('script');
const prior = beforeEl || document.getElementsByTagName('script')[0];
script.async = async;
script.defer = defer;
function onloadHander(_, isAbort) {
if (isAbort || !script.readyState || /loaded|complete/.test(script.readyState)) {
script.onload = null;
script.onreadystatechange = null;
script = undefined;
if (isAbort) { reject(); } else { resolve(); }
}
}
script.onload = onloadHander;
script.onreadystatechange = onloadHander;
script.src = source;
prior.parentNode.insertBefore(script, prior);
});
}
const scriptUrl = '{{ navbar_url }}';
if (window.location.pathname == "/") {
loadScript(scriptUrl).then(() => {
console.log('script loaded');
}, () => {
console.log('fail to load script');
});
}
...
---
- name: set up CSP to allow generic navbar
blockinfile:
backup: yes
path: '{{ lstu_path }}/lstu.conf'
marker: '# {mark} ANSIBLE ALLOW NAVBAR'
insertafter: '\s+#csp => "",'
block: |2
csp => "manifest-src 'self'; base-uri 'self'; connect-src 'self' {{ navbar_server }}; default-src 'none'; font-src 'self' {{ navbar_server }}; form-action 'self'; img-src 'self' {{ navbar_server }} data:; script-src 'self' {{ navbar_server }}; style-src 'self' {{ navbar_server }} 'unsafe-inline'",
- name: set the generic navbar common to all sites
lineinfile:
backup: yes
path: '{{ lstu_path }}/themes/default/templates/layouts/default.html.ep'
line: '{{ navbar }}'
regexp: '{{ navbar }}'
insertbefore: '\s+</body>'
...
---
- name: set up CSP to allow generic navbar
blockinfile:
backup: yes
path: "{{ lufi_path }}/lufi.conf"
marker: '# {mark} ANSIBLE ALLOW NAVBAR'
insertafter: '\s+#csp => "",'
block: |2
csp => "base-uri 'self'; connect-src 'self' {{ navbar_server }}; default-src 'none'; font-src 'self' {{ navbar_server }}; form-action 'self'; frame-ancestors 'none'; img-src 'self' {{ navbar_server }} blob:; media-src blob:; script-src 'self' {{ navbar_server }} 'unsafe-inline' 'unsafe-eval'; style-src 'self' {{ navbar_server }} 'unsafe-inline'",
- name: set the generic navbar common to all sites
lineinfile:
backup: yes
path: '{{ lufi_path }}/themes/default/templates/layouts/default.html.ep'
line: '{{ navbar }}'
regexp: '{{ navbar }}'
insertbefore: '\s+</body>'
- name: adapt lufi nomagic theme css to navbar
blockinfile:
backup: yes
path: "{{ lufi_path }}/themes/default/public/css/lufi.css"
marker: '/* {mark} ANSIBLE NAVBAR ADJUSTMENT */'
insertafter: EOF
block: |2
.side-nav {
top: 36px;
}
...
---
- name: set up CSP to allow generic navbar
blockinfile:
backup: yes
path: '{{ lutim_path }}/lutim.conf'
marker: '# {mark} ANSIBLE ALLOW NAVBAR'
insertafter: '\s+#csp => "",'
block: |2
csp => "base-uri 'self'; connect-src 'self' {{ navbar_server }}; default-src 'none'; font-src 'self' {{ navbar_server }}; form-action 'self'; img-src 'self' {{ navbar_server }} data:; script-src 'self' {{ navbar_server }} 'unsafe-eval'; style-src 'self' {{ navbar_server }} 'unsafe-inline'",
- name: set the generic navbar common to all sites
lineinfile:
backup: yes
path: '{{ navbar_server }}/themes/default/templates/partial/navbar.html.ep'
line: '{{ navbar }}'
regexp: '{{ navbar }}'
insertafter: '^</nav>$'
...
---
- import_tasks: codimd.yml
tags: ['codimd']
when: "'codimd' in group_names"
- import_tasks: ethercalc.yml
tags: ['ethercalc']
when: "'ethercalc' in group_names"
- import_tasks: framadate.yml
tags: ['framadate']
when: "'framadate' in group_names"
- import_tasks: jitsimeet.yml
tags: ['jitsimeet']
when: "'jitsimeet' in group_names"
- import_tasks: lstu.yml
tags: ['lstu']
when: "'lstu' in group_names"
- import_tasks: lufi.yml
tags: ['lufi']
when: "'lufi' in group_names"
- import_tasks: lutim.yml
tags: ['lutim']
when: "'lutim' in group_names"
- import_tasks: privatebin.yml
tags: ['privatebin']
when: "'privatebin' in group_names"
- import_tasks: seafile.yml
tags: ['seafile']
when: "'seafile' in group_names"
- import_tasks: sogo.yml
tags: ['sogo']
when: "'sogo' in group_names"
- import_tasks: wallabag.yml
tags: ['wallabag']
when: "'wallabag' in group_names"
...
---
- name: set up CSP to allow generic navbar
lineinfile:
backup: yes
path: "{{ privatebin_path }}/cfg/conf.php"
regexp: '(\s+)?cspheader ='
line: >
cspheader = "default-src 'none'; manifest-src 'self'; connect-src * blob:; script-src 'self' {{ navbar_server }} 'unsafe-eval'; style-src 'self' {{ navbar_server }}; font-src 'self' {{ navbar_server }}; img-src 'self' {{ navbar_server }} data: blob:; media-src blob:; object-src blob:; sandbox allow-same-origin allow-scripts allow-forms allow-popups allow-modals"
- name: set the generic navbar common to all sites
lineinfile:
backup: yes
path: '{{ privatebin_path }}/tpl/bootstrap.php'
line: '{{ navbar }}'
regexp: 'src="{{ navbar_url_regex }}"'
insertbefore: '(\s+)?</body>'
...
---
- name: get the current file for common.js
slurp:
src: '{{ seafile_path }}/seafile-server-latest/seahub/media/assets/staticfiles.json'
register: file_active
- name: set the generic navbar common to all sites
blockinfile:
path: "{{ seafile_path }}/seafile-server-latest/seahub/media/assets/{{ (file_active['content'] | b64decode | from_json)['paths']['frontend/commons/bundle.common.js'] }}"
marker: '/* {mark} ANSIBLE NAVBAR ADJUSTMENT */'
insertafter: EOF
backup: yes
block: |2
/* Without jquery */
const loadScript = (source, beforeEl, async = true, defer = true) => {
return new Promise((resolve, reject) => {
let script = document.createElement('script');
const prior = beforeEl || document.getElementsByTagName('script')[0];
script.async = async;
script.defer = defer;
function onloadHander(_, isAbort) {
if (isAbort || !script.readyState || /loaded|complete/.test(script.readyState)) {
script.onload = null;
script.onreadystatechange = null;
script = undefined;
if (isAbort) { reject(); } else { resolve(); }
}
}
script.onload = onloadHander;
script.onreadystatechange = onloadHander;
script.src = source;
prior.parentNode.insertBefore(script, prior);
});
}
// Adapt Seafile display for viewer pages
let myElement = document.getElementById("wrapper");
myElement.style.position = "fixed";
myElement.style.width = "100%";
const scriptUrl = '{{ navbar_url }}';
loadScript(scriptUrl).then(() => {
console.log('navbar script loaded');
}, () => {
console.log('fail to load navbar script');
});
...
---
- name: store navbar script locally on SOGo server
tags: navbar
template:
src: navbar_loader.j2
dest: '{{ sogo_path }}/WebServerResources/navbar_loader.js'
- name: tell SOGo to include the Javasvript for the navbar
tags: navbar
blockinfile:
backup: yes
path: "{{ sogo_conf }}"
marker: '/* {mark} ANSIBLE NAVBAR ADJUSTMENT */'
insertbefore: '^}$'
block: |2
// Navbar
SOGoUIAdditionalJSFiles = (
"navbar_loader.js"
);
...
---
- name: set the generic navbar common to all sites
tags: navbar
lineinfile:
backup: yes
path: '{{ wallabag_path }}/src/Wallabag/CoreBundle/Resources/views/themes/material/layout.html.twig'
line: ' {{ navbar }}'
regexp: '{{ navbar }}'
insertafter: '\{\% block scripts \%\}'
register: template_updated
- name: remove the cache dir for twig if file change was made
tags: navbar
command: rm -rf /var/www/{{ item.name }}/current/var/cache/prod/twig/*
when: template_updated.changed
- name: adapt css to navbar
tags: navbar
blockinfile:
backup: yes
path: "/var/www/{{ item.name }}/current/web/wallassets/material.css"
marker: '/* {mark} ANSIBLE NAVBAR ADJUSTMENT */'
insertafter: EOF
block: |2
#slide-out{top:37px !important;}
...
/* Without jquery */
const loadScript = (source, beforeEl, async = true, defer = true) => {
return new Promise((resolve, reject) => {
let script = document.createElement('script');
const prior = beforeEl || document.getElementsByTagName('script')[0];
script.async = async;
script.defer = defer;
function onloadHander(_, isAbort) {
if (isAbort || !script.readyState || /loaded|complete/.test(script.readyState)) {
script.onload = null;
script.onreadystatechange = null;
script = undefined;
if (isAbort) { reject(); } else { resolve(); }
}
}
script.onload = onloadHander;
script.onreadystatechange = onloadHander;
script.src = source;
prior.parentNode.insertBefore(script, prior);
});
}
// Adapt SOGo main view display
let myElement = document.querySelector("main");
myElement.style.position = "fixed";
myElement.style.top = "0px";
myElement.style.paddingTop = "37px";
const scriptUrl = '{{ navbar_url }}';
loadScript(scriptUrl).then(() => {
console.log('script loaded');
}, () => {
console.log('fail to load script');
});
Le code de la nav est sous double licence,
Creative Commons BY-SA http://creativecommons.org/licenses/by-sa/2.0/
et GNU Free Documentation License http://www.gnu.org/copyleft/fdl.html
Bootstrap est sous licence MIT : https://github.com/twbs/bootstrap
jQuery est sous licence MIT : http://jquery.com/download/
Font-awesome est sous licence SIL OFL 1.1 : http://fortawesome.github.io/Font-Awesome/license/
<html>
<body>
<script src="nav.js"></script>
</body>
</html>
This diff is collapsed.
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