zwischenstand

This commit is contained in:
Thomas Hanika 2022-02-08 22:24:20 +01:00
parent 3222c2d77f
commit ac3674555c
6 changed files with 271 additions and 87 deletions

View file

@ -23,6 +23,10 @@ class Directory:
else:
self.displayname = name
def to_dict(self):
return {'name': self.name , 'displayname': self.displayname, 'count': self.item_count }
def mk_writeable_dir(path):
try:

View file

@ -149,7 +149,7 @@ def landing_api(path):
if category.endswith('language'):
language = request.args.get('language','german')
stations = radiobrowser.get_stations_by_language(language)
if category.endswith('countrycode'):
if category.endswith('country'):
country = request.args.get('country','Germany')
stations = radiobrowser.get_stations_by_country(country)
@ -163,7 +163,26 @@ def landing_api(path):
if path.endswith('bookmarks'):
category = request.args.get('category')
stations = my_stations.get_stations_by_category(category)
return flask.jsonify({'stations': stations})
if stations is not None:
stations_dict = []
for station in stations:
stations_dict.append(station.to_dict())
return flask.jsonify(stations_dict)
if path.endswith('paramlist'):
category = request.args.get('category')
directories = None
if category.endswith('language'):
directories = radiobrowser.get_language_directories();
if category.endswith('country'):
directories = radiobrowser.get_country_directories();
if directories is not None:
directories_dict = []
for directory in directories:
directories_dict.append(directory.to_dict())
return flask.jsonify(directories_dict)
return abort(400,'Not implemented: ' + path)

View file

