diff --git a/district/blocks.py b/district/blocks.py index ba1c2499957082d0b0bf303b6aadf8a8c1ab607b..b3d5602d2f39ff634d1d54928676cb677847847f 100644 --- a/district/blocks.py +++ b/district/blocks.py @@ -1,6 +1,7 @@ from django.template.defaultfilters import slugify from django.utils.text import slugify from wagtail import blocks +from django.utils.safestring import mark_safe from wagtail.blocks import ( CharBlock, DateTimeBlock, @@ -190,16 +191,31 @@ class OctopusTeamBlock(OctopusMixin): label="Zkratka týmu", help_text="Např. TO-admin", required=True ) + roles = CharBlock( + label="Role", + help_text=mark_safe( + "Pokud chceš zobrazit pouze osoby se specifickými rolemi " + "v tomto týmu, můžeš role zadat zde ve formátu " + "<em>role1,role2,role3</em>." + ), + required=False + ) + def get_context(self, value, *args, **kwargs): from .models import DistrictOctopusPersonPage # Skip OctopusMixin context = blocks.StructBlock.get_context(self, value, *args, **kwargs) + filter = Q( + originating_team=value["team_shortcut"], + ) + + if value["roles"]: + filter = filter & Q(originating_role=value["roles"].split(",")) + context["person_list"] = ( - DistrictOctopusPersonPage.objects.filter( - originating_team=value["team_shortcut"] - ) + DistrictOctopusPersonPage.objects.filter(filter) .order_by("title") .all() ) diff --git a/district/management/commands/octopus_people_import.py b/district/management/commands/octopus_people_import.py index 1398d5adbccf0accd6a7facba7803ffa9d998c4b..3f98cbd375244e4bf07087185a577eb1b0057eda 100644 --- a/district/management/commands/octopus_people_import.py +++ b/district/management/commands/octopus_people_import.py @@ -39,6 +39,7 @@ class Command(BaseCommand): collection_id, team["shortcut"], team["title"], + team["roles"] ) for person_page in DistrictManualOctopusPersonPage.objects.all(): diff --git a/district/migrations/0297_alter_districtpeoplepage_content.py b/district/migrations/0297_alter_districtpeoplepage_content.py new file mode 100644 index 0000000000000000000000000000000000000000..c3d9c56a43249768bc7c9104afe844708db176b5 --- /dev/null +++ b/district/migrations/0297_alter_districtpeoplepage_content.py @@ -0,0 +1,21 @@ +# Generated by Django 5.0.7 on 2024-10-09 18:21 + +import wagtail.blocks +import wagtail.fields +import wagtail.images.blocks +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('district', '0296_alter_districtmanualoctopuspersonpage_person'), + ] + + operations = [ + migrations.AlterField( + model_name='districtpeoplepage', + name='content', + field=wagtail.fields.StreamField([('octopus_group', wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(label='Titulek', required=True)), ('slug', wagtail.blocks.CharBlock(help_text='Není třeba vyplňovat, bude automaticky vyplněno', label='Slug bloku', required=False)), ('group_shortcut', wagtail.blocks.CharBlock(help_text='Např. cen_to_ved', label='Zkratka skupiny', required=True))], label='Skupina z Chobotnice')), ('octopus_team', wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(label='Titulek', required=True)), ('slug', wagtail.blocks.CharBlock(help_text='Není třeba vyplňovat, bude automaticky vyplněno', label='Slug bloku', required=False)), ('team_shortcut', wagtail.blocks.CharBlock(help_text='Např. TO-admin', label='Zkratka týmu', required=True)), ('roles', wagtail.blocks.CharBlock(help_text='Pokud chceš zobrazit pouze osoby se specifickými rolemi v tomto týmu, můžeš role zadat zde ve formátu <em>role1,role2,role3</em>.', label='Role', required=True))], label='Tým z Chobotnice')), ('people_group', wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(label='Titulek')), ('slug', wagtail.blocks.CharBlock(help_text='Není třeba vyplňovat, bude automaticky vyplněno', label='Slug skupiny', required=False)), ('person_list', wagtail.blocks.ListBlock(wagtail.blocks.PageChooserBlock(label='Detail osoby', page_type=['district.DistrictPersonPage', 'district.DistrictOctopusPersonPage', 'district.DistrictManualOctopusPersonPage']), default=[], help_text='S pozicemi z jejich podstránek', label='Osoby')), ('person_list_with_custom_positions', wagtail.blocks.ListBlock(wagtail.blocks.StructBlock([('page', wagtail.blocks.PageChooserBlock(label='Detail osoby', page_type=['district.DistrictOctopusPersonPage', 'district.DistrictManualOctopusPersonPage', 'district.DistrictPersonPage'])), ('position', wagtail.blocks.CharBlock(help_text='Pokud není pozice vyplněná, použije se pozice ze stránky osoby.', label='Pozice', required=False))]), default=[], help_text='S nastavitelnými pozicemi', label='Osoby'))], group='', label='Seznam osob')), ('team_group', wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(label='Název sekce týmů')), ('slug', wagtail.blocks.CharBlock(help_text='Není třeba vyplňovat, bude automaticky vyplněno', label='Slug sekce', required=False)), ('team_list', wagtail.blocks.ListBlock(wagtail.blocks.StructBlock([('headline', wagtail.blocks.CharBlock(label='Titulek bloku', required=False)), ('card_items', wagtail.blocks.ListBlock(wagtail.blocks.StructBlock([('image', wagtail.images.blocks.ImageChooserBlock(label='Obrázek')), ('title', wagtail.blocks.CharBlock(label='Titulek', required=True)), ('text', wagtail.blocks.RichTextBlock(label='Krátký text pod nadpisem', required=False)), ('page', wagtail.blocks.PageChooserBlock(label='Stránka', page_type=['district.DistrictArticlesPage', 'district.DistrictCenterPage', 'district.DistrictContactPage', 'district.DistrictCrossroadPage', 'district.DistrictCustomPage', 'district.DistrictPeoplePage', 'district.DistrictGeoFeatureCollectionPage', 'district.DistrictCalendarPage', 'district.DistrictPdfPage', 'district.DistrictNewProgramPage'], required=False)), ('link', wagtail.blocks.URLBlock(label='Odkaz', required=False))], template='styleguide2/includes/molecules/boxes/card_box_block.html'), label='Karty s odkazy'))], label='Karta týmu'), label='Týmy'))]))], blank=True, verbose_name='Lidé a týmy'), + ), + ] diff --git a/district/migrations/0298_districtoctopuspersonpage_originating_role_and_more.py b/district/migrations/0298_districtoctopuspersonpage_originating_role_and_more.py new file mode 100644 index 0000000000000000000000000000000000000000..05e2d56df84c64c026953a071c8abf7faf5d84c8 --- /dev/null +++ b/district/migrations/0298_districtoctopuspersonpage_originating_role_and_more.py @@ -0,0 +1,26 @@ +# Generated by Django 5.0.7 on 2024-10-09 18:54 + +import wagtail.blocks +import wagtail.fields +import wagtail.images.blocks +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('district', '0297_alter_districtpeoplepage_content'), + ] + + operations = [ + migrations.AddField( + model_name='districtoctopuspersonpage', + name='originating_role', + field=models.CharField(blank=True, help_text='Požadovaná role v týmu, ze kterého byla tato osba importována.', max_length=128, null=True, verbose_name='Role'), + ), + migrations.AlterField( + model_name='districtpeoplepage', + name='content', + field=wagtail.fields.StreamField([('octopus_group', wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(label='Titulek', required=True)), ('slug', wagtail.blocks.CharBlock(help_text='Není třeba vyplňovat, bude automaticky vyplněno', label='Slug bloku', required=False)), ('group_shortcut', wagtail.blocks.CharBlock(help_text='Např. cen_to_ved', label='Zkratka skupiny', required=True))], label='Skupina z Chobotnice')), ('octopus_team', wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(label='Titulek', required=True)), ('slug', wagtail.blocks.CharBlock(help_text='Není třeba vyplňovat, bude automaticky vyplněno', label='Slug bloku', required=False)), ('team_shortcut', wagtail.blocks.CharBlock(help_text='Např. TO-admin', label='Zkratka týmu', required=True)), ('roles', wagtail.blocks.CharBlock(help_text='Pokud chceš zobrazit pouze osoby se specifickými rolemi v tomto týmu, můžeš role zadat zde ve formátu <em>role1,role2,role3</em>.', label='Role', required=False))], label='Tým z Chobotnice')), ('people_group', wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(label='Titulek')), ('slug', wagtail.blocks.CharBlock(help_text='Není třeba vyplňovat, bude automaticky vyplněno', label='Slug skupiny', required=False)), ('person_list', wagtail.blocks.ListBlock(wagtail.blocks.PageChooserBlock(label='Detail osoby', page_type=['district.DistrictPersonPage', 'district.DistrictOctopusPersonPage', 'district.DistrictManualOctopusPersonPage']), default=[], help_text='S pozicemi z jejich podstránek', label='Osoby')), ('person_list_with_custom_positions', wagtail.blocks.ListBlock(wagtail.blocks.StructBlock([('page', wagtail.blocks.PageChooserBlock(label='Detail osoby', page_type=['district.DistrictOctopusPersonPage', 'district.DistrictManualOctopusPersonPage', 'district.DistrictPersonPage'])), ('position', wagtail.blocks.CharBlock(help_text='Pokud není pozice vyplněná, použije se pozice ze stránky osoby.', label='Pozice', required=False))]), default=[], help_text='S nastavitelnými pozicemi', label='Osoby'))], group='', label='Seznam osob')), ('team_group', wagtail.blocks.StructBlock([('title', wagtail.blocks.CharBlock(label='Název sekce týmů')), ('slug', wagtail.blocks.CharBlock(help_text='Není třeba vyplňovat, bude automaticky vyplněno', label='Slug sekce', required=False)), ('team_list', wagtail.blocks.ListBlock(wagtail.blocks.StructBlock([('headline', wagtail.blocks.CharBlock(label='Titulek bloku', required=False)), ('card_items', wagtail.blocks.ListBlock(wagtail.blocks.StructBlock([('image', wagtail.images.blocks.ImageChooserBlock(label='Obrázek')), ('title', wagtail.blocks.CharBlock(label='Titulek', required=True)), ('text', wagtail.blocks.RichTextBlock(label='Krátký text pod nadpisem', required=False)), ('page', wagtail.blocks.PageChooserBlock(label='Stránka', page_type=['district.DistrictArticlesPage', 'district.DistrictCenterPage', 'district.DistrictContactPage', 'district.DistrictCrossroadPage', 'district.DistrictCustomPage', 'district.DistrictPeoplePage', 'district.DistrictGeoFeatureCollectionPage', 'district.DistrictCalendarPage', 'district.DistrictPdfPage', 'district.DistrictNewProgramPage'], required=False)), ('link', wagtail.blocks.URLBlock(label='Odkaz', required=False))], template='styleguide2/includes/molecules/boxes/card_box_block.html'), label='Karty s odkazy'))], label='Karta týmu'), label='Týmy'))]))], blank=True, verbose_name='Lidé a týmy'), + ), + ] diff --git a/district/models.py b/district/models.py index d51f2fdea000e14bb76f0a50956a6f241238676c..9c393dfa6c361e006ebe25cefd2be23a26f606c3 100644 --- a/district/models.py +++ b/district/models.py @@ -542,6 +542,14 @@ class DistrictOctopusPersonPage( null=True, ) + originating_role = models.CharField( + verbose_name="Role", + help_text="Požadovaná role v týmu, ze kterého byla tato osba importována.", + max_length=128, + blank=True, + null=True, + ) + originating_display = models.CharField( verbose_name="Název týmu/skupiny", help_text="Název týmu nebo skupiny, ze kterých byla tato osba importována.", @@ -758,6 +766,7 @@ class DistrictPeoplePage(MainPeoplePageMixin): teams.append( { "shortcut": block.value["team_shortcut"], + "roles": block.value["roles"], "title": block.value["title"], } ) @@ -765,6 +774,12 @@ class DistrictPeoplePage(MainPeoplePageMixin): # Remove duplicates by converting to a set of tuples and back to a list of dicts unique_teams = [dict(t) for t in {tuple(team.items()) for team in teams}] + # Since lists can't be hashed and our unique-ification function won't work + # with them around, convert roles to lists only after we know the teams + # are unique. + for position, team in enumerate(unique_teams): + unique_teams[position]["roles"] = team["roles"].split(",") + return unique_teams diff --git a/district/tasks.py b/district/tasks.py index d57c02a5a120ab50156381e4c0e8aadb10d53d12..992bcdd96e17b873be0696fb19544c19e7109996 100644 --- a/district/tasks.py +++ b/district/tasks.py @@ -64,12 +64,13 @@ def import_people_from_team( collection_id, team_shortcut, team_display, + team_roles, ): from .models import DistrictOctopusPersonPage, DistrictPeoplePage lock_file_name = os.path.join( tempfile.gettempdir(), - f"{people_parent_page_id}-{team_shortcut}.people-from-team-import-lock", + f"{people_parent_page_id}-{team_shortcut}-{','.join(team_roles)}.people-from-team-import-lock", ) if os.path.isfile(lock_file_name): @@ -84,6 +85,7 @@ def import_people_from_team( collection_id=collection_id, team_shortcut=team_shortcut, team_display=team_display, + team_roles=team_roles, lock_file_name=lock_file_name, ).perform_import() diff --git a/district/templatetags/district_people_filters.py b/district/templatetags/district_people_filters.py index 48ad0dbb5a0bb72332eb070e969ff0c76aeb4834..a030110ef8ec4346192e5fb0c0f57afc610d764c 100644 --- a/district/templatetags/district_people_filters.py +++ b/district/templatetags/district_people_filters.py @@ -11,7 +11,17 @@ def get_block_octopus_person_list(block): filter = ( models.Q(originating_group=block.value["group_shortcut"]) if "group_shortcut" in block.value - else models.Q(originating_team=block.value["team_shortcut"]) + else ( + models.Q( + originating_team=block.value["team_shortcut"], + originating_role__in=block.value["roles"].split(",") + ) + if block.value["roles"] + else models.Q(originating_team=block.value["team_shortcut"]) + ) ) - return DistrictOctopusPersonPage.objects.filter(filter).order_by("title").all() + for page in DistrictOctopusPersonPage.objects.filter(models.Q(originating_team=block.value["team_shortcut"])).order_by("title").distinct("title").all(): + print(page.originating_team) + + return DistrictOctopusPersonPage.objects.filter(filter).order_by("title").distinct("title").all() diff --git a/shared/people_import.py b/shared/people_import.py index 5895393efc692583f997c8a9f49bb0243c85ec0a..664fce91603035c2a25acb01cbce95ab375b5ff4 100644 --- a/shared/people_import.py +++ b/shared/people_import.py @@ -389,6 +389,7 @@ class PeopleTeamImporter(ImporterMixin): collection_id, team_shortcut, team_display, + team_roles, lock_file_name, ): try: @@ -398,6 +399,7 @@ class PeopleTeamImporter(ImporterMixin): self.collection_id = collection_id self.team_shortcut = team_shortcut self.team_display = team_display + self.team_roles = team_roles self.lock_file_name = lock_file_name self.new_user_count = 0 @@ -448,6 +450,11 @@ class PeopleTeamImporter(ImporterMixin): for node in result["allTeams"]["edges"]: for membership in node["node"]["memberships"]: + # Can't do this in the query (yet), so just filter here + + if len(self.team_roles) != 0 and membership["roleDisplay"] not in self.team_roles: + continue + users.append( { "id": membership["person"]["id"], @@ -519,20 +526,33 @@ class PeopleTeamImporter(ImporterMixin): title=person_instance.display_name, ) + if len(self.team_roles) != 0: + person_page.originating_role = person_instance.position + self.people_parent_page.add_child(instance=person_page) person_page.save_revision().publish() else: person_page.originating_display = self.team_display + + if len(self.team_roles) != 0: + person_page.originating_role = person_instance.position + person_page.save_revision().publish() # Delete old pages that correspond to profiles which aren't # part of the group we are importing anymore. - self.person_page_model.objects.filter( + + filter = models.Q( ~models.Q(person__in=people_instances), originating_team=self.team_shortcut, is_automatically_created=True, - ).descendant_of(self.people_parent_page).delete() + ) + + if len(self.team_roles) != 0: + filter = filter & models.Q(originating_role__in=self.team_roles) + + self.person_page_model.objects.filter(filter).descendant_of(self.people_parent_page).delete() finally: # No matter what happens, at least remove the lockfile.