From 5858745c1d9b8cfaba6f53b5bc5861394405670c Mon Sep 17 00:00:00 2001 From: Dominique Barton Date: Wed, 15 Apr 2020 13:31:04 +0200 Subject: [PATCH] FEATURE: Add unregister action --- mopidy_pummeluff/__init__.py | 12 +-- mopidy_pummeluff/registry.py | 11 +++ mopidy_pummeluff/web.py | 63 ++++++++-------- mopidy_pummeluff/webui/index.html | 1 + mopidy_pummeluff/webui/script.js | 121 ++++++++++++++---------------- mopidy_pummeluff/webui/style.css | 56 ++++++++------ 6 files changed, 143 insertions(+), 121 deletions(-) diff --git a/mopidy_pummeluff/__init__.py b/mopidy_pummeluff/__init__.py index 09ce374..5dd1932 100644 --- a/mopidy_pummeluff/__init__.py +++ b/mopidy_pummeluff/__init__.py @@ -7,7 +7,8 @@ import mopidy from .frontend import PummeluffFrontend -from .web import LatestHandler, RegistryHandler, RegisterHandler, ActionClassesHandler +from .web import LatestHandler, RegistryHandler, RegisterHandler, UnregisterHandler, \ + ActionClassesHandler def app_factory(config, core): # pylint: disable=unused-argument @@ -21,10 +22,11 @@ def app_factory(config, core): # pylint: disable=unused-argument :rtype: list ''' return [ - ('/latest/', LatestHandler, {'core': core}), - ('/registry/', RegistryHandler, {'core': core}), - ('/register/', RegisterHandler, {'core': core}), - ('/action-classes/', ActionClassesHandler, {'core': core}), + ('/latest/', LatestHandler), + ('/registry/', RegistryHandler), + ('/register/', RegisterHandler), + ('/unregister/', UnregisterHandler), + ('/action-classes/', ActionClassesHandler), ] diff --git a/mopidy_pummeluff/registry.py b/mopidy_pummeluff/registry.py index 8136666..9070e98 100644 --- a/mopidy_pummeluff/registry.py +++ b/mopidy_pummeluff/registry.py @@ -127,5 +127,16 @@ def register(self, action_class, uid, alias=None, parameter=None): return action + def unregister(self, uid): + ''' + Unregister a tag from the registry. + + :param str uid: The UID + ''' + LOGGER.info('Unregistering tag %s', uid) + + del self[uid] + self.write() + REGISTRY = RegistryDict() diff --git a/mopidy_pummeluff/web.py b/mopidy_pummeluff/web.py index ef81574..e3c47d9 100644 --- a/mopidy_pummeluff/web.py +++ b/mopidy_pummeluff/web.py @@ -6,6 +6,7 @@ 'LatestHandler', 'RegistryHandler', 'RegisterHandler', + 'UnregisterHandler', 'ActionClassesHandler', ) @@ -26,14 +27,6 @@ class LatestHandler(RequestHandler): # pylint: disable=abstract-method Request handler which returns the latest scanned tag. ''' - def initialize(self, core): # pylint: disable=arguments-differ - ''' - Initialize request handler with Mopidy core. - - :param mopidy.core.Core mopidy_core: The mopidy core instance - ''' - self.core = core # pylint: disable=attribute-defined-outside-init - def get(self, *args, **kwargs): # pylint: disable=unused-argument ''' Handle GET request. @@ -65,14 +58,6 @@ class RegistryHandler(RequestHandler): # pylint: disable=abstract-method Request handler which returns all registered tags. ''' - def initialize(self, core): # pylint: disable=arguments-differ - ''' - Initialize request handler with Mopidy core. - - :param mopidy.core.Core mopidy_core: The mopidy core instance - ''' - self.core = core # pylint: disable=attribute-defined-outside-init - def get(self, *args, **kwargs): # pylint: disable=unused-argument ''' Handle GET request. @@ -97,14 +82,6 @@ class RegisterHandler(RequestHandler): # pylint: disable=abstract-method Request handler which registers an RFID tag in the registry. ''' - def initialize(self, core): # pylint: disable=arguments-differ - ''' - Initialize request handler with Mopidy core. - - :param mopidy.core.Core mopidy_core: The mopidy core instance - ''' - self.core = core # pylint: disable=attribute-defined-outside-init - def post(self, *args, **kwargs): # pylint: disable=unused-argument ''' Handle POST request. @@ -141,18 +118,44 @@ def put(self, *args, **kwargs): # pylint: disable=unused-argument self.post() -class ActionClassesHandler(RequestHandler): # pylint: disable=abstract-method +class UnregisterHandler(RequestHandler): # pylint: disable=abstract-method ''' - Request handler which returns all action classes. + Request handler which unregisters an RFID tag from the registry. ''' - def initialize(self, core): # pylint: disable=arguments-differ + def post(self, *args, **kwargs): # pylint: disable=unused-argument + ''' + Handle POST request. ''' - Initialize request handler with Mopidy core. + try: + REGISTRY.unregister(uid=self.get_argument('uid')) + + data = { + 'success': True, + 'message': 'Tag successfully unregistered', + } + + except ValueError as ex: + self.set_status(400) + data = { + 'success': False, + 'message': str(ex) + } + + self.set_header('Content-type', 'application/json') + self.write(dumps(data)) - :param mopidy.core.Core mopidy_core: The mopidy core instance + def put(self, *args, **kwargs): # pylint: disable=unused-argument + ''' + Handle PUT request. ''' - self.core = core # pylint: disable=attribute-defined-outside-init + self.post() + + +class ActionClassesHandler(RequestHandler): # pylint: disable=abstract-method + ''' + Request handler which returns all action classes. + ''' def get(self, *args, **kwargs): # pylint: disable=unused-argument ''' diff --git a/mopidy_pummeluff/webui/index.html b/mopidy_pummeluff/webui/index.html index 1f45238..a8f75af 100644 --- a/mopidy_pummeluff/webui/index.html +++ b/mopidy_pummeluff/webui/index.html @@ -27,6 +27,7 @@