@ -1,5 +1,28 @@
function createItem(name, icon, description) {
window.onload = function () {
category = document.getElementById('id_category').value;
param = document.getElementById('id_param').value;
requestStationList(category, param)
}
function initSearch() {
var stationsearch = document.getElementById('stationsearch');
stationsearch.value = '';
stationsearch.onkeyup = function () {
var filter = stationsearch.value.toUpperCase();
var lis = document.getElementsByTagName('li');
for (var i = 0; i < lis.length; i++) {
var searchval = lis[i].dataset.search;
if (searchval.indexOf(filter) > -1)
lis[i].style.display = 'flex';
else
lis[i].style.display = 'none';
}
}
}
function createItem(name, icon, description) {
var itemElem = document.createElement("div");
itemElem.className = "item";
@ -7,16 +30,17 @@ function createItem(name, icon, description) {
itemicon.className = "itemicon";
var itemiconimg = document.createElement("img");
itemiconimg.src = icon;
itemiconimg.className = "itemicon";
var itemtext = document.createElement("div");
itemtext.className = "itemtext";
var h4text = document.createElement("h4");
var h4text = document.createElement("h4");
h4text.textContent = name;
var desc = document.createElement("p");
desc.textContent = description;
itemicon.appendChild(itemiconimg);
itemtext.appendChild(h4text);
itemtext.appendChild(desc);
@ -26,11 +50,102 @@ function createItem(name, icon, description) {
return itemElem;
}
function stationsAddItem() {
var listElemet = document.createElement("li");
listElemet.className = "item";
listElemet.appendChild(createItem(" Halle self created","http://www.klassikradio.de/_nuxt/icons/icon_64.a00w80w0000.png","classic, poppi"));
function requestStationList(category, param) {
var url = 'api/stations?category=' + category;
document.getElementById("stationList").appendChild(listElemet);
if (category.indexOf('language') > -1) {
url = url + '&language=' + param.toLowerCase();
}
if (category.indexOf('country') > -1) {
url = url + '&country=' + param;
}
var myRequest = new Request(url);
var myOldList = document.getElementById("stationList");
var myList = myOldList.cloneNode(false);
myOldList.parentNode.replaceChild(myList, myOldList);
fetch(myRequest)
.then(response => response.json())
.then(data => {
for (const station of data) {
let listItem = document.createElement('li');
listItem.appendChild(
createItem(station.name, station.icon, station.description)
);
listItem.dataset.json = JSON.stringify(station);
listItem.dataset.search = (station.name + '#' + station.description).toUpperCase();
myList.appendChild(listItem);
}
})
.catch(console.error);
initSearch();
}
function onInputSelect(e, objElem) {
if (objElem.id == 'id_category') {
paramElem = document.getElementById('id_param')
param = paramElem.value
category = objElem.value
switch (category) {
case 'language':
setParamlist();
try {paramElem.fokus();} catch(e) {};
return;
case 'country':
setParamlist();
try {paramElem.fokus();} catch(e) {};
return;
default:
paramElem.disabled = true;
break;
}
requestStationList(category, param);
}
}
function setParamlist() {
var category = document.getElementById('id_category').value
var url = 'api/paramlist?category=' + category;
document.getElementById('id_param').value = '';
var myRequest = new Request(url);
var myOldList = document.getElementById('paramlist');
var myList = myOldList.cloneNode(false);
myOldList.parentNode.replaceChild(myList, myOldList);
fetch(myRequest)
.then(response => response.json())
.then(data => {
for (const param of data) {
var option = document.createElement('option');
option.value = param.name;
myList.appendChild(option);
}
})
.catch(console.error);
document.getElementById('id_param').disabled = false;
}
function keyUpEvent(e, objElem) {
switch (objElem.id) {
case 'id_param':
param = objElem.value;
category = document.getElementById('id_category').value;
if (e instanceof KeyboardEvent) {
// it is a keyboard event!
if (e.code == 'Enter') {
requestStationList(category, param);
} else if (e.code == 'Backspace')
this.value = '';
} else if (e instanceof Event) {
// one Element from selection is selected
requestStationList(category, param);
}
break;
default:
break;
}
}

View file

@ -1,61 +1,78 @@
body {
font-family: sans-serif;
height: 100%;
align-items: center;
}
.page {
align-items: center;
height: 100%;
width: 100%;
}
.header {
height = 30rem;
width: 90%;
height=30rem;
width: 38.9rem;
margin: 0rem;
background-color: blue;
color: white;
text-align: center;
border: 4px #eee solid;
min-width: 20rem;
max-width: 40rem;
padding: 0.5rem
}
.container {
display: block;
width: 100%;
height: 100%;
max-height: auto;
bottom: 0rem;
background-color: aquamarine;
}
.content {
position: relative;
border: 2px #eee solid;
width: 45%;
display: block;
width: 20rem;
min-width: 20rem;
float: left;
margin: 0rem;
height: 20rem;
height: calc(100% - 13rem);
max-height: 30rem;
}
.contentheader {
display: block;
background-color: blue;
color: white;
align-items: center;
margin: 0rem;
padding: 0.2rem;
border: 2px #eee solid;
height: 5rem;
width: 100%
}
.contentitems {
position: absolute;
overflow-y: scroll;
overflow-x: hidden;
width: 100%;
height: 100%;
display: block;
overflow-y: auto;
overflow-x: hidden;
top: 6rem;
width: 100%;
height: calc(100% - 20rem);
max-height: 30rem;
border: 2px #eee solid ;
}
.item {
display: flex;
border: 2px #eee solid;
margin: 0rem;
display: flex;
height: 2.4rem;
align-items: center;
}
.item:hover {
background-color: beige;
}
background-color: beige;
}
.itemicon {
height: 2.4rem;
@ -63,7 +80,9 @@ body {
}
.itemtext {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
ul {
@ -73,16 +92,23 @@ ul {
width: 100%;
display: contents;
}
li {
width: 95%;
padding: 0rem;
margin: 0rem;
}
h2 {
padding: 0rem;
margin: 0.5rem;
}
h3 {
border: 2px #eee solid;
text-align: center;
padding: 10px;
margin: 0rem;
padding: 0.5rem;
}
h4 {
@ -90,13 +116,16 @@ h4 {
padding-left: 1rem;
margin: auto
}
p {
padding-left: 1.1rem;
margin: auto;
font-size: 0.8rem;
}
img {
height: 100%;
width: 100%;
}
label {
padding-left: 1.1rem;
}
input

View file

@ -1,56 +1,72 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="../static/style.css">
<script type="text/javascript"
src="../static/script.js"></script> <title>YCast</title>
<link rel="stylesheet" href="/static/style.css">
<script type="text/javascript" src="/static/script.js"></script>
<title>YCast</title>
</head>
<body>
<div class="header">
<h2>Hallo YCast</h2>
</div>
<div class="content">
<div class="contentheader" onclick="stationsAddItem()">
<h3>Stations</h3>
<div class="page">
<div class="header">
<h2>YCast advanced</h2>
<div>
<label for="id_category">station-source:</label>
<select tabindex="1" id="id_category" name="category" oninput="onInputSelect(event, this)">
<option value="recently">recently</option>
<option value="voted">voted</option>
<option value="language">language</option>
<option value="country">country</option>
</select>
</div>
<div>
<label for="id_param">language or country:</label>
<input tabindex="2" list="paramlist" id="id_param" autocomplete=off disabled=true onclick="this.value=''" onfocus="this.value=''" onkeyup="keyUpEvent(event,this)">
<datalist id="paramlist">
</datalist>
</div>
</div>
<div class="content">
<div class="contentheader">
<h3 onclick="stations_request()">Stations</h3>
<label for="stationsearch">search:</label>
<input tabindex="3" type="search" id="stationsearch">
</div>
<div class="contentitems">
<ul id="stationList">
</ul>
</div>
</div>
<div class="content">
<div class="contentheader">
<h3>Bookmarks</h3>
<label for="idCategory">category:</label>
<input tabindex="10000" list="category" id="idCategory">
<datalist id="category">
<option value="Actual">
<option value="Pop">
<option value="Classics">
</datalist>
</div>
<div class="contentitems">
<ul id="bookmarkList">
<li class="item">
<div class="itemicon">
<img class="itemicon" src="http://www.klassikradio.de/_nuxt/icons/icon_64.a00w80w0000.png">
</div>
<div class="itemtext">
<h4>Radio</h4>
<p>ard,actuell</p>
</div>
</li>
</ul>
</div>
</div>
</div>
<div class="contentitems">
<ul id="stationList">
<li class="item">
<div class="itemicon">
<img src="http://www.klassikradio.de/_nuxt/icons/icon_64.a00w80w0000.png">
</div>
<div class="itemtext">
<h4>Radio</h4>
<p>ard,actuell</p>
</div>
</li>
<li class="item">
<div class="itemicon">
<img src="http://wgbh.org//apple-touch-icon.png">
</div>
<div class="itemtext">
<h4>Radio</h4>
<p>ard,actuell</p>
</div>
</li>
</ul>
</div>
</div>
<div class="content">
<div class="contentheader"><h3>Bookmarks</h3></div>
<ul>
<li class="item">
<div class="itemicon">
<img src="http://www.klassikradio.de/_nuxt/icons/icon_64.a00w80w0000.png">
</div>
<div class="itemtext">
<h4>Radio</h4>
<p>ard,actuell</p>
</div>
</li>
</ul>
</div>
</body>
</html>
</html>

View file

@ -67,6 +67,9 @@ class MyTestCase(unittest.TestCase):
assert len(result) == 3
def test_get_countries(self):
generic.init_base_dir('.ycast')
my_filter.init_filter_file()
result = radiobrowser.get_country_directories()
assert len(result) == 4
@ -79,8 +82,6 @@ class MyTestCase(unittest.TestCase):
assert result == 20
def test_jsonable_classes(self):
generic.init_base_dir('.ycast')
my_filter.init_filter_file()
stations = radiobrowser.get_stations_by_country('Germany')
station = stations[0]
text = station.to_vtuner()