Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions music_spa/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-

from . import controllers
from . import models
42 changes: 42 additions & 0 deletions music_spa/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# -*- coding: utf-8 -*-
{
'name': "musicSPA",

'summary': """
Short (1 phrase/line) summary of the module's purpose, used as
subtitle on modules listing or apps.openerp.com""",

'description': """
Long description of module's purpose
""",

'author': "My Company",
'website': "https://www.yourcompany.com",

# Categories can be used to filter modules in modules listing
# Check https://github.com/odoo/odoo/blob/16.0/odoo/addons/base/data/ir_module_category_data.xml
# for the full list
'category': 'Uncategorized',
'version': '0.1',

# any module necessary for this one to work correctly
'depends': ['base'],

# always loaded
'data': [
'security/ir.model.access.csv',
'views/views.xml',
'views/templates.xml',
],
# 'assets':{
# 'web.assets_backend': [
# 'music_spa/static/app.js',
# ]
# },
# only loaded in demonstration mode
'demo': [
'demo/demo.xml',
],
'installable' : True,
'application' :True,
}
Binary file added music_spa/__pycache__/__init__.cpython-38.pyc
Binary file not shown.
3 changes: 3 additions & 0 deletions music_spa/controllers/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-

from . import controllers
Binary file not shown.
Binary file not shown.
37 changes: 37 additions & 0 deletions music_spa/controllers/controllers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# -*- coding: utf-8 -*-
import json
from odoo import http
from odoo.http import Response
from odoo.modules.module import get_module_resource

class MusicSpa(http.Controller):
@http.route('/music', auth='public')
def index(self, **kw):
return http.request.render('music_spa.music_template')

@http.route('/music/search/', type="http", auth="public", methods=['GET'])
def search(self, **kw):
searchSong = kw.get('song_name')

print(searchSong)
songlist = http.request.env['music.player'].search_read([('name','ilike',searchSong)])
print("----------------")
print(songlist)
songs = [self._get_song_data(song) for song in songlist]
print(songs)
if not songs:
songs = "Song not found"

return Response(json.dumps({'result' : songs}), content_type="application/json")

def _get_song_data(self, song):
fields_list = ['id', 'name', 'filename', 'url']
song_values = dict((i, song[i]) for i in fields_list)
return song_values

@http.route('/music/<model("music.player"):music>', type="http" ,auth='public')
def load(self, music, **kw):
music_file_path = get_module_resource('music_spa', 'static/songs', music.filename)
#rb - read binanry
file = open(music_file_path, 'rb').read()
return file
34 changes: 34 additions & 0 deletions music_spa/demo/demo.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<odoo>
<record model="music.player" id="song1">
<field name="name">Akon-Be-With-You</field>
<field name="filename">Akon-Be-With-You.mp3</field>
</record>
<record model="music.player" id="song2">
<field name="name">Akon-Beautiful</field>
<field name="filename">Akon-Beautiful.mp3</field>
</record>
<record model="music.player" id="song3">
<field name="name">Akon-Birthmark</field>
<field name="filename">Akon-Birthmark.mp3</field>
</record>
<record model="music.player" id="song4">
<field name="name">Akon-Keep-You-Much-Longer</field>
<field name="filename">Akon-Keep-You-Much-Longer.mp3</field>
</record>
<record model="music.player" id="song5">
<field name="name">Akon-Sunny-Day</field>
<field name="filename">Akon-Sunny-Day.mp3</field>
</record>
<record model="music.player" id="song6">
<field name="name">Temp-song-1</field>
<field name="filename">Temp-song-1.mp3</field>
</record>
<record model="music.player" id="song7">
<field name="name">Temp-song-2</field>
<field name="filename">Temp-song-2.mp3</field>
</record>
<record model="music.player" id="song8">
<field name="name">Temp-song-3</field>
<field name="filename">Temp-song-3.mp3</field>
</record>
</odoo>
3 changes: 3 additions & 0 deletions music_spa/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-

from . import music_player
Binary file added music_spa/models/__pycache__/__init__.cpython-38.pyc
Binary file not shown.
Binary file added music_spa/models/__pycache__/models.cpython-38.pyc
Binary file not shown.
Binary file not shown.
Binary file added music_spa/models/__pycache__/player.cpython-38.pyc
Binary file not shown.
26 changes: 26 additions & 0 deletions music_spa/models/music_player.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# -*- coding: utf-8 -*-

from odoo import models, fields, api


class MusicPlayer(models.Model):
_name = 'music.player'
_description = 'music_spa.music_spa'

name = fields.Char("Song Name")
filename = fields.Char("File Name")
url = fields.Char(compute = "_compute_url")

@api.depends('filename')
def _compute_url(self):
for record in self:
record.url = record.get_base_url() + "/music/" + str(record.id)

# value = fields.Integer()
# value2 = fields.Float(compute="_value_pc", store=True)
# description = fields.Text()
#
# @api.depends('value')
# def _value_pc(self):
# for record in self:
# record.value2 = float(record.value) / 100
2 changes: 2 additions & 0 deletions music_spa/security/ir.model.access.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
music_spa.access_music_player,access_music_player,music_spa.model_music_player,,1,1,1,1
216 changes: 216 additions & 0 deletions music_spa/static/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@

