Merge pull request #4152 from ostcar/new_projector_iv_motion_slide
New projector IV
This commit is contained in:
commit
1b3c0b4cee
@ -507,9 +507,11 @@ class Motion(RESTModelMixin, models.Model):
|
||||
"""
|
||||
if self.recommendation is not None:
|
||||
self.set_state(self.recommendation)
|
||||
if (self.recommendation_extension is not None
|
||||
if (
|
||||
self.recommendation_extension is not None
|
||||
and self.state.show_state_extension_field
|
||||
and self.recommendation.show_recommendation_extension_field):
|
||||
and self.recommendation.show_recommendation_extension_field
|
||||
):
|
||||
self.state_extension = self.recommendation_extension
|
||||
|
||||
"""
|
||||
|
@ -1,6 +1,6 @@
|
||||
from typing import Any, Dict
|
||||
|
||||
from ..utils.projector import register_projector_element
|
||||
from ..utils.projector import AllData, get_config, get_user, register_projector_element
|
||||
|
||||
|
||||
# Important: All functions have to be prune. This means, that thay can only
|
||||
@ -9,18 +9,105 @@ from ..utils.projector import register_projector_element
|
||||
# to be fast!
|
||||
|
||||
|
||||
def motion(
|
||||
element: Dict[str, Any], all_data: Dict[str, Dict[int, Dict[str, Any]]]
|
||||
def get_state(
|
||||
all_data: AllData, motion: Dict[str, Any], state_id: int
|
||||
) -> Dict[str, Any]:
|
||||
"""
|
||||
Returns a state element from one motion.
|
||||
|
||||
Returns an error if the state_id does not exist for the workflow in the motion.
|
||||
"""
|
||||
states = all_data["motions/workflow"][motion["workflow_id"]]["states"]
|
||||
for state in states:
|
||||
if state["id"] == state_id:
|
||||
return state
|
||||
return {"error": f"motion {motion['id']} can not have to id {state_id}"}
|
||||
|
||||
|
||||
def motion_slide(element: Dict[str, Any], all_data: AllData) -> Dict[str, Any]:
|
||||
"""
|
||||
Motion slide.
|
||||
|
||||
The returned dict can contain the following fields:
|
||||
* identifier
|
||||
* title
|
||||
* text
|
||||
* amendment_paragraphs
|
||||
* is_child
|
||||
* show_meta_box
|
||||
* reason
|
||||
* modified_final_version
|
||||
* state
|
||||
* state_extension
|
||||
* recommendation
|
||||
* recommendation_extension
|
||||
* submitter
|
||||
* poll
|
||||
"""
|
||||
return {"error": "TODO", "some_key": "another_value"}
|
||||
mode = element.get("mode")
|
||||
motion_id = element.get("id")
|
||||
|
||||
if motion_id is None:
|
||||
return {"error": "id is required for motion slide"}
|
||||
|
||||
try:
|
||||
motion = all_data["motions/motion"][motion_id]
|
||||
except KeyError:
|
||||
return {"error": f"motion with id {motion_id} does not exist"}
|
||||
|
||||
show_meta_box = not get_config(all_data, "motions_disable_sidebox_on_projector")
|
||||
|
||||
return_value = {
|
||||
"identifier": motion["identifier"],
|
||||
"title": motion["title"],
|
||||
"text": motion["text"],
|
||||
"amendment_paragraphs": motion["amendment_paragraphs"],
|
||||
"is_child": bool(motion["parent_id"]),
|
||||
"show_meta_box": show_meta_box,
|
||||
}
|
||||
|
||||
if not get_config(all_data, "motions_disable_reason_on_projector"):
|
||||
return_value["reason"] = motion["reason"]
|
||||
if mode == "final":
|
||||
return_value["modified_final_version"] = motion["modified_final_version"]
|
||||
|
||||
if show_meta_box:
|
||||
state = get_state(all_data, motion, motion["state_id"])
|
||||
if state.get("error"):
|
||||
return state
|
||||
|
||||
return_value["state"] = state["name"]
|
||||
return_value["state_extension"] = motion["state_extension"]
|
||||
|
||||
if (
|
||||
not get_config(all_data, "motions_disable_recommendation_on_projector")
|
||||
and motion["recommendation_id"]
|
||||
):
|
||||
return_value["recommendation"] = all_data[
|
||||
"motions/motion-change-recommendation"
|
||||
][motion["recommendation_id"]]["text"]
|
||||
return_value["recommendation_extension"] = motion[
|
||||
"recommendation_extension"
|
||||
]
|
||||
|
||||
return_value["submitter"] = [
|
||||
get_user(all_data, submitter["user_id"])
|
||||
for submitter in motion["submitters"]
|
||||
]
|
||||
|
||||
for poll in motion["polls"][::-1]:
|
||||
if poll["has_votes"]:
|
||||
return_value["poll"] = {
|
||||
"yes": poll["yes"],
|
||||
"no": poll["no"],
|
||||
"abstain": poll["abstain"],
|
||||
}
|
||||
break
|
||||
|
||||
return return_value
|
||||
|
||||
|
||||
def motion_block(
|
||||
element: Dict[str, Any], all_data: Dict[str, Dict[int, Dict[str, Any]]]
|
||||
) -> Dict[str, Any]:
|
||||
def motion_block(element: Dict[str, Any], all_data: AllData) -> Dict[str, Any]:
|
||||
"""
|
||||
Motion slide.
|
||||
"""
|
||||
@ -28,5 +115,5 @@ def motion_block(
|
||||
|
||||
|
||||
def register_projector_elements() -> None:
|
||||
register_projector_element("motions/motion", motion)
|
||||
register_projector_element("motions/motion", motion_slide)
|
||||
register_projector_element("motions/motion-block", motion_block)
|
||||
|
@ -92,3 +92,15 @@ def get_config(all_data: AllData, key: str) -> Any:
|
||||
return all_data[config.get_collection_string()][config.get_key_to_id()[key]][
|
||||
"value"
|
||||
]
|
||||
|
||||
|
||||
def get_user(all_data: AllData, user_id: int) -> Dict[str, Any]:
|
||||
"""
|
||||
Returns the value of a user to show his name.
|
||||
"""
|
||||
user = all_data["users/user"][user_id]
|
||||
return {
|
||||
"title": user["title"],
|
||||
"first_name": user["first_name"],
|
||||
"last_name": user["last_name"],
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ from django.test.utils import CaptureQueriesContext
|
||||
from openslides.core.config import config
|
||||
from openslides.core.models import Projector
|
||||
from openslides.users.models import User
|
||||
from openslides.utils.projector import get_config, register_projector_element
|
||||
from openslides.utils.projector import AllData, get_config, register_projector_element
|
||||
|
||||
|
||||
class TConfig:
|
||||
@ -90,18 +90,14 @@ class TProjector:
|
||||
return elements
|
||||
|
||||
|
||||
def slide1(
|
||||
config: Dict[str, Any], all_data: Dict[str, Dict[int, Dict[str, Any]]]
|
||||
) -> Dict[str, Any]:
|
||||
def slide1(element: Dict[str, Any], all_data: AllData) -> Dict[str, Any]:
|
||||
"""
|
||||
Slide that shows the general_event_name.
|
||||
"""
|
||||
return {"name": "slide1", "event_name": get_config(all_data, "general_event_name")}
|
||||
|
||||
|
||||
def slide2(
|
||||
config: Dict[str, Any], all_data: Dict[str, Dict[int, Dict[str, Any]]]
|
||||
) -> Dict[str, Any]:
|
||||
def slide2(element: Dict[str, Any], all_data: AllData) -> Dict[str, Any]:
|
||||
return {"name": "slide2"}
|
||||
|
||||
|
||||
@ -121,3 +117,19 @@ def count_queries(func, *args, **kwargs) -> int:
|
||||
|
||||
print(f"{len(context)} queries executed\nCaptured queries were:\n{queries}")
|
||||
return len(context)
|
||||
|
||||
|
||||
def all_data_config() -> AllData:
|
||||
return {
|
||||
TConfig().get_collection_string(): {
|
||||
element["id"]: element for element in TConfig().get_elements()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def all_data_users() -> AllData:
|
||||
return {
|
||||
TUser().get_collection_string(): {
|
||||
element["id"]: element for element in TUser().get_elements()
|
||||
}
|
||||
}
|
||||
|
173
tests/unit/motions/test_projector.py
Normal file
173
tests/unit/motions/test_projector.py
Normal file
@ -0,0 +1,173 @@
|
||||
from typing import Any, Dict
|
||||
|
||||
import pytest
|
||||
|
||||
from openslides.motions import projector
|
||||
|
||||
from ...integration.helpers import all_data_config, all_data_users
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def all_data():
|
||||
return_value = all_data_config()
|
||||
return_value.update(all_data_users())
|
||||
return_value["motions/motion"] = {
|
||||
1: {
|
||||
"id": 1,
|
||||
"identifier": "4",
|
||||
"title": "12345",
|
||||
"text": "motion text",
|
||||
"amendment_paragraphs": None,
|
||||
"modified_final_version": "",
|
||||
"reason": "",
|
||||
"parent_id": None,
|
||||
"category_id": None,
|
||||
"comments": [],
|
||||
"motion_block_id": None,
|
||||
"origin": "",
|
||||
"submitters": [{"id": 4, "user_id": 1, "motion_id": 1, "weight": 1}],
|
||||
"supporters_id": [],
|
||||
"state_id": 1,
|
||||
"state_extension": None,
|
||||
"state_required_permission_to_see": "",
|
||||
"statute_paragraph_id": None,
|
||||
"workflow_id": 1,
|
||||
"recommendation_id": None,
|
||||
"recommendation_extension": None,
|
||||
"tags_id": [],
|
||||
"attachments_id": [],
|
||||
"polls": [
|
||||
{
|
||||
"id": 1,
|
||||
"motion_id": 4,
|
||||
"yes": "10.000000",
|
||||
"no": "-1.000000",
|
||||
"abstain": "20.000000",
|
||||
"votesvalid": "11.000000",
|
||||
"votesinvalid": "2.000000",
|
||||
"votescast": "30.000000",
|
||||
"has_votes": True,
|
||||
}
|
||||
],
|
||||
"agenda_item_id": 4,
|
||||
"log_messages": [
|
||||
{
|
||||
"message_list": "['Vote updated']",
|
||||
"person_id": 1,
|
||||
"time": "2019-01-19T22:15:53.291123+01:00",
|
||||
"message": "Jan. 19, 2019, 10:15 p.m. Vote updated by Administrator",
|
||||
},
|
||||
{
|
||||
"message_list": "['Vote created']",
|
||||
"person_id": 1,
|
||||
"time": "2019-01-19T22:15:37.446262+01:00",
|
||||
"message": "Jan. 19, 2019, 10:15 p.m. Vote created by Administrator",
|
||||
},
|
||||
{
|
||||
"message_list": "['Motion created']",
|
||||
"person_id": 1,
|
||||
"time": "2019-01-19T18:37:34.833749+01:00",
|
||||
"message": "Jan. 19, 2019, 6:37 p.m. Motion created by Administrator",
|
||||
},
|
||||
],
|
||||
"sort_parent_id": None,
|
||||
"weight": 10000,
|
||||
"created": "2019-01-19T18:37:34.741336+01:00",
|
||||
"last_modified": "2019-01-19T18:37:34.741368+01:00",
|
||||
}
|
||||
}
|
||||
return_value["motions/workflow"] = {
|
||||
1: {
|
||||
"id": 1,
|
||||
"name": "Simple Workflow",
|
||||
"states": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "submitted",
|
||||
"recommendation_label": None,
|
||||
"css_class": "primary",
|
||||
"required_permission_to_see": "",
|
||||
"allow_support": True,
|
||||
"allow_create_poll": True,
|
||||
"allow_submitter_edit": True,
|
||||
"dont_set_identifier": False,
|
||||
"show_state_extension_field": False,
|
||||
"merge_amendment_into_final": 0,
|
||||
"show_recommendation_extension_field": False,
|
||||
"next_states_id": [2, 3, 4],
|
||||
"workflow_id": 1,
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "accepted",
|
||||
"recommendation_label": "Acceptance",
|
||||
"css_class": "success",
|
||||
"required_permission_to_see": "",
|
||||
"allow_support": False,
|
||||
"allow_create_poll": False,
|
||||
"allow_submitter_edit": False,
|
||||
"dont_set_identifier": False,
|
||||
"show_state_extension_field": False,
|
||||
"merge_amendment_into_final": 1,
|
||||
"show_recommendation_extension_field": False,
|
||||
"next_states_id": [],
|
||||
"workflow_id": 1,
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"name": "rejected",
|
||||
"recommendation_label": "Rejection",
|
||||
"css_class": "danger",
|
||||
"required_permission_to_see": "",
|
||||
"allow_support": False,
|
||||
"allow_create_poll": False,
|
||||
"allow_submitter_edit": False,
|
||||
"dont_set_identifier": False,
|
||||
"show_state_extension_field": False,
|
||||
"merge_amendment_into_final": -1,
|
||||
"show_recommendation_extension_field": False,
|
||||
"next_states_id": [],
|
||||
"workflow_id": 1,
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"name": "not decided",
|
||||
"recommendation_label": "No decision",
|
||||
"css_class": "default",
|
||||
"required_permission_to_see": "",
|
||||
"allow_support": False,
|
||||
"allow_create_poll": False,
|
||||
"allow_submitter_edit": False,
|
||||
"dont_set_identifier": False,
|
||||
"show_state_extension_field": False,
|
||||
"merge_amendment_into_final": -1,
|
||||
"show_recommendation_extension_field": False,
|
||||
"next_states_id": [],
|
||||
"workflow_id": 1,
|
||||
},
|
||||
],
|
||||
"first_state_id": 1,
|
||||
}
|
||||
}
|
||||
return_value["motions/motion-change-recommendation"] = {}
|
||||
return return_value
|
||||
|
||||
|
||||
def test_motion_slide(all_data):
|
||||
element: Dict[str, Any] = {"id": 1}
|
||||
|
||||
data = projector.motion_slide(element, all_data)
|
||||
|
||||
assert data == {
|
||||
"identifier": "4",
|
||||
"title": "12345",
|
||||
"text": "motion text",
|
||||
"amendment_paragraphs": None,
|
||||
"is_child": False,
|
||||
"show_meta_box": True,
|
||||
"reason": "",
|
||||
"state": "submitted",
|
||||
"state_extension": None,
|
||||
"submitter": [{"first_name": "", "last_name": "Administrator", "title": ""}],
|
||||
"poll": {"yes": "10.000000", "no": "-1.000000", "abstain": "20.000000"},
|
||||
}
|
Loading…
Reference in New Issue
Block a user