Projector V
* Changed wording: element is one element on the projector. A slide is a functoin to render one element * Use AllData as first argument all the time * Render username on server * Add exceptions for erros on projector * Fix motion recommendation * Only show state extension, if it is allowed by the state * Add motion_change_recommendations to motion full_data
This commit is contained in:
parent
0d8cbbaab9
commit
1a709a59a9
@ -13,7 +13,7 @@ class AgendaAppConfig(AppConfig):
|
|||||||
from django.db.models.signals import pre_delete, post_save
|
from django.db.models.signals import pre_delete, post_save
|
||||||
from ..core.signals import permission_change
|
from ..core.signals import permission_change
|
||||||
from ..utils.rest_api import router
|
from ..utils.rest_api import router
|
||||||
from .projector import register_projector_elements
|
from .projector import register_projector_slides
|
||||||
from .signals import (
|
from .signals import (
|
||||||
get_permission_change_data,
|
get_permission_change_data,
|
||||||
listen_to_related_object_post_delete,
|
listen_to_related_object_post_delete,
|
||||||
@ -24,7 +24,7 @@ class AgendaAppConfig(AppConfig):
|
|||||||
from ..utils.access_permissions import required_user
|
from ..utils.access_permissions import required_user
|
||||||
|
|
||||||
# Define projector elements.
|
# Define projector elements.
|
||||||
register_projector_elements()
|
register_projector_slides()
|
||||||
|
|
||||||
# Connect signals.
|
# Connect signals.
|
||||||
post_save.connect(
|
post_save.connect(
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from typing import Any, Dict, List, Tuple
|
from typing import Any, Dict, List, Tuple
|
||||||
|
|
||||||
from ..utils.projector import AllData, register_projector_element
|
from ..utils.projector import (
|
||||||
|
AllData,
|
||||||
|
ProjectorElementException,
|
||||||
|
register_projector_slide,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# Important: All functions have to be prune. This means, that thay can only
|
# Important: All functions have to be prune. This means, that thay can only
|
||||||
@ -41,7 +45,7 @@ def get_tree(
|
|||||||
return get_children(children[parent_id])
|
return get_children(children[parent_id])
|
||||||
|
|
||||||
|
|
||||||
def items(element: Dict[str, Any], all_data: AllData) -> Dict[str, Any]:
|
def items_slide(all_data: AllData, element: Dict[str, Any]) -> Dict[str, Any]:
|
||||||
"""
|
"""
|
||||||
Item list slide.
|
Item list slide.
|
||||||
|
|
||||||
@ -63,7 +67,9 @@ def items(element: Dict[str, Any], all_data: AllData) -> Dict[str, Any]:
|
|||||||
return {"items": agenda_items}
|
return {"items": agenda_items}
|
||||||
|
|
||||||
|
|
||||||
def list_of_speakers(element: Dict[str, Any], all_data: AllData) -> Dict[str, Any]:
|
def list_of_speakers_slide(
|
||||||
|
all_data: AllData, element: Dict[str, Any]
|
||||||
|
) -> Dict[str, Any]:
|
||||||
"""
|
"""
|
||||||
List of speakers slide.
|
List of speakers slide.
|
||||||
|
|
||||||
@ -76,7 +82,7 @@ def list_of_speakers(element: Dict[str, Any], all_data: AllData) -> Dict[str, An
|
|||||||
try:
|
try:
|
||||||
item = all_data["agenda/item"][item_id]
|
item = all_data["agenda/item"][item_id]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
return {"error": f"Item {item_id} does not exist"}
|
raise ProjectorElementException(f"Item {item_id} does not exist")
|
||||||
|
|
||||||
user_ids = []
|
user_ids = []
|
||||||
for speaker in item["speakers"]:
|
for speaker in item["speakers"]:
|
||||||
@ -84,6 +90,6 @@ def list_of_speakers(element: Dict[str, Any], all_data: AllData) -> Dict[str, An
|
|||||||
return {"user_ids": user_ids}
|
return {"user_ids": user_ids}
|
||||||
|
|
||||||
|
|
||||||
def register_projector_elements() -> None:
|
def register_projector_slides() -> None:
|
||||||
register_projector_element("agenda/item-list", items)
|
register_projector_slide("agenda/item-list", items_slide)
|
||||||
register_projector_element("agenda/list-of-speakers", list_of_speakers)
|
register_projector_slide("agenda/list-of-speakers", list_of_speakers_slide)
|
||||||
|
@ -15,12 +15,12 @@ class AssignmentsAppConfig(AppConfig):
|
|||||||
from ..utils.access_permissions import required_user
|
from ..utils.access_permissions import required_user
|
||||||
from ..utils.rest_api import router
|
from ..utils.rest_api import router
|
||||||
from . import serializers # noqa
|
from . import serializers # noqa
|
||||||
from .projector import register_projector_elements
|
from .projector import register_projector_slides
|
||||||
from .signals import get_permission_change_data
|
from .signals import get_permission_change_data
|
||||||
from .views import AssignmentViewSet, AssignmentPollViewSet
|
from .views import AssignmentViewSet, AssignmentPollViewSet
|
||||||
|
|
||||||
# Define projector elements.
|
# Define projector elements.
|
||||||
register_projector_elements()
|
register_projector_slides()
|
||||||
|
|
||||||
# Connect signals.
|
# Connect signals.
|
||||||
permission_change.connect(
|
permission_change.connect(
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
from typing import Any, Dict
|
from typing import Any, Dict
|
||||||
|
|
||||||
from ..utils.projector import register_projector_element
|
from ..utils.projector import AllData, register_projector_slide
|
||||||
|
|
||||||
|
|
||||||
# Important: All functions have to be prune. This means, that thay can only
|
# Important: All functions have to be prune. This means, that thay can only
|
||||||
@ -9,9 +9,7 @@ from ..utils.projector import register_projector_element
|
|||||||
# to be fast!
|
# to be fast!
|
||||||
|
|
||||||
|
|
||||||
def assignment(
|
def assignment_slide(all_data: AllData, element: Dict[str, Any]) -> Dict[str, Any]:
|
||||||
element: Dict[str, Any], all_data: Dict[str, Dict[int, Dict[str, Any]]]
|
|
||||||
) -> Dict[str, Any]:
|
|
||||||
"""
|
"""
|
||||||
Assignment slide.
|
Assignment slide.
|
||||||
"""
|
"""
|
||||||
@ -19,5 +17,5 @@ def assignment(
|
|||||||
return {"error": "TODO"}
|
return {"error": "TODO"}
|
||||||
|
|
||||||
|
|
||||||
def register_projector_elements() -> None:
|
def register_projector_slides() -> None:
|
||||||
register_projector_element("assignments/assignment", assignment)
|
register_projector_slide("assignments/assignment", assignment_slide)
|
||||||
|
@ -17,7 +17,7 @@ class CoreAppConfig(AppConfig):
|
|||||||
def ready(self):
|
def ready(self):
|
||||||
# Import all required stuff.
|
# Import all required stuff.
|
||||||
from .config import config
|
from .config import config
|
||||||
from .projector import register_projector_elements
|
from .projector import register_projector_slides
|
||||||
from . import serializers # noqa
|
from . import serializers # noqa
|
||||||
from .signals import (
|
from .signals import (
|
||||||
delete_django_app_permissions,
|
delete_django_app_permissions,
|
||||||
@ -49,7 +49,7 @@ class CoreAppConfig(AppConfig):
|
|||||||
config.collect_config_variables_from_apps()
|
config.collect_config_variables_from_apps()
|
||||||
|
|
||||||
# Define projector elements.
|
# Define projector elements.
|
||||||
register_projector_elements()
|
register_projector_slides()
|
||||||
|
|
||||||
# Connect signals.
|
# Connect signals.
|
||||||
post_permission_creation.connect(
|
post_permission_creation.connect(
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
from typing import Any, Dict
|
from typing import Any, Dict
|
||||||
|
|
||||||
from ..utils.projector import register_projector_element
|
from ..utils.projector import AllData, register_projector_slide
|
||||||
|
|
||||||
|
|
||||||
# Important: All functions have to be prune. This means, that thay can only
|
# Important: All functions have to be prune. This means, that thay can only
|
||||||
@ -9,9 +9,7 @@ from ..utils.projector import register_projector_element
|
|||||||
# to be fast!
|
# to be fast!
|
||||||
|
|
||||||
|
|
||||||
def countdown(
|
def countdown_slide(all_data: AllData, element: Dict[str, Any]) -> Dict[str, Any]:
|
||||||
element: Dict[str, Any], all_data: Dict[str, Dict[int, Dict[str, Any]]]
|
|
||||||
) -> Dict[str, Any]:
|
|
||||||
"""
|
"""
|
||||||
Countdown slide.
|
Countdown slide.
|
||||||
|
|
||||||
@ -30,9 +28,7 @@ def countdown(
|
|||||||
return {"error": f"Countdown {countdown_id} does not exist"}
|
return {"error": f"Countdown {countdown_id} does not exist"}
|
||||||
|
|
||||||
|
|
||||||
def message(
|
def message_slide(all_data: AllData, element: Dict[str, Any]) -> Dict[str, Any]:
|
||||||
element: Dict[str, Any], all_data: Dict[str, Dict[int, Dict[str, Any]]]
|
|
||||||
) -> Dict[str, Any]:
|
|
||||||
"""
|
"""
|
||||||
Message slide.
|
Message slide.
|
||||||
|
|
||||||
@ -51,7 +47,7 @@ def message(
|
|||||||
return {"error": f"Message {message_id} does not exist"}
|
return {"error": f"Message {message_id} does not exist"}
|
||||||
|
|
||||||
|
|
||||||
def register_projector_elements() -> None:
|
def register_projector_slides() -> None:
|
||||||
register_projector_element("core/countdown", countdown)
|
register_projector_slide("core/countdown", countdown_slide)
|
||||||
register_projector_element("core/projector-message", message)
|
register_projector_slide("core/projector-message", message_slide)
|
||||||
# TODO: Add clock slide
|
# TODO: Add clock slide
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from ..utils.projector import projector_elements
|
from ..utils.projector import projector_slides
|
||||||
from ..utils.rest_api import Field, IntegerField, ModelSerializer, ValidationError
|
from ..utils.rest_api import Field, IntegerField, ModelSerializer, ValidationError
|
||||||
from ..utils.validate import validate_html
|
from ..utils.validate import validate_html
|
||||||
from .models import (
|
from .models import (
|
||||||
@ -56,7 +56,7 @@ def elements_validator(value: Any) -> None:
|
|||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
{"detail": "Every dictionary must have a key 'name'."}
|
{"detail": "Every dictionary must have a key 'name'."}
|
||||||
)
|
)
|
||||||
if element["name"] not in projector_elements:
|
if element["name"] not in projector_slides:
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
{"detail": f"Unknown projector element {element['name']},"}
|
{"detail": f"Unknown projector element {element['name']},"}
|
||||||
)
|
)
|
||||||
|
@ -12,14 +12,14 @@ class MediafilesAppConfig(AppConfig):
|
|||||||
# Import all required stuff.
|
# Import all required stuff.
|
||||||
from openslides.core.signals import permission_change
|
from openslides.core.signals import permission_change
|
||||||
from openslides.utils.rest_api import router
|
from openslides.utils.rest_api import router
|
||||||
from .projector import register_projector_elements
|
from .projector import register_projector_slides
|
||||||
from .signals import get_permission_change_data
|
from .signals import get_permission_change_data
|
||||||
from .views import MediafileViewSet
|
from .views import MediafileViewSet
|
||||||
from . import serializers # noqa
|
from . import serializers # noqa
|
||||||
from ..utils.access_permissions import required_user
|
from ..utils.access_permissions import required_user
|
||||||
|
|
||||||
# Define projector elements.
|
# Define projector elements.
|
||||||
register_projector_elements()
|
register_projector_slides()
|
||||||
|
|
||||||
# Connect signals.
|
# Connect signals.
|
||||||
permission_change.connect(
|
permission_change.connect(
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
from typing import Any, Dict
|
from typing import Any, Dict
|
||||||
|
|
||||||
from ..utils.projector import register_projector_element
|
from ..utils.projector import AllData, register_projector_slide
|
||||||
|
|
||||||
|
|
||||||
# Important: All functions have to be prune. This means, that thay can only
|
# Important: All functions have to be prune. This means, that thay can only
|
||||||
@ -9,14 +9,12 @@ from ..utils.projector import register_projector_element
|
|||||||
# to be fast!
|
# to be fast!
|
||||||
|
|
||||||
|
|
||||||
def mediafile(
|
def mediafile_slide(all_data: AllData, element: Dict[str, Any]) -> Dict[str, Any]:
|
||||||
element: Dict[str, Any], all_data: Dict[str, Dict[int, Dict[str, Any]]]
|
|
||||||
) -> Dict[str, Any]:
|
|
||||||
"""
|
"""
|
||||||
Slide for Mediafile.
|
Slide for Mediafile.
|
||||||
"""
|
"""
|
||||||
return {"error": "TODO"}
|
return {"error": "TODO"}
|
||||||
|
|
||||||
|
|
||||||
def register_projector_elements() -> None:
|
def register_projector_slides() -> None:
|
||||||
register_projector_element("mediafiles/mediafile", mediafile)
|
register_projector_slide("mediafiles/mediafile", mediafile_slide)
|
||||||
|
@ -13,7 +13,7 @@ class MotionsAppConfig(AppConfig):
|
|||||||
# Import all required stuff.
|
# Import all required stuff.
|
||||||
from openslides.core.signals import permission_change
|
from openslides.core.signals import permission_change
|
||||||
from openslides.utils.rest_api import router
|
from openslides.utils.rest_api import router
|
||||||
from .projector import register_projector_elements
|
from .projector import register_projector_slides
|
||||||
from .signals import create_builtin_workflows, get_permission_change_data
|
from .signals import create_builtin_workflows, get_permission_change_data
|
||||||
from . import serializers # noqa
|
from . import serializers # noqa
|
||||||
from .views import (
|
from .views import (
|
||||||
@ -30,7 +30,7 @@ class MotionsAppConfig(AppConfig):
|
|||||||
from ..utils.access_permissions import required_user
|
from ..utils.access_permissions import required_user
|
||||||
|
|
||||||
# Define projector elements.
|
# Define projector elements.
|
||||||
register_projector_elements()
|
register_projector_slides()
|
||||||
|
|
||||||
# Connect signals.
|
# Connect signals.
|
||||||
post_migrate.connect(
|
post_migrate.connect(
|
||||||
|
@ -87,6 +87,7 @@ class MotionManager(models.Manager):
|
|||||||
"tags",
|
"tags",
|
||||||
"submitters",
|
"submitters",
|
||||||
"supporters",
|
"supporters",
|
||||||
|
"change_recommendations",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -1,6 +1,12 @@
|
|||||||
from typing import Any, Dict
|
from typing import Any, Dict
|
||||||
|
|
||||||
from ..utils.projector import AllData, get_config, get_user, register_projector_element
|
from ..users.projector import get_user_name
|
||||||
|
from ..utils.projector import (
|
||||||
|
AllData,
|
||||||
|
ProjectorElementException,
|
||||||
|
get_config,
|
||||||
|
register_projector_slide,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# Important: All functions have to be prune. This means, that thay can only
|
# Important: All functions have to be prune. This means, that thay can only
|
||||||
@ -21,10 +27,12 @@ def get_state(
|
|||||||
for state in states:
|
for state in states:
|
||||||
if state["id"] == state_id:
|
if state["id"] == state_id:
|
||||||
return state
|
return state
|
||||||
return {"error": f"motion {motion['id']} can not have to id {state_id}"}
|
raise ProjectorElementException(
|
||||||
|
f"motion {motion['id']} can not be on the state with id {state_id}"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def motion_slide(element: Dict[str, Any], all_data: AllData) -> Dict[str, Any]:
|
def motion_slide(all_data: AllData, element: Dict[str, Any]) -> Dict[str, Any]:
|
||||||
"""
|
"""
|
||||||
Motion slide.
|
Motion slide.
|
||||||
|
|
||||||
@ -53,7 +61,7 @@ def motion_slide(element: Dict[str, Any], all_data: AllData) -> Dict[str, Any]:
|
|||||||
try:
|
try:
|
||||||
motion = all_data["motions/motion"][motion_id]
|
motion = all_data["motions/motion"][motion_id]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
return {"error": f"motion with id {motion_id} does not exist"}
|
raise ProjectorElementException(f"motion with id {motion_id} does not exist")
|
||||||
|
|
||||||
show_meta_box = not get_config(all_data, "motions_disable_sidebox_on_projector")
|
show_meta_box = not get_config(all_data, "motions_disable_sidebox_on_projector")
|
||||||
|
|
||||||
@ -68,31 +76,38 @@ def motion_slide(element: Dict[str, Any], all_data: AllData) -> Dict[str, Any]:
|
|||||||
|
|
||||||
if not get_config(all_data, "motions_disable_reason_on_projector"):
|
if not get_config(all_data, "motions_disable_reason_on_projector"):
|
||||||
return_value["reason"] = motion["reason"]
|
return_value["reason"] = motion["reason"]
|
||||||
|
|
||||||
if mode == "final":
|
if mode == "final":
|
||||||
return_value["modified_final_version"] = motion["modified_final_version"]
|
return_value["modified_final_version"] = motion["modified_final_version"]
|
||||||
|
|
||||||
if show_meta_box:
|
if show_meta_box:
|
||||||
state = get_state(all_data, motion, motion["state_id"])
|
state = get_state(all_data, motion, motion["state_id"])
|
||||||
if state.get("error"):
|
|
||||||
return state
|
|
||||||
|
|
||||||
return_value["state"] = state["name"]
|
return_value["state"] = state["name"]
|
||||||
return_value["state_extension"] = motion["state_extension"]
|
if state["show_state_extension_field"]:
|
||||||
|
return_value["state_extension"] = motion["state_extension"]
|
||||||
|
|
||||||
if (
|
if (
|
||||||
not get_config(all_data, "motions_disable_recommendation_on_projector")
|
not get_config(all_data, "motions_disable_recommendation_on_projector")
|
||||||
and motion["recommendation_id"]
|
and motion["recommendation_id"]
|
||||||
):
|
):
|
||||||
return_value["recommendation"] = all_data[
|
recommendation_state = get_state(
|
||||||
"motions/motion-change-recommendation"
|
all_data, motion, motion["recommendation_id"]
|
||||||
][motion["recommendation_id"]]["text"]
|
)
|
||||||
return_value["recommendation_extension"] = motion[
|
return_value["recommendation"] = recommendation_state[
|
||||||
"recommendation_extension"
|
"recommendation_label"
|
||||||
]
|
]
|
||||||
|
if recommendation_state["show_recommendation_extension_field"]:
|
||||||
|
return_value["recommendation_extension"] = motion[
|
||||||
|
"recommendation_extension"
|
||||||
|
]
|
||||||
|
|
||||||
|
return_value["change_recommendations"] = motion["change_recommendations"]
|
||||||
|
|
||||||
return_value["submitter"] = [
|
return_value["submitter"] = [
|
||||||
get_user(all_data, submitter["user_id"])
|
get_user_name(all_data, submitter["user_id"])
|
||||||
for submitter in motion["submitters"]
|
for submitter in sorted(
|
||||||
|
motion["submitters"], key=lambda submitter: submitter["weight"]
|
||||||
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
for poll in motion["polls"][::-1]:
|
for poll in motion["polls"][::-1]:
|
||||||
@ -107,13 +122,13 @@ def motion_slide(element: Dict[str, Any], all_data: AllData) -> Dict[str, Any]:
|
|||||||
return return_value
|
return return_value
|
||||||
|
|
||||||
|
|
||||||
def motion_block(element: Dict[str, Any], all_data: AllData) -> Dict[str, Any]:
|
def motion_block_slide(all_data: AllData, element: Dict[str, Any]) -> Dict[str, Any]:
|
||||||
"""
|
"""
|
||||||
Motion slide.
|
Motion slide.
|
||||||
"""
|
"""
|
||||||
return {"error": "TODO"}
|
return {"error": "TODO"}
|
||||||
|
|
||||||
|
|
||||||
def register_projector_elements() -> None:
|
def register_projector_slides() -> None:
|
||||||
register_projector_element("motions/motion", motion_slide)
|
register_projector_slide("motions/motion", motion_slide)
|
||||||
register_projector_element("motions/motion-block", motion_block)
|
register_projector_slide("motions/motion-block", motion_block_slide)
|
||||||
|
@ -400,6 +400,9 @@ class MotionSerializer(ModelSerializer):
|
|||||||
)
|
)
|
||||||
agenda_parent_id = IntegerField(write_only=True, required=False, min_value=1)
|
agenda_parent_id = IntegerField(write_only=True, required=False, min_value=1)
|
||||||
submitters = SubmitterSerializer(many=True, read_only=True)
|
submitters = SubmitterSerializer(many=True, read_only=True)
|
||||||
|
change_recommendations = MotionChangeRecommendationSerializer(
|
||||||
|
many=True, read_only=True
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Motion
|
model = Motion
|
||||||
@ -436,6 +439,7 @@ class MotionSerializer(ModelSerializer):
|
|||||||
"weight",
|
"weight",
|
||||||
"created",
|
"created",
|
||||||
"last_modified",
|
"last_modified",
|
||||||
|
"change_recommendations",
|
||||||
)
|
)
|
||||||
read_only_fields = (
|
read_only_fields = (
|
||||||
"state",
|
"state",
|
||||||
|
@ -10,13 +10,13 @@ class TopicsAppConfig(AppConfig):
|
|||||||
# Import all required stuff.
|
# Import all required stuff.
|
||||||
from openslides.core.signals import permission_change
|
from openslides.core.signals import permission_change
|
||||||
from ..utils.rest_api import router
|
from ..utils.rest_api import router
|
||||||
from .projector import register_projector_elements
|
from .projector import register_projector_slides
|
||||||
from .signals import get_permission_change_data
|
from .signals import get_permission_change_data
|
||||||
from .views import TopicViewSet
|
from .views import TopicViewSet
|
||||||
from . import serializers # noqa
|
from . import serializers # noqa
|
||||||
|
|
||||||
# Define projector elements.
|
# Define projector elements.
|
||||||
register_projector_elements()
|
register_projector_slides()
|
||||||
|
|
||||||
# Connect signals.
|
# Connect signals.
|
||||||
permission_change.connect(
|
permission_change.connect(
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
from typing import Any, Dict
|
from typing import Any, Dict
|
||||||
|
|
||||||
from ..utils.projector import register_projector_element
|
from ..utils.projector import AllData, register_projector_slide
|
||||||
|
|
||||||
|
|
||||||
# Important: All functions have to be prune. This means, that thay can only
|
# Important: All functions have to be prune. This means, that thay can only
|
||||||
@ -9,14 +9,12 @@ from ..utils.projector import register_projector_element
|
|||||||
# to be fast!
|
# to be fast!
|
||||||
|
|
||||||
|
|
||||||
def topic(
|
def topic_slide(all_data: AllData, element: Dict[str, Any]) -> Dict[str, Any]:
|
||||||
element: Dict[str, Any], all_data: Dict[str, Dict[int, Dict[str, Any]]]
|
|
||||||
) -> Dict[str, Any]:
|
|
||||||
"""
|
"""
|
||||||
Topic slide.
|
Topic slide.
|
||||||
"""
|
"""
|
||||||
return {"error": "TODO"}
|
return {"error": "TODO"}
|
||||||
|
|
||||||
|
|
||||||
def register_projector_elements() -> None:
|
def register_projector_slides() -> None:
|
||||||
register_projector_element("topics/topic", topic)
|
register_projector_slide("topics/topic", topic_slide)
|
||||||
|
@ -13,12 +13,12 @@ class UsersAppConfig(AppConfig):
|
|||||||
from . import serializers # noqa
|
from . import serializers # noqa
|
||||||
from ..core.signals import post_permission_creation, permission_change
|
from ..core.signals import post_permission_creation, permission_change
|
||||||
from ..utils.rest_api import router
|
from ..utils.rest_api import router
|
||||||
from .projector import register_projector_elements
|
from .projector import register_projector_slides
|
||||||
from .signals import create_builtin_groups_and_admin, get_permission_change_data
|
from .signals import create_builtin_groups_and_admin, get_permission_change_data
|
||||||
from .views import GroupViewSet, PersonalNoteViewSet, UserViewSet
|
from .views import GroupViewSet, PersonalNoteViewSet, UserViewSet
|
||||||
|
|
||||||
# Define projector elements.
|
# Define projector elements.
|
||||||
register_projector_elements()
|
register_projector_slides()
|
||||||
|
|
||||||
# Connect signals.
|
# Connect signals.
|
||||||
post_permission_creation.connect(
|
post_permission_creation.connect(
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
from typing import Any, Dict
|
from typing import Any, Dict, List
|
||||||
|
|
||||||
from ..utils.projector import register_projector_element
|
from ..utils.projector import AllData, register_projector_slide
|
||||||
|
|
||||||
|
|
||||||
# Important: All functions have to be prune. This means, that thay can only
|
# Important: All functions have to be prune. This means, that thay can only
|
||||||
@ -9,14 +9,28 @@ from ..utils.projector import register_projector_element
|
|||||||
# to be fast!
|
# to be fast!
|
||||||
|
|
||||||
|
|
||||||
def user(
|
def user_slide(all_data: AllData, element: Dict[str, Any]) -> Dict[str, Any]:
|
||||||
element: Dict[str, Any], all_data: Dict[str, Dict[int, Dict[str, Any]]]
|
|
||||||
) -> Dict[str, Any]:
|
|
||||||
"""
|
"""
|
||||||
User slide.
|
User slide.
|
||||||
"""
|
"""
|
||||||
return {"error": "TODO"}
|
return {"error": "TODO"}
|
||||||
|
|
||||||
|
|
||||||
def register_projector_elements() -> None:
|
def get_user_name(all_data: AllData, user_id: int) -> str:
|
||||||
register_projector_element("users/user", user)
|
"""
|
||||||
|
Returns the short name for an user_id.
|
||||||
|
"""
|
||||||
|
user = all_data["users/user"][user_id]
|
||||||
|
name_parts: List[str] = []
|
||||||
|
for name_part in ("title", "first_name", "last_name"):
|
||||||
|
if user[name_part]:
|
||||||
|
name_parts.append(user[name_part])
|
||||||
|
if not name_part:
|
||||||
|
name_parts.append(user["username"])
|
||||||
|
if user["structure_level"]:
|
||||||
|
name_parts.append(f"({user['structure_level']})")
|
||||||
|
return " ".join(name_parts)
|
||||||
|
|
||||||
|
|
||||||
|
def register_projector_slides() -> None:
|
||||||
|
register_projector_slide("users/user", user_slide)
|
||||||
|
@ -11,19 +11,25 @@ from .cache import element_cache
|
|||||||
|
|
||||||
|
|
||||||
AllData = Dict[str, Dict[int, Dict[str, Any]]]
|
AllData = Dict[str, Dict[int, Dict[str, Any]]]
|
||||||
ProjectorElementCallable = Callable[[Dict[str, Any], AllData], Dict[str, Any]]
|
ProjectorSlide = Callable[[AllData, Dict[str, Any]], Dict[str, Any]]
|
||||||
|
|
||||||
|
|
||||||
projector_elements: Dict[str, ProjectorElementCallable] = {}
|
projector_slides: Dict[str, ProjectorSlide] = {}
|
||||||
|
|
||||||
|
|
||||||
def register_projector_element(name: str, element: ProjectorElementCallable) -> None:
|
class ProjectorElementException(Exception):
|
||||||
"""
|
"""
|
||||||
Registers a projector element.
|
Exception for errors in one element on the projector.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def register_projector_slide(name: str, slide: ProjectorSlide) -> None:
|
||||||
|
"""
|
||||||
|
Registers a projector slide.
|
||||||
|
|
||||||
Has to be called in the app.ready method.
|
Has to be called in the app.ready method.
|
||||||
"""
|
"""
|
||||||
projector_elements[name] = element
|
projector_slides[name] = slide
|
||||||
|
|
||||||
|
|
||||||
async def get_projector_data(
|
async def get_projector_data(
|
||||||
@ -75,10 +81,12 @@ async def get_projector_data(
|
|||||||
|
|
||||||
projector_data[projector_id] = []
|
projector_data[projector_id] = []
|
||||||
for element in projector["elements"]:
|
for element in projector["elements"]:
|
||||||
projector_element = projector_elements[element["name"]]
|
projector_slide = projector_slides[element["name"]]
|
||||||
projector_data[projector_id].append(
|
try:
|
||||||
{"data": projector_element(element, all_data), "element": element}
|
data = projector_slide(all_data, element)
|
||||||
)
|
except ProjectorElementException as err:
|
||||||
|
data = {"error": err}
|
||||||
|
projector_data[projector_id].append({"data": data, "element": element})
|
||||||
|
|
||||||
return projector_data
|
return projector_data
|
||||||
|
|
||||||
@ -92,15 +100,3 @@ def get_config(all_data: AllData, key: str) -> Any:
|
|||||||
return all_data[config.get_collection_string()][config.get_key_to_id()[key]][
|
return all_data[config.get_collection_string()][config.get_key_to_id()[key]][
|
||||||
"value"
|
"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.config import config
|
||||||
from openslides.core.models import Projector
|
from openslides.core.models import Projector
|
||||||
from openslides.users.models import User
|
from openslides.users.models import User
|
||||||
from openslides.utils.projector import AllData, get_config, register_projector_element
|
from openslides.utils.projector import AllData, get_config, register_projector_slide
|
||||||
|
|
||||||
|
|
||||||
class TConfig:
|
class TConfig:
|
||||||
@ -90,19 +90,19 @@ class TProjector:
|
|||||||
return elements
|
return elements
|
||||||
|
|
||||||
|
|
||||||
def slide1(element: Dict[str, Any], all_data: AllData) -> Dict[str, Any]:
|
def slide1(all_data: AllData, element: Dict[str, Any]) -> Dict[str, Any]:
|
||||||
"""
|
"""
|
||||||
Slide that shows the general_event_name.
|
Slide that shows the general_event_name.
|
||||||
"""
|
"""
|
||||||
return {"name": "slide1", "event_name": get_config(all_data, "general_event_name")}
|
return {"name": "slide1", "event_name": get_config(all_data, "general_event_name")}
|
||||||
|
|
||||||
|
|
||||||
def slide2(element: Dict[str, Any], all_data: AllData) -> Dict[str, Any]:
|
def slide2(all_data: AllData, element: Dict[str, Any]) -> Dict[str, Any]:
|
||||||
return {"name": "slide2"}
|
return {"name": "slide2"}
|
||||||
|
|
||||||
|
|
||||||
register_projector_element("test/slide1", slide1)
|
register_projector_slide("test/slide1", slide1)
|
||||||
register_projector_element("test/slide2", slide2)
|
register_projector_slide("test/slide2", slide2)
|
||||||
|
|
||||||
|
|
||||||
def count_queries(func, *args, **kwargs) -> int:
|
def count_queries(func, *args, **kwargs) -> int:
|
||||||
|
@ -48,7 +48,8 @@ def test_motion_db_queries():
|
|||||||
* 1 request to get the polls,
|
* 1 request to get the polls,
|
||||||
* 1 request to get the attachments,
|
* 1 request to get the attachments,
|
||||||
* 1 request to get the tags,
|
* 1 request to get the tags,
|
||||||
* 2 requests to get the submitters and supporters.
|
* 2 requests to get the submitters and supporters,
|
||||||
|
* 1 request for change_recommendations.
|
||||||
|
|
||||||
Two comment sections are created and for each motions two comments.
|
Two comment sections are created and for each motions two comments.
|
||||||
"""
|
"""
|
||||||
@ -70,7 +71,7 @@ def test_motion_db_queries():
|
|||||||
)
|
)
|
||||||
# TODO: Create some polls etc.
|
# TODO: Create some polls etc.
|
||||||
|
|
||||||
assert count_queries(Motion.get_elements) == 12
|
assert count_queries(Motion.get_elements) == 13
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db(transaction=False)
|
@pytest.mark.django_db(transaction=False)
|
||||||
|
@ -86,32 +86,32 @@ def all_data():
|
|||||||
|
|
||||||
|
|
||||||
def test_items(all_data):
|
def test_items(all_data):
|
||||||
config: Dict[str, Any] = {}
|
element: Dict[str, Any] = {}
|
||||||
|
|
||||||
data = projector.items(config, all_data)
|
data = projector.items_slide(all_data, element)
|
||||||
|
|
||||||
assert data == {"items": ["Item1", "item2"]}
|
assert data == {"items": ["Item1", "item2"]}
|
||||||
|
|
||||||
|
|
||||||
def test_items_parent(all_data):
|
def test_items_parent(all_data):
|
||||||
config: Dict[str, Any] = {"id": 1}
|
element: Dict[str, Any] = {"id": 1}
|
||||||
|
|
||||||
data = projector.items(config, all_data)
|
data = projector.items_slide(all_data, element)
|
||||||
|
|
||||||
assert data == {"items": ["item4"]}
|
assert data == {"items": ["item4"]}
|
||||||
|
|
||||||
|
|
||||||
def test_items_tree(all_data):
|
def test_items_tree(all_data):
|
||||||
config: Dict[str, Any] = {"tree": True}
|
element: Dict[str, Any] = {"tree": True}
|
||||||
|
|
||||||
data = projector.items(config, all_data)
|
data = projector.items_slide(all_data, element)
|
||||||
|
|
||||||
assert data == {"items": [("Item1", [("item4", [])]), ("item2", [])]}
|
assert data == {"items": [("Item1", [("item4", [])]), ("item2", [])]}
|
||||||
|
|
||||||
|
|
||||||
def test_items_tree_parent(all_data):
|
def test_items_tree_parent(all_data):
|
||||||
config: Dict[str, Any] = {"tree": True, "id": 1}
|
element: Dict[str, Any] = {"tree": True, "id": 1}
|
||||||
|
|
||||||
data = projector.items(config, all_data)
|
data = projector.items_slide(all_data, element)
|
||||||
|
|
||||||
assert data == {"items": [("item4", [])]}
|
assert data == {"items": [("item4", [])]}
|
||||||
|
@ -156,7 +156,7 @@ def all_data():
|
|||||||
def test_motion_slide(all_data):
|
def test_motion_slide(all_data):
|
||||||
element: Dict[str, Any] = {"id": 1}
|
element: Dict[str, Any] = {"id": 1}
|
||||||
|
|
||||||
data = projector.motion_slide(element, all_data)
|
data = projector.motion_slide(all_data, element)
|
||||||
|
|
||||||
assert data == {
|
assert data == {
|
||||||
"identifier": "4",
|
"identifier": "4",
|
||||||
@ -167,7 +167,6 @@ def test_motion_slide(all_data):
|
|||||||
"show_meta_box": True,
|
"show_meta_box": True,
|
||||||
"reason": "",
|
"reason": "",
|
||||||
"state": "submitted",
|
"state": "submitted",
|
||||||
"state_extension": None,
|
"submitter": ["Administrator"],
|
||||||
"submitter": [{"first_name": "", "last_name": "Administrator", "title": ""}],
|
|
||||||
"poll": {"yes": "10.000000", "no": "-1.000000", "abstain": "20.000000"},
|
"poll": {"yes": "10.000000", "no": "-1.000000", "abstain": "20.000000"},
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user