Spickerrrrrrrrrrr!

Check-in [a48102b1c6]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Erste Version.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: a48102b1c6d76c8224e24ffea3c627529cc3c2e3dbbfa32889ab777aa94779eb
User & Date: Cthulhux 2019-09-04 23:48:46
Context
2019-09-05
00:12
Unicode check-in: 86d030aa75 user: Cthulhux tags: trunk
2019-09-04
23:48
Erste Version. check-in: a48102b1c6 user: Cthulhux tags: trunk
20:53
initial empty check-in check-in: 3dc27e99c4 user: Cthulhux tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Added README.md.





































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# Spickerrrrrretc.

* Ein portables Web-UI fŘr den [Spickerrr](https://spickerrr.piraten-tools.de).

## Runterladen

* Dieses Tool wird auf [code.rosaelefanten.org](https://code.rosaelefanten.org/web-spicker) gehostet.
* Es gibt einen Mirror auf [GitHub](https://github.com/dertuxmalwieder/piratenpartei-web-spicker), der vielleicht, vielleicht aber auch nicht, auf dem neuesten Stand ist.

## Installation

* Besorgt euch Perl.
* Installiert Mojolicious: `cpan install Mojolicious`
* `hypnotoad ./spicker.pl`

## Feedback

* [Thread im Piratenforum](https://forum.piratenpartei.de/t/spickerrr-das-mobile-antragsbuch-fuer-unterwegs/2896)

Added public/IBMPlexSerif-Regular.woff.

cannot compute difference between binary files

Added public/IBMPlexSerif-Regular.woff2.

cannot compute difference between binary files

Added public/base.css.



































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
@font-face {
    font-family: IBMPlexSerif;
    src: url(IBMPlexSerif-Regular.woff2) format("woff2"), url(IBMPlexSerif-Regular.woff) format("woff");
}

body {
    background-color: white;
    font-family: IBMPlexSerif, Vollkorn, serif;
    margin: 0;
    padding: 8px;
}

a:link, a:visited {
    color: blue;
    text-decoration: underline;
}

label {
    display: inline-block;
    font-size: 16px;
    font-weight: bold;
    width: 100px;
}

select {
    font-family: IBMPlexSerif, Vollkorn, serif;
    font-size: 16px;
    font-weight: bold;
    width: 300px;
}

footer {
    position: fixed;
    bottom: 5px;
    left: 5px;
    margin-top: 25px;
    padding: 6px;
    display: block;
    background-color: orange;
    width: 100%;
    height: 20px;
}

header {
    background-color: black;
    color: orange;
    display: block;
    font-size: 24px;
    font-weight: bold;
    padding: 4px;
}

main {
    margin: 20px;
    overflow: auto;
}

div#content_header {
    font-weight: bold;
    margin-top: 10px;
}

div#content_antragsteller {
    font-style: italic;
    margin-top: 10px;
}

div#content_antrag {
    border-top: 1px solid black;
    padding-top: 5px;
    margin-top: 10px;
}

div#content_begruendung {
    margin-left: 30px;
}

div#content_begruendung::first-line {
    font-weight: bold;
    margin-left: -30px;
}

Added public/base.js.























































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
function panic(str) {
    // AAAAAAAAAAAHHHH!
    alert("@tux0r hat einen Fehler gemacht!... " + str);
}

function fillInitSelect() {
    // F├╝llt die Parteitagsselectbox zu Beginn.
    let selParteitag = document.getElementById("parteitage");

    fetch("Parteitage",
        { method: "POST" })
    .then(res => res.json())
    .then(data => {
        let dummyoption = document.createElement("option");
        dummyoption.value = "dummy";
        dummyoption.innerHTML = "- bitte ausw├Ąhlen -";
        selParteitag.appendChild(dummyoption);
        
        if (data["data"] !== undefined && data["data"].length > 0) {
            data["data"].forEach(parteitag => {
                /* parteitag["Key"] und parteitag["Name"] in Selectbox
                   f├╝llen: */
                let option = document.createElement("option");
                option.value = parteitag["Key"];
                option.innerHTML = parteitag["Name"];
                selParteitag.appendChild(option);
            });
            
            selParteitag.disabled = false;
        }
    })
    .catch(error => panic(error));
}

function listAntraege() {
    // F├╝llt die Antragsselectbox.
    let selParteitag = document.getElementById("parteitage");
    let selAntrag = document.getElementById("antraege");
    
    fetch("Parteitag/" + selParteitag.value,
        { method: "POST" })
    .then(res => res.json())
    .then(data => {
        let dummyoption = document.createElement("option");
        dummyoption.value = "dummy";
        dummyoption.innerHTML = "- bitte ausw├Ąhlen -";
        selAntrag.appendChild(dummyoption);
        
        data.forEach(antrag => {
            /* Antrag in Selectbox f├╝llen: */
            let option = document.createElement("option");
            option.value = antrag["id"];
            option.innerHTML = antrag["id"] /* + " - " + antrag["title"] */;
            selAntrag.appendChild(option);
        });
        
        selAntrag.disabled = false;
    })
    .catch(error => panic(error));
}

