yunohost-fosdem-2017/template.html
Laurent Peuch 4ddc2d735f init
2017-01-30 04:56:50 +01:00

930 lines
23 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<meta charset="utf-8">
<title>YunoHost</title>
<!-- Your Slides -->
<!-- One section is one slide -->
<section>
<div class="center" style="height: 100%; display: flex">
<img src="img/logo.png" style="margin: auto">
</div>
</section>
<section>
<h2>Me</h2>
</section>
<section>
<h3>YunoHost short history</h3>
<ul class="incremental">
<li>2011 - Beudbeud install his mail server, kload wants the same</li>
<li>2012 - first release</li>
<li>Feature list grows:
<ul class="incremental">
<li>xmpp</li>
<li>several domains</li>
<li>"applications"</li>
<li>SSO</li>
<li>etc...</li>
</ul>
</li>
</ul>
</section>
<section>
<h3>Political context</h3>
<ul>
<li>Internet Centralization</li>
<li>FDN/FFDN</li>
<li>La Quadrature du Net</li>
<li>HADOPI laws & co</li>
<li>GAFAM</li>
<li>mass surveillance</li>
</ul>
</section>
<section>
<h2>But what is YunoHost?</h2>
</section>
<section style="background-image: url('img/admin.png'); background-size: 100%; background-repeat: no-repeat; background-position-y: center;">
</section>
<section style="background-image: url('img/apps.png'); background-size: 100%; background-repeat: no-repeat; background-position-y: center;">
</section>
<section style="background-image: url('img/app_install_zerobin.png'); background-size: 100%; background-repeat: no-repeat; background-position-y: center;">
</section>
<section style="background-image: url('img/tools.png'); background-size: 100%; background-repeat: no-repeat; background-position-y: center;">
</section>
<section>
<h2>Architecture</h2>
</section>
<section>
<div style="display: flex; align-items: center; height: 100%">
<div>
<img style="width: 100%;" src="img/domains.png" />
</div>
<div style="width: 20px">
</div>
<div>
<img style="width: 100%;" src="img/cli.png" />
</div>
</div>
</section>
<section style="background-image: url('img/architecture.png'); background-size: 100%; background-repeat: no-repeat; background-position-y: center;">
</section>
<section>
<div style="display: flex; align-items: center; height: 100%">
<div>
<img style="width: 100%;" src="img/domain_list.py.png" />
</div>
<div style="width: 20px">
</div>
<div>
<img style="width: 100%;" src="img/actionmap.png" />
</div>
</div>
</section>
<section>
<div style="display: flex; align-items: center; height: 100%">
<div>
<img style="width: 100%;" src="img/files.png" />
</div>
<div style="width: 20px">
</div>
<div>
<img style="width: 100%;" src="img/help.png" />
</div>
</div>
</section>
<section style="background-image: url('img/ssoportal.png'); background-size: 100%; background-repeat: no-repeat; background-position-y: center;">
</section>
<section>
<h2>How apps are made</h2>
</section>
<section>
<div style="display: flex; align-items: center; height: 100%">
<div>
<img style="width: 100%;" src="img/app_root.png" />
</div>
<div style="width: 20px">
</div>
<div>
<img style="width: 100%;" src="img/app_scripts.png" />
</div>
<div style="width: 20px">
</div>
<div>
<img style="width: 100%;" src="img/manifest.json.png" />
</div>
</div>
</section>
<section>
<div style="display: flex; align-items: center; height: 100%">
<div>
<img style="width: 100%;" src="img/app_install_jirafeau.png" />
</div>
<div style="width: 20px">
</div>
<div>
<img style="width: 100%;" src="img/app_install.png" />
</div>
</div>
</section>
<section>
<h3 style="margin-bottom: 20px">Features list</h3>
<ul style="margin-top: 0px">
<li>debian based</li>
<li>users management: emails + xmpp</li>
<li>domain management: dyndns, own self-signed CA or Let's Encrypt</li>
<li>applications with SSO</li>
<li>services + regen-conf + hooks</li>
<li>firewall + fail2ban</li>
<li>backup</li>
<li>small monitoring</li>
<li>and growing...</li>
</ul>
</section>
<section>
<h3>Community, organisation and others</h3>
<ul class="incremental">
<li>1000 - 2000 users (hard to count)</li>
<li>20 official app, 63 (129) community</li>
<li>collective with our own constitution</li>
<li>Continuous Integration of apps</li>
<li>apps levels</li>
<li>Forum and xmpp chatrooms</li>
<li>Translations</li>
<li>quite le french</li>
</ul>
</section>
<section>
<h3>Friends</h3>
<ul>
<li>The Internet Cube / La Brique Internet</li>
<li>FFDN (associative ISPs)</li>
<li>Framasoft / CHATONS</li>
<li>and others &lt;3</li>
</ul>
</section>
<section>
<h3>Futur/Dreams/Ideas</h3>
<ul>
<li>borg backup
<li>friends backup each others
<li>monitoring
<li>friends monitor each others
<li>auto detect error
<li>auto repair errors?
<li>"app market"
</ul>
</section>
<section>
<h2>Questions?</h2>
</section>
<!--
moi
"YunoHost est un outil qui vous permet dinstaller et dutiliser facilement votre propre serveur.""
histoire:
* 2011 beudbeud install son serveur mail, kload "je veux le même"
* c'est super chiant à porter -> coder un truc
partant de là YunoHost a évoléu petit à petit:
* emails
* xmpp
* several domains
* dyndns
* "applications"
* services
* firewalls
* backup
* SSO
* etc...
Context fortement politisé: lqdn, ffdn, etc...
graphique architecture
cli vs admin
exemple de code + yaml + commande
regen conf
hooks
community
* forum
* # of users
* very le french
Framasoft
La brique Internet
organisation
* schéma
latest release with LE
Apps:
* levels
* CI
Ideas/future/dreams:
* borg backup
* friends backup each others
* monitoring
* friends monitor each others
* auto detect error (bad domain configuration, blocked ports)
* "app market"
-->
<!-- Your Style -->
<!-- Define the style of your presentation -->
<!-- Maybe a font from http://www.google.com/webfonts ? -->
<link href='http://fonts.googleapis.com/css?family=Oswald' rel='stylesheet'>
<style>
html, .view body {
background-color: #050505;
counter-reset: slideidx;
}
body, .view section {
color: #eee;
}
/* A section is a slide. It's size is 800x600, and this will never change */
section, .view head > title {
/* The font from Google */
font-family: 'Oswald', arial, serif;
font-size: 30px;
}
.view section:after {
counter-increment: slideidx;
content: counter(slideidx, decimal-leading-zero);
position: absolute; bottom: -80px; right: 100px;
color: white;
}
a {
color: #D7AF5F;
text-decoration: none;
}
.table {
margin: auto;
width: 100%;
}
.table td {
padding: 3px;
}
.center {
text-align: center;
}
.date {
color: #bbb;
font-size: normal;
}
.view head > title {
color: white;
text-align: center;
margin: 1em 0 1em 0;
}
h1 {
margin-top: 200px;
text-align: center;
font-size: 70px;
text-transform: uppercase;
}
h2 {
margin-top: 200px;
text-align: center;
font-size: 80px;
}
.background-light {
text-shadow: 1px 1px 1px white;
}
.rainbow {
background-image: -webkit-gradient( linear, left top, right top, color-stop(0, #f22), color-stop(0.15, #f2f), color-stop(0.3, #22f), color-stop(0.45, #2ff), color-stop(0.6, #2f2),color-stop(0.75, #2f2), color-stop(0.9, #ff2), color-stop(1, #f22) );
background-image: gradient( linear, left top, right top, color-stop(0, #f22), color-stop(0.15, #f2f), color-stop(0.3, #22f), color-stop(0.45, #2ff), color-stop(0.6, #2f2),color-stop(0.75, #2f2), color-stop(0.9, #ff2), color-stop(1, #f22) );
color:transparent;
-webkit-background-clip: text;
background-clip: text;
}
h3 {
margin: 100px 0 50px 100px;
}
ul, ol {
margin: 50px 200px;
}
li > ul {
margin: 15px 50px;
}
p {
margin: 75px;
font-size: 50px;
}
.standalone-quote {
margin: auto;
margin-top: 200px;
}
blockquote {
height: 100%;
font-size: 60px;
padding: 50px;
}
blockquote:before {
content: open-quote;
}
blockquote:after {
content: close-quote;
}
/* Figures are displayed full-page, with the caption
on top of the image/video */
figure {
background-color: black;
width: 100%;
height: 100%;
}
figure > * {
position: absolute;
}
figure > img, figure > video {
width: 100%; height: 100%;
}
figcaption {
margin: 70px;
font-size: 50px;
}
footer {
position: absolute;
bottom: 0;
width: 100%;
padding: 40px;
text-align: right;
background-color: #F3F4F8;
border-top: 1px solid #CCC;
}
/* Transition effect */
/* Feel free to change the transition effect for original
animations. See here:
https://developer.mozilla.org/en/CSS/CSS_transitions
How to use CSS3 Transitions: */
section {
/*
-moz-transition: left 400ms linear 0s;
-webkit-transition: left 400ms linear 0s;
-ms-transition: left 400ms linear 0s;
transition: left 400ms linear 0s;
*/
}
.view section {
-moz-transition: none;
-webkit-transition: none;
-ms-transition: none;
transition: none;
}
.view section[aria-selected] {
border: 5px red solid;
}
/* Before */
section { left: -150%; }
/* Now */
section[aria-selected] { left: 0; }
/* After */
section[aria-selected] ~ section { left: +150%; }
/* Incremental elements */
/* By default, visible */
.incremental > * { opacity: 1; }
/* The current item */
.incremental > *[aria-selected] { opacity: 1; }
/* The items to-be-selected */
.incremental > *[aria-selected] ~ * { opacity: 0; }
/* The progressbar, at the bottom of the slides, show the global
progress of the presentation. */
#progress-bar {
height: 0px;
background: #AAA;
}
small {
color: #b6b6b6;
}
</style>
<!-- {{{{ dzslides core
#
#
# __ __ __ . __ ___ __
# | \ / /__` | | | \ |__ /__`
# |__/ /_ .__/ |___ | |__/ |___ .__/ core :€
#
#
# The following block of code is not supposed to be edited.
# But if you want to change the behavior of these slides,
# feel free to hack it!
#
-->
<div id="progress-bar"></div>
<!-- Default Style -->
<style>
* { margin: 0; padding: 0; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; }
[role="note"] { display: none; }
body {
width: 800px; height: 600px;
margin-left: -400px; margin-top: -300px;
position: absolute; top: 50%; left: 50%;
overflow: hidden;
display: none;
}
.view body {
position: static;
margin: 0; padding: 0;
width: 100%; height: 100%;
display: inline-block;
overflow: visible; overflow-x: hidden;
/* undo Dz.onresize */
transform: none !important;
-moz-transform: none !important;
-webkit-transform: none !important;
-o-transform: none !important;
-ms-transform: none !important;
}
.view head, .view head > title { display: block }
section {
position: absolute;
pointer-events: none;
width: 100%; height: 100%;
}
.view section {
pointer-events: auto;
position: static;
width: 800px; height: 600px;
margin: -150px -200px;
float: left;
transform: scale(.4);
-moz-transform: scale(.4);
-webkit-transform: scale(.4);
-o-transform: scale(.4);
-ms-transform: scale(.4);
}
.view section > * { pointer-events: none; }
section[aria-selected] { pointer-events: auto; }
html { overflow: hidden; }
html.view { overflow: visible; }
body.loaded { display: block; }
.incremental {visibility: hidden; }
.incremental[active] {visibility: visible; }
#progress-bar{
bottom: 0;
position: absolute;
-moz-transition: width 400ms linear 0s;
-webkit-transition: width 400ms linear 0s;
-ms-transition: width 400ms linear 0s;
transition: width 400ms linear 0s;
}
.view #progress-bar {
display: none;
}
</style>
<script>
var Dz = {
remoteWindows: [],
idx: -1,
step: 0,
html: null,
slides: null,
progressBar : null,
params: {
autoplay: "1"
}
};
Dz.init = function() {
document.body.className = "loaded";
this.slides = Array.prototype.slice.call($$("body > section"));
this.progressBar = $("#progress-bar");
this.html = document.body.parentNode;
this.setupParams();
this.onhashchange();
this.setupTouchEvents();
this.onresize();
this.setupView();
}
Dz.setupParams = function() {
var p = window.location.search.substr(1).split('&');
p.forEach(function(e, i, a) {
var keyVal = e.split('=');
Dz.params[keyVal[0]] = decodeURIComponent(keyVal[1]);
});
// Specific params handling
if (!+this.params.autoplay)
$$.forEach($$("video"), function(v){ v.controls = true });
}
Dz.onkeydown = function(aEvent) {
// Don't intercept keyboard shortcuts
if (aEvent.altKey
|| aEvent.ctrlKey
|| aEvent.metaKey
|| aEvent.shiftKey) {
return;
}
if ( aEvent.keyCode == 37 // left arrow
|| aEvent.keyCode == 38 // up arrow
|| aEvent.keyCode == 33 // page up
) {
aEvent.preventDefault();
this.back();
}
if ( aEvent.keyCode == 39 // right arrow
|| aEvent.keyCode == 40 // down arrow
|| aEvent.keyCode == 34 // page down
) {
aEvent.preventDefault();
this.forward();
}
if (aEvent.keyCode == 35) { // end
aEvent.preventDefault();
this.goEnd();
}
if (aEvent.keyCode == 36) { // home
aEvent.preventDefault();
this.goStart();
}
if (aEvent.keyCode == 32) { // space
aEvent.preventDefault();
this.toggleContent();
}
if (aEvent.keyCode == 70) { // f
aEvent.preventDefault();
this.goFullscreen();
}
if (aEvent.keyCode == 79) { // o
aEvent.preventDefault();
this.toggleView();
}
}
/* Touch Events */
Dz.setupTouchEvents = function() {
var orgX, newX;
var tracking = false;
var db = document.body;
db.addEventListener("touchstart", start.bind(this), false);
db.addEventListener("touchmove", move.bind(this), false);
function start(aEvent) {
aEvent.preventDefault();
tracking = true;
orgX = aEvent.changedTouches[0].pageX;
}
function move(aEvent) {
if (!tracking) return;
newX = aEvent.changedTouches[0].pageX;
if (orgX - newX > 100) {
tracking = false;
this.forward();
} else {
if (orgX - newX < -100) {
tracking = false;
this.back();
}
}
}
}
Dz.setupView = function() {
document.body.addEventListener("click", function ( e ) {
if (!Dz.html.classList.contains("view")) return;
if (!e.target || e.target.nodeName != "SECTION") return;
Dz.html.classList.remove("view");
Dz.setCursor(Dz.slides.indexOf(e.target) + 1);
}, false);
}
/* Adapt the size of the slides to the window */
Dz.onresize = function() {
var db = document.body;
var sx = db.clientWidth / window.innerWidth;
var sy = db.clientHeight / window.innerHeight;
var transform = "scale(" + (1/Math.max(sx, sy)) + ")";
db.style.MozTransform = transform;
db.style.WebkitTransform = transform;
db.style.OTransform = transform;
db.style.msTransform = transform;
db.style.transform = transform;
}
Dz.getNotes = function(aIdx) {
var s = $("section:nth-of-type(" + aIdx + ")");
var d = s.$("[role='note']");
return d ? d.innerHTML : "";
}
Dz.onmessage = function(aEvent) {
var argv = aEvent.data.split(" "), argc = argv.length;
argv.forEach(function(e, i, a) { a[i] = decodeURIComponent(e) });
var win = aEvent.source;
if (argv[0] === "REGISTER" && argc === 1) {
this.remoteWindows.push(win);
this.postMsg(win, "REGISTERED", document.title, this.slides.length);
this.postMsg(win, "CURSOR", this.idx + "." + this.step);
return;
}
if (argv[0] === "BACK" && argc === 1)
this.back();
if (argv[0] === "FORWARD" && argc === 1)
this.forward();
if (argv[0] === "START" && argc === 1)
this.goStart();
if (argv[0] === "END" && argc === 1)
this.goEnd();
if (argv[0] === "TOGGLE_CONTENT" && argc === 1)
this.toggleContent();
if (argv[0] === "SET_CURSOR" && argc === 2)
window.location.hash = "#" + argv[1];
if (argv[0] === "GET_CURSOR" && argc === 1)
this.postMsg(win, "CURSOR", this.idx + "." + this.step);
if (argv[0] === "GET_NOTES" && argc === 1)
this.postMsg(win, "NOTES", this.getNotes(this.idx));
}
Dz.toggleContent = function() {
// If a Video is present in this new slide, play it.
// If a Video is present in the previous slide, stop it.
var s = $("section[aria-selected]");
if (s) {
var video = s.$("video");
if (video) {
if (video.ended || video.paused) {
video.play();
} else {
video.pause();
}
}
}
}
Dz.setCursor = function(aIdx, aStep) {
// If the user change the slide number in the URL bar, jump
// to this slide.
aStep = (aStep != 0 && typeof aStep !== "undefined") ? "." + aStep : ".0";
window.location.hash = "#" + aIdx + aStep;
}
Dz.onhashchange = function() {
var cursor = window.location.hash.split("#"),
newidx = 1,
newstep = 0;
if (cursor.length == 2) {
newidx = ~~cursor[1].split(".")[0];
newstep = ~~cursor[1].split(".")[1];
if (newstep > Dz.slides[newidx - 1].$$('.incremental > *').length) {
newstep = 0;
newidx++;
}
}
this.setProgress(newidx, newstep);
if (newidx != this.idx) {
this.setSlide(newidx);
}
if (newstep != this.step) {
this.setIncremental(newstep);
}
for (var i = 0; i < this.remoteWindows.length; i++) {
this.postMsg(this.remoteWindows[i], "CURSOR", this.idx + "." + this.step);
}
}
Dz.back = function() {
if (this.idx == 1 && this.step == 0) {
return;
}
if (this.step == 0) {
this.setCursor(this.idx - 1,
this.slides[this.idx - 2].$$('.incremental > *').length);
} else {
this.setCursor(this.idx, this.step - 1);
}
}
Dz.forward = function() {
if (this.idx >= this.slides.length &&
this.step >= this.slides[this.idx - 1].$$('.incremental > *').length) {
return;
}
if (this.step >= this.slides[this.idx - 1].$$('.incremental > *').length) {
this.setCursor(this.idx + 1, 0);
} else {
this.setCursor(this.idx, this.step + 1);
}
}
Dz.goStart = function() {
this.setCursor(1, 0);
}
Dz.goEnd = function() {
var lastIdx = this.slides.length;
var lastStep = this.slides[lastIdx - 1].$$('.incremental > *').length;
this.setCursor(lastIdx, lastStep);
}
Dz.toggleView = function() {
this.html.classList.toggle("view");
if (this.html.classList.contains("view")) {
$("section[aria-selected]").scrollIntoView(true);
}
}
Dz.setSlide = function(aIdx) {
this.idx = aIdx;
var old = $("section[aria-selected]");
var next = $("section:nth-of-type("+ this.idx +")");
if (old) {
old.removeAttribute("aria-selected");
var video = old.$("video");
if (video) {
video.pause();
}
}
if (next) {
next.setAttribute("aria-selected", "true");
if (this.html.classList.contains("view")) {
next.scrollIntoView();
}
var video = next.$("video");
if (video && !!+this.params.autoplay) {
video.play();
}
} else {
// That should not happen
this.idx = -1;
// console.warn("Slide doesn't exist.");
}
}
Dz.setIncremental = function(aStep) {
this.step = aStep;
var old = this.slides[this.idx - 1].$('.incremental > *[aria-selected]');
if (old) {
old.removeAttribute('aria-selected');
}
var incrementals = $$('.incremental');
if (this.step <= 0) {
$$.forEach(incrementals, function(aNode) {
aNode.removeAttribute('active');
});
return;
}
var next = this.slides[this.idx - 1].$$('.incremental > *')[this.step - 1];
if (next) {
next.setAttribute('aria-selected', true);
next.parentNode.setAttribute('active', true);
var found = false;
$$.forEach(incrementals, function(aNode) {
if (aNode != next.parentNode)
if (found)
aNode.removeAttribute('active');
else
aNode.setAttribute('active', true);
else
found = true;
});
} else {
setCursor(this.idx, 0);
}
return next;
}
Dz.goFullscreen = function() {
var html = $('html'),
requestFullscreen = html.requestFullscreen || html.requestFullScreen || html.mozRequestFullScreen || html.webkitRequestFullScreen;
if (requestFullscreen) {
requestFullscreen.apply(html);
}
}
Dz.setProgress = function(aIdx, aStep) {
var slide = $("section:nth-of-type("+ aIdx +")");
if (!slide)
return;
var steps = slide.$$('.incremental > *').length + 1,
slideSize = 100 / (this.slides.length - 1),
stepSize = slideSize / steps;
this.progressBar.style.width = ((aIdx - 1) * slideSize + aStep * stepSize) + '%';
}
Dz.postMsg = function(aWin, aMsg) { // [arg0, [arg1...]]
aMsg = [aMsg];
for (var i = 2; i < arguments.length; i++)
aMsg.push(encodeURIComponent(arguments[i]));
aWin.postMessage(aMsg.join(" "), "*");
}
function init() {
Dz.init();
window.onkeydown = Dz.onkeydown.bind(Dz);
window.onresize = Dz.onresize.bind(Dz);
window.onhashchange = Dz.onhashchange.bind(Dz);
window.onmessage = Dz.onmessage.bind(Dz);
}
window.onload = init;
</script>
<script> // Helpers
if (!Function.prototype.bind) {
Function.prototype.bind = function (oThis) {
// closest thing possible to the ECMAScript 5 internal IsCallable
// function
if (typeof this !== "function")
throw new TypeError(
"Function.prototype.bind - what is trying to be fBound is not callable"
);
var aArgs = Array.prototype.slice.call(arguments, 1),
fToBind = this,
fNOP = function () {},
fBound = function () {
return fToBind.apply( this instanceof fNOP ? this : oThis || window,
aArgs.concat(Array.prototype.slice.call(arguments)));
};
fNOP.prototype = this.prototype;
fBound.prototype = new fNOP();
return fBound;
};
}
var $ = (HTMLElement.prototype.$ = function(aQuery) {
return this.querySelector(aQuery);
}).bind(document);
var $$ = (HTMLElement.prototype.$$ = function(aQuery) {
return this.querySelectorAll(aQuery);
}).bind(document);
$$.forEach = function(nodeList, fun) {
Array.prototype.forEach.call(nodeList, fun);
}
</script>
<!-- vim: set fdm=marker: }}} -->