Skip to content

Commit

Permalink
Merge branch 'release/3.3.1'
Browse files Browse the repository at this point in the history
* release/3.3.1:
  preparing release 3.3.1
  Bump version: 3.3.0 → 3.3.1
  minor typo in documentation
  Added menu entries support for the web interface
  Clarify approve_all flag location
  fixing test for windows.
  • Loading branch information
javipalanca committed Sep 18, 2023
2 parents 9228ae3 + 2962da8 commit f483278
Show file tree
Hide file tree
Showing 10 changed files with 93 additions and 13 deletions.
6 changes: 6 additions & 0 deletions HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@
History
=======

3.3.1 (2023-09-18)
------------------

* Added menu entries support for the web interface.
* Minor typos in documentation.

3.3.0 (2023-06-13)
------------------

Expand Down
2 changes: 1 addition & 1 deletion docs/presence.rst
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ There are four handlers that you can override to manage these kind of messages:

.. note:: In the previous example you can see also how to approve a subscription request by using the ``approve`` method.

.. tip:: If you want to automatically approve all subscription requests you can set the ``approve_all`` flag to ``True``.
.. tip:: If you want to automatically approve all subscription requests you can set the ``PresenceManager.approve_all`` flag to ``True``.


Example
Expand Down
16 changes: 15 additions & 1 deletion docs/web.rst
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ In this example there are some elements that must be explained:

Next we are going to explain a little more about the controller, the path and the template.

.. note:: Please, do not use the ``/spade`` path o avoid conflicts with the default agent pages (unless you want to modify them).
.. note:: Please, do not use the ``/spade`` path to avoid conflicts with the default agent pages (unless you want to modify them).

Controller
----------
Expand Down Expand Up @@ -199,3 +199,17 @@ A simple example of template would be:
</html>

.. note:: Note that the ``agent`` variable is always available in your templates to help you to access your internal data.


Menu entries
------------