function zeigeAntrag() {
    // Ruft einen Antrag ab und zeigt ihn an.
    let selParteitag = document.getElementById("parteitage");
    let selAntrag = document.getElementById("antraege");
    let divInhalt = document.getElementById("inhalt");
    
    fetch("Parteitag/" + selParteitag.value + "/Antrag/" + selAntrag.value,
        { method: "POST" })
    .then(res => res.text())
    .then(data => {
        divInhalt.innerHTML = data;
    })
    .catch(error => panic(error));
}

Added spicker.pl.















































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#!/usr/bin/env perl

package webspicker;

use strict;
use warnings;
use utf8;

use Mojo::JSON qw(decode_json);
use Mojo::UserAgent;
use Mojolicious::Lite;

our $APIURL = 'https://spickerrr.piraten-tools.de/api/';

# ----------------------------------------------------
# Routing
# ----------------------------------------------------

get '/' => sub {
    # ├ťbersichtsseite:
    my $c = shift;
    $c->render(template => 'start');
};

post '/Parteitage' => sub {
    # AJAX-Anfrage: Liste der Parteitage
    my $c = shift;
    
    my $ua  = Mojo::UserAgent->new;
    my $url = "${APIURL}currentbooks";

    $c->render(json => $ua->get($url)->result->json);
};

post '/Parteitag/:parteitag' => sub {
    # AJAX-Anfrage: Liste der Antr├Ąge
    my $c = shift;
    my $parteitag = $c->stash('parteitag');
    
    if ($parteitag ne 'dummy') {    
        my $ua  = Mojo::UserAgent->new;
        my $url = "${APIURL}book/${parteitag}/motions";
	    
        $c->render(json => $ua->get($url)->result->json);
    }
};

post '/Parteitag/:parteitag/Antrag/:antrag' => sub {
    # AJAX-Anfrage: Antrag :antrag f├╝r Parteitag :parteitag
    my $c = shift;
    my $parteitag = $c->stash('parteitag');
    my $antrag = $c->stash('antrag');
    
    if ($antrag ne 'dummy') {    
        my $ua       = Mojo::UserAgent->new;
        my $url      = "${APIURL}book/${parteitag}/motions";
        my $antraege = $ua->get($url)->result->json;
        
        my $needle_location = -1;
        
        while (my ($idx, $elem) = each(@{$antraege})) {
            if ($elem->{'id'} eq $antrag) {
                $needle_location = $idx;
                last;
            }
        }
        
        # Der gesuchte Antrag steht jetzt in $antraege->[$needle_location].
        # Aufbereiten f├╝r die Anzeige:
	    my $antrag = $antraege->[$needle_location];
	    
	    # Im Antragstext k├Ânnten Wikilinks drin sein. B├Ąh ... :-)
	    my $antragstext = $antrag->{text};
	    $antragstext =~ s/<a href="(\\)?\//<a href="https:\/\/wiki.piratenpartei.de\//g;
	    
	    $c->content_for(author => $antrag->{author});
	    $c->stash(origlink => $antrag->{url});
	    $c->stash(antragsid => $antrag->{id});
	    $c->stash(title => $antrag->{title});
	    $c->content_for(antrag => $antragstext);
	    $c->content_for(begruendung => $antrag->{remarks});
	    
        $c->render(template => 'antrag');
    }
};

app->start;

Added templates/antrag.html.ep.

































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<div id="content_header"><a href="<%= $origlink %>" target="_blank" title="Antrag im Antragsportal anzeigen">Antrag <%= $antragsid %></a>: <%= $title %></div>

<div id="content_antragsteller">
Antragsteller:
%= content 'author'
</div>

<div id="content_antrag">
%= content 'antrag'
</div>

<div id="content_begruendung">
<p>Begr├╝ndung:</p>

%= content 'begruendung'
</div>

Added templates/layouts/base_layout.html.ep.















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!doctype html>
<html>
  <head>
    <title><%= title %></title>
    %= stylesheet '/base.css'
    %= javascript '/base.js'
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta charset="utf-8" />
    <script language="javascript" type="text/javascript">
    document.addEventListener("DOMContentLoaded", function() {
        /* Liste der Parteitage auslesen: */
        fillInitSelect();
    });
    </script>
  </head>
  <body>
    <header><%= title %> - viel weniger schlecht.&trade;</header>
    <main>
      <article><%= content %></article>
    </main>
    <footer>Beschwert euch bei <a href="https://twitter.com/tux0r" target="_blank">@tux0r</a>.</footer>
  </body>
</html>

Added templates/start.html.ep.















>
>
>
>
>
>
>
1
2
3
4
5
6
7
% title 'Spickerrrrrrrrrrr!';
% layout 'base_layout';

<label for="parteitage">Parteitag:</label> <select name="parteitage" id="parteitage" disabled="disabled" onchange="listAntraege()"></select><br />
<label for="antraege">Antrag:</label> <select name="antraege" id="antraege" disabled="disabled" onchange="zeigeAntrag()"></select><br />
<br />
<div id="inhalt"></div>