const { Component, xml, mount, useState,useEffect, setup } = owl;
let audio = '';

class Player extends Component {
static template = xml`
<div style="Position:absolute;bottom:10px;width:100%;text-align:center">
<h2 id="song-title">Song Title</h2>
<div id="player-controls">
<button id="pause-button" t-on-click="pauseThisSong">Pause</button>
<button id="play_btn" t-on-click="playThisSong">Play</button>
<button id="stop-button" t-on-click="stopThisSong">Stop</button>
</div>
</div>`;
playThisSong() {
if (!audio) {
return;
}
audio.play();
}
pauseThisSong() {
if (!audio) {
return;
}
audio.pause();
}
stopThisSong() {
if (!audio) {
return;
}
audio.pause();
audio.currentTime = 0;
}
}

class SongItems extends Component {
static template = xml`
<div style="float:right;margin-right:2%">
<table>
<t t-if="props.songitems[0]">
<h1 style="text-align:center">Playlist</h1>
<hr/>
<t t-foreach="props.songitems" t-as="song" t-key="song.id">
<tr>
<td>
<div>
<p id="song_name"><t t-out="song.name"/></p>
<button t-on-click="removeSongFromList" id="listadded" t-att-value="song.url">Remove</button>
<button t-att-value="song.url" t-on-click="playThisSong">Play song</button>
</div>
</td>
</tr>
</t>
</t>
</table>
</div>
`;

removeSongFromList(ev) {
const selectedSongUrl = ev.target.getAttribute('value');
const selectedIndex = this.props.songitems.findIndex(song => song.url === selectedSongUrl);
if (selectedIndex !== -1) {
this.props.songitems.splice(selectedIndex, 1);
}
}

playThisSong(ev) {

const selectedSongUrl = ev.target.getAttribute('value');
const selectedSong = this.props.songitems.find(song => song.url === selectedSongUrl);
document.getElementById('song-title').textContent = selectedSong.name;
audio = new Audio(selectedSongUrl);
audio.pause();
audio.currentTime = 0;
audio.play();
}

static props = ['songitems']
}

class PlayList extends Component {
static template = xml`
<div id="MusicList">
<SongItems songitems="props.playlist"/>
</div>
`;

static props = ['playlist'];
static components = { SongItems };
}

class MusicData extends Component {
static template = xml`
<div id="MusicList" style="width:40%;float:left;margin-left:2%;">
<table>

<t t-if="props.musicdata[0]">

<t t-if="props.musicdata[0] !== 'Song not Found'">
<h1 style="text-align:center">Tranding Songs</h1>
<hr/>
<t t-foreach="props.musicdata[0]" t-as="song" t-key="song.id">

<p><t t-out="song.name"/></p>
<button t-att-value="song.url" t-on-click="addSongToPlaylist">Add to playlist</button>
<button t-att-value="song.url" t-on-click="playSong">Play song</button>

</t>
</t>


</t>
</table>
</div>
`;


addSongToPlaylist(ev) {
let musicInfo = this.props.musicdata[0];
console.log(musicInfo)
const selectedSongUrl = ev.target.getAttribute('value');
const selectedSong = musicInfo.find(song => song.url === selectedSongUrl);
this.props.updateAddToPlayList(selectedSong);
}

playSong(ev) {
let musicInfo = this.props.musicdata[0];
const selectedSongUrl = ev.target.getAttribute('value');
const selectedSong = musicInfo.find(song => song.url === selectedSongUrl);
document.getElementById('song-title').textContent = selectedSong.name;
audio = new Audio(selectedSongUrl);
audio.play();
}

static props = ['musicdata', 'updateAddToPlayList'];
}

class Search extends Component {
static template = xml`
<div>
<div style="border:1px,solid,black;text-align:center">
<input type="text" id="searchSong" placeholder="Search a music" value="Akon"/>
<button t-on-click="getMusic" id="SearchButton">Search</button>
</div>
<MusicData musicdata="searchData" updateAddToPlayList="props.updateAddToPlayList"/>
</div>
`;
setup() {
this.searchData = useState([]);

}

async getMusic() {
const findSong = document.getElementById('searchSong').value;
const response = await fetch(`/music/search?song_name=${findSong}`);
const {result : newData}= await response.json();
this.searchData.pop();
this.searchData.push(newData);
}



static components = { MusicData }

static props = ['updateAddToPlayList'];
}

class Root extends Component {

static template = xml `
<style>
body{
color:white;
background:black;
}
button{
margin:10px;
padding:10px;
font-size: 15px;
border-radius:5px;
background-color: #B0EDED;
}
input{
margin:15px;
padding:10px;
font-size: 15px;
}
p{
padding:2px;
font-family:Calibri;
font-size:20px;
}
</style>
<div id="Container" style="position:relative;height:100%">
<div>
<Search updateAddToPlayList="this.updateAddToPlayList"/>
</div>
<PlayList playlist="addToPlaylist"/>
<Player/>
</div>`;

setup(){
this.addToPlaylist = useState([]);
}

updateAddToPlayList = (newData) => {
this.addToPlaylist.push(newData);
}

static components = { Search, PlayList, Player };
}

window.onload = function() {
mount(Root, document.body);
};

Loading