Register New Tag

+ diff --git a/mopidy_pummeluff/webui/script.js b/mopidy_pummeluff/webui/script.js index ea05d42..14527da 100644 --- a/mopidy_pummeluff/webui/script.js +++ b/mopidy_pummeluff/webui/script.js @@ -8,15 +8,13 @@ class API { * Send AJAX request to REST API endpoint. */ - request(endpoint, data, callback) - { + request = (endpoint, data, callback) => { let init = {} if(data) init = { method: 'POST', body: data } fetch(endpoint, init) - .then(function(response) - { + .then((response) => { return response.json() }) .then(callback) @@ -27,24 +25,21 @@ class API { * Refresh the registry. */ - refreshRegistry() - { - let callback = function(response) - { + refreshRegistry = () => { + let callback = (response) => { let tagsContainer = document.getElementById('tags') - while(tagsContainer.firstChild) + while(tagsContainer.firstChild) { tagsContainer.removeChild(tagsContainer.firstChild) + } - for(let tag of response.tags) - { + for(let tag of response.tags) { let tagElement = document.createElement('div') tagElement.setAttribute('class', 'tag') let args = new Array('alias', 'uid', 'action_class', 'parameter') - for(let arg of args) - { + for(let arg of args) { let spanElement = document.createElement('span') - let value = tag[arg] ? tag[arg] : '-' + let value = tag[arg] ? tag[arg] : '-' spanElement.setAttribute('class', arg.replace('_', '-')) spanElement.innerHTML = value tagElement.appendChild(spanElement) @@ -61,16 +56,13 @@ class API { * Refresh the tags. */ - refreshActionClasses() - { - let callback = function(response) - { + refreshActionClasses = () => { + let callback = (response) => { let select = document.getElementById('action-class'); while(select.firstChild) select.removeChild(select.firstChild) - for(let action_class in response.action_classes) - { + for(let action_class in response.action_classes) { let option = document.createElement('option') option.setAttribute('value', action_class) option.innerHTML = action_class + ' (' + response.action_classes[action_class] + ')' @@ -81,45 +73,52 @@ class API { this.request('/pummeluff/action-classes/', false, callback) } + /* + * Reset the form. + */ + + formCallback = (response) => { + if(response.success) { + this.refreshRegistry() + document.getElementById('uid').value = '' + document.getElementById('alias').value = '' + document.getElementById('parameter').value = '' + document.getElementById('action-class').selectIndex = 0 + } else { + window.alert(response.message) + } + } + /* * Register a new tag. */ - register() - { + register = () => { let form = document.getElementById('register-form') let data = new FormData(form) + this.request('/pummeluff/register/', data, this.formCallback) + } - let callback = function(response) - { - if(response.success) - { - api.refreshRegistry() - document.getElementById('uid').value = '' - document.getElementById('alias').value = '' - document.getElementById('parameter').value = '' - document.getElementById('action-class').selectIndex = 0 - } - else - { - window.alert(response.message) - } - } + /* + * Unregister an existing tag. + */ - this.request('/pummeluff/register/', data, callback) + unregister = () => { + let form = document.getElementById('register-form') + let data = new FormData(form) + this.request('/pummeluff/unregister/', data, this.formCallback) } /* * Get latest scanned tag. */ - getLatestTag() - { + getLatestTag = () => { let latest_tag = undefined - let uid_field = document.getElementById('uid') - let alias_field = document.getElementById('alias') - let parameter_field = document.getElementById('parameter') + let uid_field = document.getElementById('uid') + let alias_field = document.getElementById('alias') + let parameter_field = document.getElementById('parameter') let action_class_select = document.getElementById('action-class') uid_field.value = '' @@ -127,15 +126,12 @@ class API { parameter_field.value = '' action_class_select.selectIndex = 0 - let link = document.getElementById('read-rfid-tag') + let link = document.getElementById('read-rfid-tag') link.classList.add('reading') - let do_request = function() - { - let callback = function(response) - { - if(latest_tag && response.success && JSON.stringify(response) != JSON.stringify(latest_tag)) - { + let do_request = () => { + let callback = (response) => { + if(latest_tag && response.success && JSON.stringify(response) != JSON.stringify(latest_tag)) { uid_field.value = response.uid if(response.alias) @@ -148,9 +144,7 @@ class API { action_class_select.value = response.action_class link.classList.remove('reading') - } - else - { + } else { setTimeout(() => do_request(), 1000) } @@ -167,27 +161,28 @@ class API { api = new API() -api.refreshRegistry(); -api.refreshActionClasses(); +api.refreshRegistry() +api.refreshActionClasses() -document.addEventListener('click', function(event) -{ +document.addEventListener('click', (event) => { let target = event.target let div = target.closest('div') - if(div && div.classList.contains('tag')) - { - for(let child of div.children) - { + if(div && div.classList.contains('tag')) { + for(let child of div.children) { document.getElementById(child.className).value = child.innerHTML.replace(/^-$/, '') } } }) -document.getElementById('register-form').onsubmit = function() -{ +document.getElementById('register-form').onsubmit = () => { api.register() return false; } +document.getElementById('unregister-button').onclick = () => { + api.unregister() + return false +} + document.getElementById('read-rfid-tag').onclick = () => api.getLatestTag() diff --git a/mopidy_pummeluff/webui/style.css b/mopidy_pummeluff/webui/style.css index dc39d7e..15488dc 100644 --- a/mopidy_pummeluff/webui/style.css +++ b/mopidy_pummeluff/webui/style.css @@ -18,11 +18,11 @@ body body { - min-height : 100vh; + background-color: #222; + color : #eee; font-family : sans-serif; font-size : 14px; - color : #eee; - background-color: #222; + min-height : 100vh; } /* @@ -80,15 +80,15 @@ input, select, button { - width : 100%; + background-color: #222; border : 0; - padding : 10px; - border-width : 0 0 2px 0; - border-style : solid; border-color : #333; - background-color: #222; + border-style : solid; + border-width : 0 0 2px 0; color : #eee; outline : none; + padding : 10px; + width : 100%; } select @@ -103,26 +103,36 @@ input::placeholder input:focus { - border-bottom-color: #fa0; + border-bottom-color: #8ff; } button +{ + color : #eee; + cursor : pointer; + font-weight: bold; + margin-top : 10px; +} + +button#register-button { background-color: #4a4; - color : #eee; - font-weight : bold; - margin-top : 10px; +} + +button#unregister-button +{ + background-color: #a20; } #read-rfid-tag { - text-decoration: none; - color : #fa0; + color : #8ff; font-size : 11px; + text-decoration: none; } #read-rfid-tag.reading { - animation: blink 0.5s cubic-bezier(.5, 0, 1, 1) infinite alternate; + animation: blink 0.5s cubic-bezier(.5, 0, 1, 1) infinite alternate; } @keyframes blink { to { opacity: 0.25; } } @@ -133,15 +143,15 @@ button div.tag { - display : inline-block; - cursor : pointer; background-color: #eee; - color : #222; box-shadow : 1px 1px 5px #000; - padding : 10px; + color : #222; + cursor : pointer; + display : inline-block; + line-height : 20px; margin : 0 20px 20px 0; + padding : 10px; width : 400px; - line-height : 20px; } div.tag span.uid, @@ -153,14 +163,14 @@ div.tag span.parameter div.tag span.action-class { - display : inline-block; background-color: #888; + border-radius : 10px; color : #eee; + display : inline-block; font-size : 11px; line-height : 11px; - padding : 3px 5px; margin-left : 5px; - border-radius : 10px; + padding : 3px 5px; } div.tag span.alias,