You can also add new entries to the menu bar of the agent's web interface. To do so, you can use the ``add_menu_entry`` method.
This method receives the name of the entry, the path to which it will redirect and the icon that will be shown in the menu bar.
The icon is a string from the Font Awesome collection (http://fontawesome.io/icons/).

For example, to add a new entry to the menu, you can do the following::

agent.web.add_menu_entry("My entry", "/my_entry", "fa fa-user")


2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[bumpversion]
current_version = 3.3.0
current_version = 3.3.1
commit = True
tag = False

Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def parse_requirements(filename):

setup(
name='spade',
version='3.3.0',
version='3.3.1',
description="Smart Python Agent Development Environment",
long_description=readme + '\n\n' + history,
author="Javi Palanca",
Expand Down
2 changes: 1 addition & 1 deletion spade/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

__author__ = """Javi Palanca"""
__email__ = "jpalanca@gmail.com"
__version__ = "3.3.0"
__version__ = "3.3.1"

__all__ = ["agent", "behaviour", "message", "template"]

Expand Down
17 changes: 15 additions & 2 deletions spade/templates/internal_tpl_base.html
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,20 @@ <h4>
<!-- Sidebar Menu -->
<ul class="sidebar-menu" data-widget="tree">
<!-- Optionally, you can add icons to the links -->
<li class="active"><a href="/spade"><i class="fa fa-dashboard"></i> <span>Dashboard</span></a></li>
{% if active == "/spade" %}
<li class="active">
{% else %}
<li>
{% endif %}
<a href="/spade"><i class="fa fa-id-card"></i> <span>Dashboard</span></a></li>
{% for name, entry in menu.items() %}
{% if active == entry.0 %}
<li class="active">
{% else %}
<li>
{% endif %}
<a href="{{ entry.0 }}"><i class="{{ entry.1 }}"></i> <span>{{ name }}</span></a></li>
{% endfor %}
</ul>
<!-- /.sidebar-menu -->
</section>
Expand Down Expand Up @@ -289,7 +302,7 @@ <h3 class="box-title">Agent Friends</h3>

<footer class="main-footer">
<div class="pull-right hidden-xs">
<b>Version</b> 3.3.0
<b>Version</b> 3.3.1
</div>
<strong>Copyright © {% now 'local', '%Y' %} <a href="http://github.com/javipalanca/spade">SPADE</a>.</strong>
</footer>
Expand Down
20 changes: 19 additions & 1 deletion spade/web.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ def __init__(self, agent):
cwd_loader = jinja2.FileSystemLoader(".")
self.loaders = [internal_loader, cwd_loader]
self._set_loaders()
self.menu_entries = {}

def start(
self,
Expand Down Expand Up @@ -115,6 +116,18 @@ def setup_routes(self) -> None:
)
self.app.router.add_post("/spade/agent/{agentjid}/send/", self.send_agent)

def add_menu_entry(self, name: str, url: str, icon="fa fa-circle") -> None:
"""
Adds a new entry to the menu.
Args:
name (str): name of the entry
url (str): url to be redirected to
icon (str): icon to be displayed (Default value = "fa fa-circle")
"""
self.menu_entries[name] = (url, icon)

def add_get(
self,
path: str,
Expand Down Expand Up @@ -193,7 +206,12 @@ async def agent_processor(self, request):
messages = [
(self.timeago(m[0]), m[1]) for m in self.agent.traces.received(limit=5)
]
return {"agent": self.agent, "messages": messages}
return {
"agent": self.agent,
"messages": messages,
"menu": self.menu_entries,
"active": request.path,
}

# Default controllers for agent

Expand Down
2 changes: 1 addition & 1 deletion tests/test_behaviour.py
Original file line number Diff line number Diff line change
Expand Up @@ -759,7 +759,7 @@ async def run(self):
agent = MockedAgentFactory()
await agent.start(auto_register=False)

start_at = datetime.datetime.now() + datetime.timedelta(seconds=0.01)
start_at = datetime.datetime.now() + datetime.timedelta(seconds=0.02)
behaviour = TestTimeoutBehaviour(start_at=start_at)

assert behaviour._timeout == start_at
Expand Down
37 changes: 33 additions & 4 deletions tests/test_web.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import asyncio
import time
from unittest.mock import AsyncMock, Mock, MagicMock

import pytest
import requests
from aiohttp import web
from aiohttp_jinja2 import get_env
Expand All @@ -10,7 +9,6 @@
from jinja2 import ChoiceLoader, FileSystemLoader, PackageLoader
from parsel import Selector
from testfixtures import LogCapture
from unittest.mock import AsyncMock, Mock, MagicMock

from spade.agent import Agent
from spade.behaviour import OneShotBehaviour, CyclicBehaviour
Expand Down Expand Up @@ -80,14 +78,16 @@ async def test_add_template_path():


async def test_check_server(aiohttp_client, loop):
agent = MockedAgentFactory()
agent = MockedPresenceAgentFactory()
await agent.start(auto_register=False)

agent.web.setup_routes()

client = await aiohttp_client(agent.web.app)
response = await client.get("/spade")

assert response.status == 200

text = await response.text()

sel = Selector(text=text)
Expand Down Expand Up @@ -374,6 +374,8 @@ async def test_stop(aiohttp_client):
client = await aiohttp_client(agent.web.app)

response = await client.get("/spade/stop")
assert response.status == 200

response = await response.text()

sel = Selector(text=response)
Expand Down Expand Up @@ -440,3 +442,30 @@ async def handle_post(request):
assert data["number"] == 1024

await agent.stop()


async def test_add_menu_entry(aiohttp_client):
agent = MockedPresenceAgentFactory()
await agent.start(auto_register=False)
agent.web.setup_routes()

agent.web.add_menu_entry("Test", "/test", "fa fa-test")

client = await aiohttp_client(agent.web.app)
response = await client.get("/spade")

assert response.status == 200

# get html from response
response = await response.text()
# look for menu entry
sel = Selector(text=response)

assert len(sel.css("ul.sidebar-menu > li").getall()) == 2

# get second li element from sidebar-menu
menu_entry = sel.css("ul.sidebar-menu > li").getall()[1]
menu_entry = Selector(text=menu_entry)
assert menu_entry.css("li > a > span::text").get().strip() == "Test"
assert menu_entry.css("a > i::attr(class)").get().strip() == "fa fa-test"
assert menu_entry.css("a::attr(href)").get().strip() == "/test"

0 comments on commit f483278

Please sign in to comment.