Skip to content

Commit 8421726

Browse files
committed
progress in the individual page experiment
1 parent b41dbee commit 8421726

File tree

5 files changed

+241
-33
lines changed

5 files changed

+241
-33
lines changed

backend.js

+75-2
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,8 @@ app.get('/api/details/:memberState', cors(), async function (req, res) {
126126
app.get('/api', cors(), function (req, res) {
127127
const implemented = [
128128
"/api/meps/:filter?", "/api/homepage", "/api/squared",
129-
"/api/stats", "/api/details/:memberState", "/api/emotional"];
129+
"/api/stats", "/api/details/:memberState", "/api/emotional",
130+
"/api/individual/:id", "/api/group/:name"];
130131
res.status(200);
131132
res.send(`
132133
<code>dontspyonus.eu</code><hr/>
@@ -144,6 +145,9 @@ app.get('/api/group/:name', cors(), async (req, res) => {
144145
console.log(`Group API called with ${name}`);
145146
const data = await queryMEPs({ group: name });
146147

148+
if(!data.length)
149+
throw new Error(`Unable to find group ${name}`);
150+
147151
const ready = _.map(data, function (mep) {
148152
const o = _.omit(mep, ['_id']);
149153
o.facerec = _.omit(_.first(mep.facerec), ['_id', 'id']);
@@ -214,7 +218,77 @@ app.get('/api/emotionals', cors(), async (req, res) => {
214218
message: error.message
215219
})
216220
}
221+
});
217222

223+
app.get('/api/list', cors(), async (req, res) => {
224+
/* pick all the MEPs and return them in a CSV format,
225+
* with the following fields:
226+
* id, name, nation, group, party, twitter */
227+
const flist = ['id', 'name', 'nation', 'group', 'party', 'twitter'];
228+
try {
229+
const data = await queryMEPs({});
230+
const selected = _.map(data, function (mep) {
231+
return _.pick(mep, flist);
232+
});
233+
const textual = _.reduce(selected, function (memo, mep) {
234+
memo.push(_.values(mep).join(","));
235+
return memo;
236+
}, [ flist.join(",") ] );
237+
238+
console.log(`List API returning ${textual.length}`);
239+
res.status(200);
240+
/* set the header to make the CSV download with name 'list.csv' */
241+
res.header('Content-Disposition', 'attachment; filename="list.csv"');
242+
res.header('Content-Type', 'text/plain');
243+
res.send(textual.join("\n"));
244+
}
245+
catch (error) {
246+
res.status(500);
247+
console.log(`Error: ${error.message}`);
248+
res.json({
249+
error: true,
250+
message: error.message
251+
});
252+
}
253+
});
254+
255+
app.get('/api/individual/:idList', cors(), async (req, res) => {
256+
/* pick up the MEP by id and transform the data in the same
257+
* format as we do for the group API */
258+
try {
259+
const ids = req.params.idList.split(',');
260+
const data = await queryMEPs({ id: { "$in": ids } });
261+
if (!data.length)
262+
throw new Error(`Unable to find MEP with id ${req.params.idList}`);
263+
264+
const ready = _.map(data, function (mep) {
265+
const o = _.omit(mep, ['_id']);
266+
o.facerec = _.omit(_.first(mep.facerec), ['_id', 'id']);
267+
o.facerec.expressions = _.reduce(o.facerec.expressions, function (memo, val, emo) {
268+
const effective = _.round(val * 100, 1);
269+
if (effective < 1)
270+
return memo;
271+
272+
memo.push({
273+
emotion: emo,
274+
value: effective
275+
})
276+
return memo;
277+
}, []);
278+
return o;
279+
});
280+
281+
console.log(`Individual API returning ${ready.length} meps`);
282+
res.status(200);
283+
res.json(ready);
284+
} catch(error) {
285+
res.status(500);
286+
console.log(`Error: ${error.message}`);
287+
res.json({
288+
error: true,
289+
message: error.message
290+
});
291+
}
218292
});
219293

220294
app.get('/api/squared', cors(), async function (req, res) {
@@ -246,7 +320,6 @@ app.get('/api/squared', cors(), async function (req, res) {
246320
}
247321
});
248322

249-
250323
app.get('/api/homepage', cors(), async function (req, res) {
251324
/* at the moment homepage returns random */
252325
try {

site/content/individual/index.md

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
---
2+
title: 'Special page: pictures from ID'
3+
type: "individual"
4+
---
5+
6+
How does it works? by picking one of the ID from [this CSV](https://dontspyonus.eu/api/list), you can compose an URL like `https://dontspyonus.eu/individual#124973,124936` it would produce a picture composed by the two faces. [EXAMPLE](/individual#124973,124936,197820)
7+
8+
9+
<script type="text/javascript" src="/js/group.js"></script>
10+
11+
<script>
12+
window.addEventListener('load', loadPhotos);
13+
14+
const serverAPI =
15+
window.location.hostname === 'localhost' ?
16+
'http://localhost:2023/api/individual' : '/api/individual';
17+
18+
async function loadPhotos() {
19+
const ids = window.location.hash;
20+
const check = ids.split(',');
21+
if(check.length !== 3) {
22+
$("#target").html("<h3>Error, expected three IDs</h3>");
23+
return;
24+
}
25+
const resp = await fetch(`${serverAPI}/${ids.substr(1)}`);
26+
const mep = await resp.json()
27+
const htmli = produceHTML(mep);
28+
$("#target").html(htmli);
29+
}
30+
</script>

site/layouts/individual/single.html

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{{ define "main" }}
2+
3+
<section class="about section mt-5">
4+
<h2 class="section__title">
5+
{{ .Title }}
6+
</h2>
7+
<span class="section__subtitle mb-1">
8+
{{ .Params.subtitle }}
9+
</span>
10+
<br />
11+
<br />
12+
<div class="container grid">
13+
{{ .Content }}
14+
</div>
15+
<hr />
16+
<div class="container">
17+
<div id="target"></div>
18+
</div>
19+
</section>
20+
21+
{{end}}

site/static/css/upload.css

+32
Original file line numberDiff line numberDiff line change
@@ -121,3 +121,35 @@
121121
margin: 1px;
122122
padding: 1px;
123123
}
124+
125+
/* individual */
126+
.main--table {
127+
width: 80%;
128+
margin-left: 10%;
129+
margin-top: 70px;
130+
margin-bottom: 70px;
131+
border-collapse: collapse;
132+
border: 1px solid #ddd;
133+
background: whitesmoke;
134+
}
135+
136+
.group--name {
137+
font-size: 11px;
138+
font-family: 'Courier New', Courier, monospace;
139+
word-break: break-word;
140+
};
141+
142+
.party--name {
143+
font-size: 10px;
144+
word-break: break-word;
145+
}
146+
147+
.table--data {
148+
line-height: 15px;
149+
max-width: 220px;
150+
}
151+
152+
.mep--name {
153+
font-size: 14px;
154+
font-weight: 700;
155+
}

site/static/js/group.js

+83-31
Original file line numberDiff line numberDiff line change
@@ -35,38 +35,38 @@ async function rendermeps() {
3535

3636
}
3737

38-
const EUMS = {
39-
'Austria': "🇦🇹",
40-
'Belgium': "🇧🇪",
41-
'Bulgaria': "🇧🇬",
42-
'Croatia': "🇭🇷",
43-
'Cyprus': "🇨🇾",
44-
'Czechia': "🇨🇿",
45-
'Denmark': "🇩🇰",
46-
'Estonia': "🇪🇪",
47-
'Finland': "🇫🇮",
48-
'France': "🇫🇷",
49-
'Germany': "🇩🇪",
50-
'Greece': "🇬🇷",
51-
'Hungary': "🇭🇺",
52-
'Ireland': "🇮🇪",
53-
'Italy': "🇮🇹",
54-
'Latvia': "🇱🇻",
55-
'Lithuania': "🇱🇹",
56-
'Luxembourg': "🇱🇺",
57-
'Malta': "🇲🇹",
58-
'Netherlands': "🇳🇱",
59-
'Poland': "🇵🇱",
60-
'Portugal': "🇵🇹",
61-
'Romania': "🇷🇴",
62-
'Slovakia': "🇸🇰",
63-
'Slovenia': "🇸🇮",
64-
'Spain': "🇪🇸",
65-
'Sweden': "🇸🇪"
66-
};
38+
const EUMS = {
39+
'Austria': "🇦🇹",
40+
'Belgium': "🇧🇪",
41+
'Bulgaria': "🇧🇬",
42+
'Croatia': "🇭🇷",
43+
'Cyprus': "🇨🇾",
44+
'Czechia': "🇨🇿",
45+
'Denmark': "🇩🇰",
46+
'Estonia': "🇪🇪",
47+
'Finland': "🇫🇮",
48+
'France': "🇫🇷",
49+
'Germany': "🇩🇪",
50+
'Greece': "🇬🇷",
51+
'Hungary': "🇭🇺",
52+
'Ireland': "🇮🇪",
53+
'Italy': "🇮🇹",
54+
'Latvia': "🇱🇻",
55+
'Lithuania': "🇱🇹",
56+
'Luxembourg': "🇱🇺",
57+
'Malta': "🇲🇹",
58+
'Netherlands': "🇳🇱",
59+
'Poland': "🇵🇱",
60+
'Portugal': "🇵🇹",
61+
'Romania': "🇷🇴",
62+
'Slovakia': "🇸🇰",
63+
'Slovenia': "🇸🇮",
64+
'Spain': "🇪🇸",
65+
'Sweden': "🇸🇪"
66+
};
6767

6868
function loopOverFaces(faceStats, targetId) {
69-
const htmlblob = _.map(faceStats, function(mep, n) {
69+
const htmlblob = _.map(faceStats, function (mep, n) {
7070
/*
7171
TLC: "BG"
7272
email: "andrey.kovatchev@europarl.europa.eu"
@@ -79,7 +79,7 @@ function loopOverFaces(faceStats, targetId) {
7979
twitter: "http://twitter.com/andreykovatchev"
8080
urlimg: "https://www.europarl.europa.eu/mepphoto/97968.jpg" */
8181

82-
const emotions = _.map(mep.facerec.expressions, function(inf) {
82+
const emotions = _.map(mep.facerec.expressions, function (inf) {
8383
return `<div class="meprbi">${inf.emotion} ${inf.value}%</div>`;
8484
}).join('\n');
8585

@@ -118,4 +118,56 @@ function loopOverFaces(faceStats, targetId) {
118118
return rv;
119119
});
120120
$(targetId).html(htmlblob.join('\n'));
121+
}
122+
123+
function produceHTML(mepdata) {
124+
console.log(mepdata);
125+
126+
const rv = `<div class="picture-block">
127+
<table class="main--table">
128+
<tr>
129+
130+
<td class="table--data">
131+
<div class="mep--name">${EUMS[mepdata[0].nation]}<br> ${mepdata[0].name}</div>
132+
</td>
133+
<td class="table--data">
134+
<div class="mep--name">${EUMS[mepdata[1].nation]}<br> ${mepdata[1].name}</div>
135+
</td>
136+
<td class="table--data">
137+
<div class="mep--name">${EUMS[mepdata[2].nation]}<br> ${mepdata[2].name}</div>
138+
</td>
139+
</tr>
140+
141+
<tr>
142+
<td class="table--data">
143+
<img class="contained-image" src="/MEPs/pics/${mepdata[0].id}.jpg">
144+
</td>
145+
<td class="table--data">
146+
<img class="contained-image" src="/MEPs/pics/${mepdata[1].id}.jpg">
147+
</td>
148+
<td class="table--data">
149+
<img class="contained-image" src="/MEPs/pics/${mepdata[2].id}.jpg">
150+
</td>
151+
</tr>
152+
153+
<tr>
154+
<td class="table--data">
155+
156+
157+
<div class="party--name">${mepdata[0].party}</div>
158+
<small class="group--name">${mepdata[0].group}</small>
159+
</td>
160+
<td class="table--data">
161+
<div class="party--name">${mepdata[1].party}</div>
162+
<small class="group--name">${mepdata[1].group}</small>
163+
</td>
164+
<td class="table--data">
165+
<div class="party--name">${mepdata[2].party}</div>
166+
<small class="group--name">${mepdata[2].group}</small>
167+
</td>
168+
</tr>
169+
170+
</table>
171+
</div>`
172+
return rv;
121173
}

0 commit comments

Comments
 (0)