serve itunes library directly and import js frontend
This commit is contained in:
parent
56d92d1d3d
commit
866174e47e
4 changed files with 281 additions and 19 deletions
|
@ -155,6 +155,10 @@ class Server(Resource):
|
|||
return f
|
||||
if request.path == '/api/':
|
||||
return self
|
||||
if request.path == '/library.xml':
|
||||
f = File(self.backend.xml)
|
||||
f.isLeaf = True
|
||||
return f
|
||||
if request.path.startswith('/track/'):
|
||||
track_id = request.path.split('/')[-1].split('.')[0]
|
||||
track = self.backend.library['Tracks'].get(track_id)
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<title>0xcd</title>
|
||||
<link rel="shortcut icon" type="image/png" href="/png/icon16.png"/>
|
||||
<script type="text/javascript" src="/oxjs/build/Ox.js"></script>
|
||||
<script type="text/javascript" src="/js/site.js"></script>
|
||||
<script type="text/javascript" src="/js/index.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
|
|
276
oxcd/static/js/index.js
Normal file
276
oxcd/static/js/index.js
Normal file
|
@ -0,0 +1,276 @@
|
|||
'use strict';
|
||||
|
||||
Ox.load('UI', function() {
|
||||
var app = {
|
||||
$ui: {},
|
||||
data: {},
|
||||
site: {
|
||||
columns: [
|
||||
{
|
||||
format: function(value) {
|
||||
return value ? $('<img>').addClass('symbol').attr({
|
||||
src: Ox.UI.getImageURL('symbolMute')
|
||||
}) : '';
|
||||
},
|
||||
id: 'playing',
|
||||
operator: '-',
|
||||
removable: false,
|
||||
resizable: false,
|
||||
title: 'Playing',
|
||||
titleImage: 'mute',
|
||||
visible: true,
|
||||
width: 16
|
||||
},
|
||||
{
|
||||
format: function(value) {
|
||||
return value ? '' : $('<img>').addClass('symbol').attr({
|
||||
src: Ox.UI.getImageURL('symbolCheck')
|
||||
});
|
||||
},
|
||||
id: 'disabled',
|
||||
operator: '+',
|
||||
removable: false,
|
||||
resizable: false,
|
||||
title: 'Enabled',
|
||||
titleImage: 'check',
|
||||
visible: true,
|
||||
width: 16
|
||||
},
|
||||
{
|
||||
format: function(value) {
|
||||
return app.utils.formatTitle(value);
|
||||
},
|
||||
id: 'name',
|
||||
operator: '+',
|
||||
removable: false,
|
||||
title: 'Name',
|
||||
visible: true,
|
||||
width: 192
|
||||
},
|
||||
{
|
||||
id: 'artist',
|
||||
operator: '+',
|
||||
sort: function(value, data) {
|
||||
return data.albumArtist ? data.sortAlbumArtist || data.albumArtist
|
||||
: data.compilation ? ''
|
||||
: data.sortArtist || data.artist || '';
|
||||
},
|
||||
title: 'Artist',
|
||||
visible: true,
|
||||
width: 192
|
||||
},
|
||||
{
|
||||
format: function(value) {
|
||||
return app.utils.formatTitle(value);
|
||||
},
|
||||
id: 'album',
|
||||
operator: '+',
|
||||
title: 'Album',
|
||||
visible: true,
|
||||
width: 192
|
||||
},
|
||||
{
|
||||
align: 'right',
|
||||
id: 'year',
|
||||
operator: '+',
|
||||
title: 'Year',
|
||||
visible: true,
|
||||
width: 64
|
||||
},
|
||||
{
|
||||
align: 'right',
|
||||
format: function(value) {
|
||||
return app.utils.formatTime(value);
|
||||
},
|
||||
id: 'totalTime',
|
||||
operator: '-',
|
||||
title: 'Time',
|
||||
visible: true,
|
||||
width: 64
|
||||
},
|
||||
{
|
||||
align: 'right',
|
||||
format: function(value) {
|
||||
return Ox.formatValue(value, 'B');
|
||||
},
|
||||
id: 'size',
|
||||
operator: '-',
|
||||
title: 'Size',
|
||||
visible: true,
|
||||
width: 64,
|
||||
}
|
||||
]
|
||||
},
|
||||
user: {
|
||||
library: '/library.xml',
|
||||
sort: [
|
||||
{key: 'artist', operator: '+'},
|
||||
{key: 'year', operator: '+'},
|
||||
{key: 'album', operator: '+'},
|
||||
{key: 'discNumber', operator: '+'},
|
||||
{key: 'trackNumber', operator: '+'}
|
||||
]
|
||||
},
|
||||
ui: {},
|
||||
utils: {}
|
||||
};
|
||||
app.load = function() {
|
||||
app.$ui.appPanel = app.ui.appPanel().appendTo(Ox.$body);
|
||||
app.utils.parseLibrary(function(data) {
|
||||
app.user.music = data;
|
||||
app.loaded = true;
|
||||
app.$ui.appPanel.replaceElement(1, app.$ui.list = app.ui.list());
|
||||
});
|
||||
}
|
||||
app.ui.appPanel = function() {
|
||||
var $element = Ox.SplitPanel({
|
||||
elements: [
|
||||
{element: app.$ui.toolbar = app.ui.toolbar(), size: 24},
|
||||
{element: app.$ui.list = app.ui.list()},
|
||||
{element: app.$ui.statusbar = app.ui.statusbar(), size: 24}
|
||||
],
|
||||
orientation: 'vertical'
|
||||
});
|
||||
return $element;
|
||||
};
|
||||
app.ui.toolbar = function() {
|
||||
var $element = Ox.Bar({size: 24});
|
||||
return $element;
|
||||
};
|
||||
app.ui.list = function() {
|
||||
var $element = !app.loaded ? Ox.Element() : Ox.TableList({
|
||||
columns: app.site.columns,
|
||||
columnsRemovable: true,
|
||||
columnsVisible: true,
|
||||
items: app.user.music.tracks,
|
||||
keys: ['albumArtist', 'compilation', 'sortAlbumArtist', 'sortArtist'],
|
||||
/*
|
||||
query: {
|
||||
conditions: [
|
||||
{key: 'artist', operator: '==', value: 'Mary Lou Lord'},
|
||||
{key: 'artist', operator: '==', value: 'Liz Phair'}
|
||||
],
|
||||
operator: '|'
|
||||
},
|
||||
*/
|
||||
scrollbarVisible: true,
|
||||
sort: app.user.sort,
|
||||
sums: ['size', 'totalTime'],
|
||||
unique: 'trackID'
|
||||
})
|
||||
.bindEvent({
|
||||
init: function(data) {
|
||||
app.$ui.statusbar.update(data);
|
||||
},
|
||||
open: function(data) {
|
||||
app.utils.play(data.ids[0]);
|
||||
},
|
||||
openpreview: function(data) {
|
||||
$element.closePreview();
|
||||
app.utils.play(data.ids[0]);
|
||||
},
|
||||
select: function(data) {
|
||||
app.$ui.statusbar.update(data);
|
||||
}
|
||||
});
|
||||
return $element;
|
||||
};
|
||||
app.ui.statusbar = function() {
|
||||
var $status = $('<div>').attr({id: 'status'}),
|
||||
$element = Ox.Bar({size: 24})
|
||||
.append($status);
|
||||
$element.update = function(data) {
|
||||
var items;
|
||||
if (data) {
|
||||
if (data.items) {
|
||||
app.data.status = data;
|
||||
} else if (data.ids && data.ids.length > 1) {
|
||||
var items = app.user.music.tracks.filter(function(track) {
|
||||
return Ox.contains(data.ids, track.trackID);
|
||||
});
|
||||
data.selected = data.ids.length;
|
||||
['size', 'totalTime'].forEach(function(key) {
|
||||
data[key] = items.reduce(function(p, c) {
|
||||
return p + c[key];
|
||||
}, 0);
|
||||
});
|
||||
}
|
||||
}
|
||||
$status.html(
|
||||
data ? (data.selected ? data.selected + ' of ' : '')
|
||||
+ Ox.formatNumber(app.data.status.items) + ' item'
|
||||
+ (app.data.status.items == 1 ? '' : 's') + ', '
|
||||
+ app.utils.formatTime(data.totalTime || app.data.status.totalTime) + ' total time, '
|
||||
+ Ox.formatValue(data.size || app.data.status.size, 'B')
|
||||
: 'Loading...'
|
||||
);
|
||||
};
|
||||
$element.update();
|
||||
return $element;
|
||||
};
|
||||
app.utils.formatTime = function(duration) {
|
||||
return Ox.formatDuration(duration / 1000).replace(/^00:/, '').replace(/^0/, '');
|
||||
};
|
||||
app.utils.formatTitle = function(title) {
|
||||
return title.replace(/\[(.+)\]$/, '<span class="OxLight">($1)</span>');
|
||||
};
|
||||
app.utils.parseKey = function(key) {
|
||||
return key[0].toLowerCase() + key.substr(1).replace(/ /g, '');
|
||||
};
|
||||
app.utils.parseLibrary = function(callback) {
|
||||
Ox.get(app.user.library, function(xml) {
|
||||
var data = {playlists: [], tracks: []},
|
||||
library = app.utils.parseXML($(xml).children()[0]);
|
||||
Ox.forEach(library.tracks, function(track) {
|
||||
if (track.kind == 'MPEG audio file' && !track.podcast) {
|
||||
app.site.columns.map(function(column) {
|
||||
return column.id;
|
||||
}).forEach(function(key) {
|
||||
if (!track[key]) {
|
||||
track[key] = '';
|
||||
}
|
||||
})
|
||||
data.tracks.push(track);
|
||||
}
|
||||
});
|
||||
callback(data);
|
||||
});
|
||||
};
|
||||
app.utils.parseXML = function(xml) {
|
||||
var type = xml.nodeName.toLowerCase(), value;
|
||||
if (type == 'array') {
|
||||
value = [];
|
||||
$(xml).children().each(function(k, v) {
|
||||
value.push(app.utils.parseXML(v));
|
||||
});
|
||||
} else if (type == 'data') {
|
||||
value = xml.innerHTML.replace(/(\n|\t)/g, '');
|
||||
} else if (type == 'date') {
|
||||
value = xml.innerHTML;
|
||||
} else if (type == 'dict') {
|
||||
value = {};
|
||||
$(xml).children('key').each(function(k, v) {
|
||||
value[app.utils.parseKey(v.innerHTML)] = app.utils.parseXML($(v).next()[0]);
|
||||
});
|
||||
} else if (type == 'false') {
|
||||
value = false;
|
||||
} else if (type == 'integer') {
|
||||
value = parseInt(xml.innerHTML);
|
||||
} else if (type == 'string') {
|
||||
value = xml.innerHTML;
|
||||
} else if (type == 'true') {
|
||||
value = true;
|
||||
}
|
||||
return value;
|
||||
};
|
||||
app.utils.play = function(id) {
|
||||
if (app.user.playing) {
|
||||
app.$ui.list.value(app.user.playing, 'playing', false);
|
||||
}
|
||||
if (id != app.user.playing) {
|
||||
app.user.playing = id;
|
||||
app.$ui.list.value(app.user.playing, 'playing', true);
|
||||
}
|
||||
};
|
||||
app.load();
|
||||
});
|
|
@ -1,18 +0,0 @@
|
|||
Ox.load('UI', function() {
|
||||
window.oxcd = Ox.App({
|
||||
name: 'oxcd',
|
||||
url: '/api/'
|
||||
}).bindEvent({
|
||||
load: function(data) {
|
||||
oxcd.api.library(function(result) {
|
||||
var items = Ox.values(result.data.Tracks),
|
||||
element = Ox.Element();
|
||||
items.forEach(function(item) {
|
||||
element.append($('<div>').html('<a href="/track/'+item['Track ID']+'.mp3">'+item['Track ID'] + ': '+item.Name+'</a>'))
|
||||
console.log('<a href="/track/'+item['Track ID']+'.mp3">'+item['Track ID'] + ':'+item.Name+'</a>');
|
||||
});
|
||||
Ox.UI.$body.append(element);
|
||||
})
|
||||
}
|
||||
});
|
||||
});
|
Loading…
Reference in a new issue