Skip to content
Snippets Groups Projects
Commit 1ea3a065 authored by Roang's avatar Roang
Browse files

Remove channel functionality

- Remove channel functionality
  - Remove channel_team
  - Remove channel from assembly
- Rename state_assembly to state
- Remove NONE state for assemblies
- Simplify form permissions
  - Remove staff_access and assembly_staff_access
  - All checks now use staff_mode
- Fix type in conference_admin permission description
parent d3af0bfa
No related branches found
No related tags found
No related merge requests found
Showing
with 156 additions and 255 deletions
...@@ -227,7 +227,7 @@ class ScheduleEncoder(json.JSONEncoder): ...@@ -227,7 +227,7 @@ class ScheduleEncoder(json.JSONEncoder):
'name': obj.name, 'name': obj.name,
'slug': obj.slug, 'slug': obj.slug,
'guid': obj.id, 'guid': obj.id,
# Future TODO: # 'type': obj., # channel vs. cluster vs. virtual vs. ...? # Future TODO: # 'type': obj., # cluster vs. virtual vs. ...?
# 'description_en': obj.description_en, # 'description_en': obj.description_en,
# 'description_de': obj.description_de, # 'description_de': obj.description_de,
# Future TODO 'url': obj.get_absolute_url(), # Future TODO 'url': obj.get_absolute_url(),
......
...@@ -147,8 +147,7 @@ class AssemblySerializer(HubModelSerializer): ...@@ -147,8 +147,7 @@ class AssemblySerializer(HubModelSerializer):
'slug', 'slug',
'id', 'id',
'name', 'name',
'state_assembly', 'state',
'state_channel',
'hierarchy', 'hierarchy',
'parent', 'parent',
'assembly_location', 'assembly_location',
...@@ -158,7 +157,7 @@ class AssemblySerializer(HubModelSerializer): ...@@ -158,7 +157,7 @@ class AssemblySerializer(HubModelSerializer):
'rooms_url', 'rooms_url',
'badges_url', 'badges_url',
] ]
staff_only_fields = ['state_assembly', 'state_channel', 'hierarchy'] staff_only_fields = ['state', 'hierarchy']
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
......
...@@ -26,7 +26,7 @@ class CreateRedeemTokenTests(TestCase): ...@@ -26,7 +26,7 @@ class CreateRedeemTokenTests(TestCase):
end=datetime(2020, 12, 30, 23, 45, 00, tzinfo=tz), end=datetime(2020, 12, 30, 23, 45, 00, tzinfo=tz),
) )
self.conf.save() self.conf.save()
self.assembly = Assembly(name='TestAssembly', slug='asmbly', conference=self.conf, state_assembly=Assembly.State.PLACED) self.assembly = Assembly(name='TestAssembly', slug='asmbly', conference=self.conf, state=Assembly.State.PLACED)
self.assembly.save() self.assembly.save()
self.badge = Badge( self.badge = Badge(
......
...@@ -22,7 +22,7 @@ class EventsTestCase(TestCase): ...@@ -22,7 +22,7 @@ class EventsTestCase(TestCase):
self.human_cm = ConferenceMember(conference=self.conference1, user=self.human_user) self.human_cm = ConferenceMember(conference=self.conference1, user=self.human_user)
self.human_cm.save() self.human_cm.save()
assembly = Assembly(conference=self.conference1, name='DUMMY', slug='dummy', state_assembly=Assembly.State.ACCEPTED, is_official=True) assembly = Assembly(conference=self.conference1, name='DUMMY', slug='dummy', state=Assembly.State.ACCEPTED, is_official=True)
assembly.save() assembly.save()
self.event = Event( self.event = Event(
......
...@@ -50,7 +50,7 @@ class MapTest(TestCase): ...@@ -50,7 +50,7 @@ class MapTest(TestCase):
# set POI on assembly and accept it # set POI on assembly and accept it
self.assembly.location_point = Point(8.9, 52.9) self.assembly.location_point = Point(8.9, 52.9)
self.assembly.state_assembly = Assembly.State.ACCEPTED self.assembly.state = Assembly.State.ACCEPTED
self.assembly.save() self.assembly.save()
ConferenceExportCache.objects.all().delete() ConferenceExportCache.objects.all().delete()
...@@ -61,7 +61,7 @@ class MapTest(TestCase): ...@@ -61,7 +61,7 @@ class MapTest(TestCase):
self.assertEqual(0, len(content['features'])) self.assertEqual(0, len(content['features']))
# change state to 'placed', now there should be a POI # change state to 'placed', now there should be a POI
self.assembly.state_assembly = Assembly.State.PLACED self.assembly.state = Assembly.State.PLACED
self.assembly.save() self.assembly.save()
ConferenceExportCache.objects.all().delete() ConferenceExportCache.objects.all().delete()
resp = self.client.get(url) resp = self.client.get(url)
...@@ -78,7 +78,7 @@ class MapTest(TestCase): ...@@ -78,7 +78,7 @@ class MapTest(TestCase):
self.assertEqual(self.assembly.is_cluster, feature.get('properties', {}).get('cluster')) self.assertEqual(self.assembly.is_cluster, feature.get('properties', {}).get('cluster'))
# change assembly to 'hidden', POI should still be there # change assembly to 'hidden', POI should still be there
self.assembly.state_assembly = Assembly.State.HIDDEN self.assembly.state = Assembly.State.HIDDEN
self.assembly.save() self.assembly.save()
ConferenceExportCache.objects.all().delete() ConferenceExportCache.objects.all().delete()
resp = self.client.get(url) resp = self.client.get(url)
......
...@@ -32,7 +32,7 @@ class MetricsTest(TestCase): ...@@ -32,7 +32,7 @@ class MetricsTest(TestCase):
assembly = Assembly( assembly = Assembly(
name='TestAssembly', name='TestAssembly',
slug='asmbly', slug='asmbly',
state_assembly=Assembly.State('planned'), state=Assembly.State('planned'),
conference=conf, conference=conf,
) )
assembly.save() assembly.save()
......
...@@ -202,7 +202,7 @@ class AssemblyPermissionTestCase(ConferencePermissionTestCase): ...@@ -202,7 +202,7 @@ class AssemblyPermissionTestCase(ConferencePermissionTestCase):
self.assembly = self.view.assembly = Assembly.objects.create( self.assembly = self.view.assembly = Assembly.objects.create(
name='TestAssembly', name='TestAssembly',
slug='asmbly', slug='asmbly',
state_assembly=Assembly.State('planned'), state=Assembly.State('planned'),
conference=self.conference, conference=self.conference,
) )
...@@ -235,7 +235,7 @@ class IsPublicAssemblyReadOnlyTestCase(AssemblyPermissionTestCase): ...@@ -235,7 +235,7 @@ class IsPublicAssemblyReadOnlyTestCase(AssemblyPermissionTestCase):
def test_get_allowed_public(self): def test_get_allowed_public(self):
request = self.factory.get('/') request = self.factory.get('/')
self.assembly.state_assembly = Assembly.PUBLIC_STATES[0] self.assembly.state = Assembly.PUBLIC_STATES[0]
self.assembly.save() self.assembly.save()
self.run_permission_test(IsPublicAssemblyReadOnly(), (True, True), request) self.run_permission_test(IsPublicAssemblyReadOnly(), (True, True), request)
......
...@@ -30,7 +30,7 @@ class ScheduleTest(TestCase): ...@@ -30,7 +30,7 @@ class ScheduleTest(TestCase):
self.conf.save() self.conf.save()
self.conf.tracks.create(slug='community', name='Community').save() self.conf.tracks.create(slug='community', name='Community').save()
self.conf.tracks.create(slug='security', name='Security').save() self.conf.tracks.create(slug='security', name='Security').save()
self.assembly = Assembly(name='TestAssembly', slug='asmbly', conference=self.conf, state_assembly=Assembly.State.PLACED) self.assembly = Assembly(name='TestAssembly', slug='asmbly', conference=self.conf, state=Assembly.State.PLACED)
self.assembly.save() self.assembly.save()
self.room = Room(conference=self.conf, assembly=self.assembly, name='Foo Room', room_type=Room.RoomType.STAGE) self.room = Room(conference=self.conf, assembly=self.assembly, name='Foo Room', room_type=Room.RoomType.STAGE)
self.room.save() self.room.save()
...@@ -52,7 +52,7 @@ class ScheduleTest(TestCase): ...@@ -52,7 +52,7 @@ class ScheduleTest(TestCase):
content_parser(content_str) content_parser(content_str)
# prepare assembly for event-hosting, incl. room # prepare assembly for event-hosting, incl. room
self.assembly.state_channel = Assembly.State.ACCEPTED self.assembly.state = Assembly.State.ACCEPTED
self.assembly.save() self.assembly.save()
r = self.assembly.rooms.create(conference=self.conf, name='Zelt', room_type='stage') r = self.assembly.rooms.create(conference=self.conf, name='Zelt', room_type='stage')
......
...@@ -94,9 +94,9 @@ class WorkAdventureMapServiceTestCase(_WorkAdventureTestCase): ...@@ -94,9 +94,9 @@ class WorkAdventureMapServiceTestCase(_WorkAdventureTestCase):
endpoint_data = response.json() endpoint_data = response.json()
self.assertEqual(0, len(endpoint_data)) self.assertEqual(0, len(endpoint_data))
self.assembly1a.state_assembly = Assembly.State.ACCEPTED self.assembly1a.state = Assembly.State.ACCEPTED
self.assembly1a.save() self.assembly1a.save()
self.assembly1b.state_assembly = Assembly.State.PLACED self.assembly1b.state = Assembly.State.PLACED
self.assembly1b.save() self.assembly1b.save()
response = c.get(self.wa_url) response = c.get(self.wa_url)
...@@ -114,15 +114,15 @@ class WorkAdventureMapServiceTestCase(_WorkAdventureTestCase): ...@@ -114,15 +114,15 @@ class WorkAdventureMapServiceTestCase(_WorkAdventureTestCase):
def testPush(self): def testPush(self):
# prepare assembly objects # prepare assembly objects
self.assembly1a.state_assembly = Assembly.State.ACCEPTED self.assembly1a.state = Assembly.State.ACCEPTED
self.assembly1a.save(update_fields=['state_assembly']) self.assembly1a.save(update_fields=['state'])
assembly2 = Assembly(conference=self.conference1, slug='dummy2', name='Test Dummy 2', state_assembly=Assembly.State.ACCEPTED) assembly2 = Assembly(conference=self.conference1, slug='dummy2', name='Test Dummy 2', state=Assembly.State.ACCEPTED)
assembly2.save() assembly2.save()
assembly3 = Assembly(conference=self.conference1, slug='dummy3', name='Test Dummy 3', state_assembly=Assembly.State.ACCEPTED) assembly3 = Assembly(conference=self.conference1, slug='dummy3', name='Test Dummy 3', state=Assembly.State.ACCEPTED)
assembly3.save() assembly3.save()
assembly4 = Assembly(conference=self.conference1, slug='dummy4', name='Test Dummy 4', state_assembly=Assembly.State.ACCEPTED) assembly4 = Assembly(conference=self.conference1, slug='dummy4', name='Test Dummy 4', state=Assembly.State.ACCEPTED)
assembly4.save() assembly4.save()
assembly5 = Assembly(conference=self.conference1, slug='dummy5', name='Test Dummy 5', state_assembly=Assembly.State.ACCEPTED) assembly5 = Assembly(conference=self.conference1, slug='dummy5', name='Test Dummy 5', state=Assembly.State.ACCEPTED)
assembly5.save() assembly5.save()
# prepare room objects # prepare room objects
...@@ -227,9 +227,9 @@ class WorkAdventureEndpointTestCase: # TODO: enable again -- _WorkAdventureTest ...@@ -227,9 +227,9 @@ class WorkAdventureEndpointTestCase: # TODO: enable again -- _WorkAdventureTest
response = c.get(url_a) response = c.get(url_a)
self.assertEqual(response.status_code, 404, f'Expected to have WA endpoint return HTTP 404 instead of {response.status_code}.') self.assertEqual(response.status_code, 404, f'Expected to have WA endpoint return HTTP 404 instead of {response.status_code}.')
self.assembly1a.state_assembly = Assembly.State.ACCEPTED self.assembly1a.state = Assembly.State.ACCEPTED
self.assembly1a.save() self.assembly1a.save()
self.assembly1b.state_assembly = Assembly.State.PLACED self.assembly1b.state = Assembly.State.PLACED
self.assembly1b.save() self.assembly1b.save()
endpoint_data = [] endpoint_data = []
...@@ -252,7 +252,7 @@ class WorkAdventureEndpointTestCase: # TODO: enable again -- _WorkAdventureTest ...@@ -252,7 +252,7 @@ class WorkAdventureEndpointTestCase: # TODO: enable again -- _WorkAdventureTest
def testPush(self): def testPush(self):
# prepare assembly and room # prepare assembly and room
self.assembly1c.refresh_from_db() self.assembly1c.refresh_from_db()
self.assembly1c.state_assembly = Assembly.State.ACCEPTED self.assembly1c.state = Assembly.State.ACCEPTED
self.assembly1c.save() self.assembly1c.save()
self.room1c.refresh_from_db() self.room1c.refresh_from_db()
......
...@@ -71,7 +71,7 @@ class AssembliesExportView(ConferenceSlugMixin, APIView, metaclass=abc.ABCMeta): ...@@ -71,7 +71,7 @@ class AssembliesExportView(ConferenceSlugMixin, APIView, metaclass=abc.ABCMeta):
def get_queryset(self): def get_queryset(self):
exportable_states = [*Assembly.PLACED_STATES, Assembly.State.HIDDEN] exportable_states = [*Assembly.PLACED_STATES, Assembly.State.HIDDEN]
return Assembly.objects.filter(conference=self.conference, state_assembly__in=exportable_states) return Assembly.objects.filter(conference=self.conference, state__in=exportable_states)
def get_geometry_field(self, obj): def get_geometry_field(self, obj):
return getattr(obj, self.geometry_field) return getattr(obj, self.geometry_field)
...@@ -138,7 +138,7 @@ class C3NavExportView(ConferenceSlugMixin, APIView): ...@@ -138,7 +138,7 @@ class C3NavExportView(ConferenceSlugMixin, APIView):
data = [] data = []
exportable_states = [*Assembly.PLACED_STATES, Assembly.State.HIDDEN] exportable_states = [*Assembly.PLACED_STATES, Assembly.State.HIDDEN]
qs = self.conference.assemblies.filter(state_assembly__in=exportable_states) qs = self.conference.assemblies.filter(state__in=exportable_states)
if request.GET.get('all') != '1': if request.GET.get('all') != '1':
qs = qs.exclude(location_data__point=None, location_data__boundaries=None) qs = qs.exclude(location_data__point=None, location_data__boundaries=None)
for assembly in qs: # type: Assembly for assembly in qs: # type: Assembly
...@@ -153,7 +153,7 @@ class C3NavExportView(ConferenceSlugMixin, APIView): ...@@ -153,7 +153,7 @@ class C3NavExportView(ConferenceSlugMixin, APIView):
'description': {'de': assembly.description_de, 'en': assembly.description_en}, 'description': {'de': assembly.description_de, 'en': assembly.description_en},
'public_url': hub_absolute('plainui:assembly', assembly_slug=assembly.slug), 'public_url': hub_absolute('plainui:assembly', assembly_slug=assembly.slug),
'parent_id': assembly.parent_id, 'parent_id': assembly.parent_id,
'children': assembly.children.filter(state_assembly__in=exportable_states).values_list('slug', flat=True) if assembly.is_cluster else None, 'children': assembly.children.filter(state__in=exportable_states).values_list('slug', flat=True) if assembly.is_cluster else None,
'floor': assembly.get_location_floor_index(), 'floor': assembly.get_location_floor_index(),
'location': loc_data.get('point'), # assembly.get_location_point_xy(), 'location': loc_data.get('point'), # assembly.get_location_point_xy(),
'polygons': loc_data.get('boundaries'), # assembly.get_location_boundaries_xy(), 'polygons': loc_data.get('boundaries'), # assembly.get_location_boundaries_xy(),
......
...@@ -49,7 +49,6 @@ class MetricsView(TemplateView): ...@@ -49,7 +49,6 @@ class MetricsView(TemplateView):
'hub_conference_members_themes': {'help': 'used themes by members in the conference', 'type': 'gauge', 'values': {}}, 'hub_conference_members_themes': {'help': 'used themes by members in the conference', 'type': 'gauge', 'values': {}},
'hub_conference_tickets': {'help': 'registered tickets', 'type': 'counter', 'values': {}}, 'hub_conference_tickets': {'help': 'registered tickets', 'type': 'counter', 'values': {}},
'hub_conference_assemblies': {'help': "conference's assemblies", 'type': 'gauge', 'values': {}}, 'hub_conference_assemblies': {'help': "conference's assemblies", 'type': 'gauge', 'values': {}},
'hub_conference_channels': {'help': "conference's channels", 'type': 'gauge', 'values': {}},
'hub_conference_badges_public': {'help': "conference's badges (public)", 'type': 'gauge', 'values': {}}, 'hub_conference_badges_public': {'help': "conference's badges (public)", 'type': 'gauge', 'values': {}},
'hub_conference_badges_hidden': {'help': "conference's badges (non-public)", 'type': 'gauge', 'values': {}}, 'hub_conference_badges_hidden': {'help': "conference's badges (non-public)", 'type': 'gauge', 'values': {}},
'hub_conference_badges_accepted': {'help': "conference's badges (accepted/assigned)", 'type': 'gauge', 'values': {}}, 'hub_conference_badges_accepted': {'help': "conference's badges (accepted/assigned)", 'type': 'gauge', 'values': {}},
...@@ -64,10 +63,7 @@ class MetricsView(TemplateView): ...@@ -64,10 +63,7 @@ class MetricsView(TemplateView):
slug = conference.slug slug = conference.slug
# hub_conference_assemblies # hub_conference_assemblies
self.report_assembly_metrics(metrics, conference, 'assembly', 'assemblies') self.report_assembly_metrics(metrics, conference, 'assemblies')
# hub_conference_channels
self.report_assembly_metrics(metrics, conference, 'channel', 'channels')
# hub_conference_rooms # hub_conference_rooms
room_counts = {room_type: 0 for room_type in Room.RoomType.values} room_counts = {room_type: 0 for room_type in Room.RoomType.values}
...@@ -145,11 +141,11 @@ class MetricsView(TemplateView): ...@@ -145,11 +141,11 @@ class MetricsView(TemplateView):
return context return context
@staticmethod @staticmethod
def report_assembly_metrics(metrics, conference: Conference, lookup_key: str, report_key: str): def report_assembly_metrics(metrics, conference: Conference, report_key: str):
asm_count = Assembly.objects.filter(conference=conference).values(f'state_{lookup_key}').annotate(count=Count('*')) asm_count = Assembly.objects.filter(conference=conference).values('state').annotate(count=Count('*'))
expected_states = list(Assembly.State.values) expected_states = list(Assembly.State.values)
for line in asm_count: for line in asm_count:
metrics[f'hub_conference_{report_key}']['values'][f'{{conference="{conference.slug}",state="{line["state_" + lookup_key]}"}}'] = line['count'] metrics[f'hub_conference_{report_key}']['values'][f'{{conference="{conference.slug}",state="{line["state"]}"}}'] = line['count']
expected_states.remove(line[f'state_{lookup_key}']) expected_states.remove(line['state'])
for missing in expected_states: for missing in expected_states:
metrics[f'hub_conference_{report_key}']['values'][f'{{conference="{conference.slug}",state="{missing}"}}'] = 0 metrics[f'hub_conference_{report_key}']['values'][f'{{conference="{conference.slug}",state="{missing}"}}'] = 0
...@@ -75,7 +75,7 @@ class MapServiceView(ConferenceSlugMixin, APIView): ...@@ -75,7 +75,7 @@ class MapServiceView(ConferenceSlugMixin, APIView):
def get(self, request, format=None): def get(self, request, format=None):
wa_rooms = [] wa_rooms = []
for room in Room.objects.filter(conference=self.conference, room_type=Room.RoomType.WORKADVENTURE).select_related('assembly'): for room in Room.objects.filter(conference=self.conference, room_type=Room.RoomType.WORKADVENTURE).select_related('assembly'):
if room.assembly is not None and room.assembly.state_assembly not in Assembly.PUBLIC_STATES: if room.assembly is not None and room.assembly.state not in Assembly.PUBLIC_STATES:
continue continue
room_data = _export_room_data(room) room_data = _export_room_data(room)
wa_rooms.append(room_data) wa_rooms.append(room_data)
......
...@@ -61,20 +61,12 @@ class ProfileForm(forms.ModelForm): ...@@ -61,20 +61,12 @@ class ProfileForm(forms.ModelForm):
class AssemblyCreateForm(forms.ModelForm): class AssemblyCreateForm(forms.ModelForm):
class Meta: class Meta:
model = Assembly model = Assembly
fields = ['slug', 'name', 'is_assembly', 'is_channel'] fields = ['slug', 'name']
is_assembly = forms.BooleanField(initial=False, required=False, help_text=_('Assembly__is_assembly__help'), label=_('Assembly__is_assembly'))
is_channel = forms.BooleanField(initial=False, required=False, help_text=_('Assembly__is_channel__help'), label=_('Assembly__is_channel'))
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
self._conference = kwargs.pop('conference') self._conference = kwargs.pop('conference')
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
if not self._conference.support_channels:
self.fields['is_assembly'].disabled = True
self.fields['is_assembly'].initial = True
del self.fields['is_channel']
if self._conference.has_disclaimer('assembly'): if self._conference.has_disclaimer('assembly'):
self.fields['disclaimer'] = forms.BooleanField( self.fields['disclaimer'] = forms.BooleanField(
initial=False, initial=False,
...@@ -88,10 +80,6 @@ class AssemblyCreateForm(forms.ModelForm): ...@@ -88,10 +80,6 @@ class AssemblyCreateForm(forms.ModelForm):
if self._conference.has_disclaimer('assembly') and not self.cleaned_data['disclaimer']: if self._conference.has_disclaimer('assembly') and not self.cleaned_data['disclaimer']:
self.add_error('disclaimer', _('Assembly__disclaimer-needed')) self.add_error('disclaimer', _('Assembly__disclaimer-needed'))
if (not self.cleaned_data['is_assembly']) and (not self.cleaned_data['is_channel']):
self.add_error('is_assembly', _('Assembly__must_be_assembly_or_channel'))
self.add_error('is_channel', _('Assembly__must_be_assembly_or_channel'))
if (slug := self.cleaned_data.get('slug')) and Assembly.objects.filter(conference=self._conference, slug=slug).exists(): if (slug := self.cleaned_data.get('slug')) and Assembly.objects.filter(conference=self._conference, slug=slug).exists():
self.add_error('slug', _('Assembly__slug__alreadyexists')) self.add_error('slug', _('Assembly__slug__alreadyexists'))
...@@ -118,7 +106,7 @@ class AssemblyEditForm(TranslatedFieldsForm): ...@@ -118,7 +106,7 @@ class AssemblyEditForm(TranslatedFieldsForm):
'assembly_location': forms.Textarea(attrs={'rows': 4}), 'assembly_location': forms.Textarea(attrs={'rows': 4}),
} }
def __init__(self, *args, staff_access: bool, staff_mode: bool, assembly_staff_access: bool, channel_staff_access: bool, **kwargs): def __init__(self, *args, staff_mode: bool, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
# configure fields' widget customizations # configure fields' widget customizations
...@@ -127,7 +115,7 @@ class AssemblyEditForm(TranslatedFieldsForm): ...@@ -127,7 +115,7 @@ class AssemblyEditForm(TranslatedFieldsForm):
# configure fields # configure fields
assembly = self.instance assembly = self.instance
conference = self.instance.conference conference = self.instance.conference
if assembly.basedata_readonly and not staff_access: if assembly.basedata_readonly and not staff_mode:
self.fields['name'].disabled = True self.fields['name'].disabled = True
self.fields['slug'].disabled = True self.fields['slug'].disabled = True
self.fields['is_physical'].disabled = True self.fields['is_physical'].disabled = True
...@@ -185,7 +173,7 @@ class AssemblyEditForm(TranslatedFieldsForm): ...@@ -185,7 +173,7 @@ class AssemblyEditForm(TranslatedFieldsForm):
class AssemblyMemberEditForm(forms.ModelForm): class AssemblyMemberEditForm(forms.ModelForm):
class Meta: class Meta:
model = AssemblyMember model = AssemblyMember
fields = ['is_representative', 'can_manage_assembly', 'is_content_coordinator', 'is_production_coordinator', 'is_technical_contact', 'show_public'] fields = ['is_representative', 'can_manage_assembly', 'is_technical_contact', 'show_public']
def clean(self): def clean(self):
# call original .clean() which does some checks already # call original .clean() which does some checks already
...@@ -365,7 +353,7 @@ class EditAssemblyRoomForm(TranslatedFieldsForm): ...@@ -365,7 +353,7 @@ class EditAssemblyRoomForm(TranslatedFieldsForm):
model = Room model = Room
fields = ['name', 'slug', 'description', 'is_public_fahrplan', 'is_official', 'official_room_order', 'capacity'] fields = ['name', 'slug', 'description', 'is_public_fahrplan', 'is_official', 'official_room_order', 'capacity']
def __init__(self, with_capacity=False, channel_staff=False, *args, **kwargs): def __init__(self, with_capacity=False, staff_mode=False, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.fields['slug'].disabled = True self.fields['slug'].disabled = True
if self.instance.room_type in Room.BACKEND_ROOMTYPES: if self.instance.room_type in Room.BACKEND_ROOMTYPES:
...@@ -383,7 +371,7 @@ class EditAssemblyRoomForm(TranslatedFieldsForm): ...@@ -383,7 +371,7 @@ class EditAssemblyRoomForm(TranslatedFieldsForm):
if self.instance.room_type in [Room.RoomType.HANGAR]: if self.instance.room_type in [Room.RoomType.HANGAR]:
self.fields['name'].disabled = True self.fields['name'].disabled = True
if not channel_staff: if not staff_mode:
del self.fields['is_public_fahrplan'] del self.fields['is_public_fahrplan']
del self.fields['is_official'] del self.fields['is_official']
del self.fields['official_room_order'] del self.fields['official_room_order']
...@@ -436,7 +424,7 @@ class EditAssemblyRoomWorkAdventureForm(TranslatedFieldsForm): ...@@ -436,7 +424,7 @@ class EditAssemblyRoomWorkAdventureForm(TranslatedFieldsForm):
model = Room model = Room
fields = ['backend_status', 'backend_link', 'backend_link_branch'] fields = ['backend_status', 'backend_link', 'backend_link_branch']
def __init__(self, with_capacity=False, channel_staff=False, *args, **kwargs): def __init__(self, with_capacity=False, staff_mode=False, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.fields['backend_status'].disabled = True self.fields['backend_status'].disabled = True
self.fields['backend_link'].label = _('Room-workadventure_backend_link') self.fields['backend_link'].label = _('Room-workadventure_backend_link')
...@@ -452,7 +440,7 @@ class EditAssemblyRoomHangarForm(TranslatedFieldsForm): ...@@ -452,7 +440,7 @@ class EditAssemblyRoomHangarForm(TranslatedFieldsForm):
model = Room model = Room
fields = ['backend_status', 'backend_link'] fields = ['backend_status', 'backend_link']
def __init__(self, with_capacity=False, channel_staff=False, *args, **kwargs): def __init__(self, with_capacity=False, staff_mode=False, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.fields['backend_status'].disabled = True self.fields['backend_status'].disabled = True
self.fields['backend_link'].label = _('Room-hangar_backend_link') self.fields['backend_link'].label = _('Room-hangar_backend_link')
......
...@@ -17,24 +17,9 @@ msgstr "" ...@@ -17,24 +17,9 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
msgid "Assembly__is_assembly__help"
msgstr "Ankreuzen, wenn ihr eine Assembly seid - egal ob physisch oder virtuell."
msgid "Assembly__is_assembly"
msgstr "Ich melde eine Assembly an."
msgid "Assembly__is_channel__help"
msgstr "Ankreuzen, wenn ihr ein Channel bzw. eine Bühne seid - sprich Vortragsprogramm bietet welches über Self-organized Sessions hinausgeht (Faustregel: ihr habt Streaming über das bzw. mit dem VOC). Wenn ihr nicht wisst was gemeint ist seid ihr kein Channel."
msgid "Assembly__is_channel"
msgstr "Ich melde einen Channel oder eine Bühne an."
msgid "Assembly__disclaimer-needed" msgid "Assembly__disclaimer-needed"
msgstr "Bitte beachte den Hinweis und bestätige, dass du ihn gelesen und verstanden hast." msgstr "Bitte beachte den Hinweis und bestätige, dass du ihn gelesen und verstanden hast."
msgid "Assembly__must_be_assembly_or_channel"
msgstr "Assembly und/oder Channel - nur \"keines von beiden\" ergibt keinen Sinn."
msgid "Assembly__slug__alreadyexists" msgid "Assembly__slug__alreadyexists"
msgstr "Dieser Kurzname wird bereits von einer anderen Assembly benutzt." msgstr "Dieser Kurzname wird bereits von einer anderen Assembly benutzt."
...@@ -313,11 +298,7 @@ msgid "no" ...@@ -313,11 +298,7 @@ msgid "no"
msgstr "Nein" msgstr "Nein"
# use translation from core # use translation from core
msgid "Assembly__state_assembly" msgid "Assembly__state"
msgstr ""
# use translation from core
msgid "Assembly__state_channel"
msgstr "" msgstr ""
msgid "assemblycreate_title" msgid "assemblycreate_title"
...@@ -344,10 +325,10 @@ msgstr "Webseite" ...@@ -344,10 +325,10 @@ msgstr "Webseite"
msgid "Assembly__hierarchy" msgid "Assembly__hierarchy"
msgstr "Einordnung" msgstr "Einordnung"
msgid "Assembly__state_assembly-planned__hint" msgid "Assembly__state-planned__hint"
msgstr "Die Registrierung dieser Assembly ist noch nicht abgeschlossen." msgstr "Die Registrierung dieser Assembly ist noch nicht abgeschlossen."
msgid "Assembly__state_assembly-planned__description" msgid "Assembly__state-planned__description"
msgstr "Um die Registrierung dieses Assemblies abzuschließen, füllt bitte die Informationen und restlichen Daten (z.B. Beschreibung) aus." msgstr "Um die Registrierung dieses Assemblies abzuschließen, füllt bitte die Informationen und restlichen Daten (z.B. Beschreibung) aus."
msgid "Assembly__registration_details" msgid "Assembly__registration_details"
...@@ -565,12 +546,6 @@ msgstr "Repräsentant" ...@@ -565,12 +546,6 @@ msgstr "Repräsentant"
msgid "AssemblyMember__can_manage_assembly" msgid "AssemblyMember__can_manage_assembly"
msgstr "kann Assembly verwalten" msgstr "kann Assembly verwalten"
msgid "AssemblyMember__is_content_coordinator"
msgstr "Content-Koordinator"
msgid "AssemblyMember__is_production_coordinator"
msgstr "Produktions-Koordinator"
msgid "AssemblyMember__is_technical_contact" msgid "AssemblyMember__is_technical_contact"
msgstr "technische Ansprechperson" msgstr "technische Ansprechperson"
...@@ -804,9 +779,6 @@ msgstr "Assembly-Team" ...@@ -804,9 +779,6 @@ msgstr "Assembly-Team"
msgid "nav_vouchers" msgid "nav_vouchers"
msgstr "Vouchers" msgstr "Vouchers"
msgid "nav_channels"
msgstr "Channels-Team"
msgid "nav_map" msgid "nav_map"
msgstr "Karte" msgstr "Karte"
...@@ -1744,9 +1716,6 @@ msgstr "abgelehnt" ...@@ -1744,9 +1716,6 @@ msgstr "abgelehnt"
msgid "nav_assemblies_hidden" msgid "nav_assemblies_hidden"
msgstr "versteckt" msgstr "versteckt"
msgid "nav_assemblies_not_selected"
msgstr "keine Teilnahme"
msgid "lists" msgid "lists"
msgstr "Listen" msgstr "Listen"
...@@ -1844,24 +1813,6 @@ msgstr "Badge %(token)s aktiviert" ...@@ -1844,24 +1813,6 @@ msgstr "Badge %(token)s aktiviert"
msgid "BadgeToken__deactivated %(token)s" msgid "BadgeToken__deactivated %(token)s"
msgstr "Badge %(token)s deaktiviert" msgstr "Badge %(token)s deaktiviert"
msgid "nav_channels_all"
msgstr "alle"
msgid "nav_channels_accepted"
msgstr "akzeptiert"
msgid "nav_channels_pending"
msgstr "wartend"
msgid "nav_channels_planned"
msgstr "geplant"
msgid "nav_channels_rejected"
msgstr "abgelehnt"
msgid "nav_channels_hidden"
msgstr "versteckt"
msgid "nav_conference" msgid "nav_conference"
msgstr "Konferenz" msgstr "Konferenz"
......
...@@ -17,24 +17,9 @@ msgstr "" ...@@ -17,24 +17,9 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
msgid "Assembly__is_assembly__help"
msgstr "Tick this if you are an assembly - no matter whether physical or virtual."
msgid "Assembly__is_assembly"
msgstr "I'm registering an assembly."
msgid "Assembly__is_channel__help"
msgstr "Tick this if you are a channel or stage, i.e. you are doing events apart from self-organized sessions (rule of thumb: you do streaming via/with the VOC). If you don't know what we're talking about don't tick this box."
msgid "Assembly__is_channel"
msgstr "I'm registering a channel or stage."
msgid "Assembly__disclaimer-needed" msgid "Assembly__disclaimer-needed"
msgstr "Please read the disclaimer and acknowledge that you have understood and will adhere to it." msgstr "Please read the disclaimer and acknowledge that you have understood and will adhere to it."
msgid "Assembly__must_be_assembly_or_channel"
msgstr "Assembly and/or channel - only neither of both doesn't make any sense."
msgid "Assembly__slug__alreadyexists" msgid "Assembly__slug__alreadyexists"
msgstr "This slug is already used by another assembly." msgstr "This slug is already used by another assembly."
...@@ -312,14 +297,11 @@ msgstr "Yes" ...@@ -312,14 +297,11 @@ msgstr "Yes"
msgid "no" msgid "no"
msgstr "No" msgstr "No"
msgid "Assembly__state_assembly" msgid "Assembly__state"
msgstr "assembly" msgstr "assembly"
msgid "Assembly__state_channel"
msgstr "channel"
msgid "assemblycreate_title" msgid "assemblycreate_title"
msgstr "details of the new assembly/channel/stage" msgstr "details of the new assembly/stage"
msgid "Assembly__registration__closed" msgid "Assembly__registration__closed"
msgstr "New assembly registrations for this conference are no longer possible." msgstr "New assembly registrations for this conference are no longer possible."
...@@ -342,10 +324,10 @@ msgstr "website" ...@@ -342,10 +324,10 @@ msgstr "website"
msgid "Assembly__hierarchy" msgid "Assembly__hierarchy"
msgstr "hierarchy" msgstr "hierarchy"
msgid "Assembly__state_assembly-planned__hint" msgid "Assembly__state-planned__hint"
msgstr "This assembly's registration has not been completed." msgstr "This assembly's registration has not been completed."
msgid "Assembly__state_assembly-planned__description" msgid "Assembly__state-planned__description"
msgstr "To complete the registration of this assembly, please fill in the information and remaining data (e.g. description)." msgstr "To complete the registration of this assembly, please fill in the information and remaining data (e.g. description)."
msgid "Assembly__registration_details" msgid "Assembly__registration_details"
...@@ -564,12 +546,6 @@ msgstr "representative" ...@@ -564,12 +546,6 @@ msgstr "representative"
msgid "AssemblyMember__can_manage_assembly" msgid "AssemblyMember__can_manage_assembly"
msgstr "can manage assembly" msgstr "can manage assembly"
msgid "AssemblyMember__is_content_coordinator"
msgstr "content coordinator"
msgid "AssemblyMember__is_production_coordinator"
msgstr "production coordinator"
msgid "AssemblyMember__is_technical_contact" msgid "AssemblyMember__is_technical_contact"
msgstr "technical contact" msgstr "technical contact"
...@@ -803,9 +779,6 @@ msgstr "assemblies team" ...@@ -803,9 +779,6 @@ msgstr "assemblies team"
msgid "nav_vouchers" msgid "nav_vouchers"
msgstr "Vouchers" msgstr "Vouchers"
msgid "nav_channels"
msgstr "channels team"
msgid "nav_map" msgid "nav_map"
msgstr "map" msgstr "map"
...@@ -1749,9 +1722,6 @@ msgstr "rejected" ...@@ -1749,9 +1722,6 @@ msgstr "rejected"
msgid "nav_assemblies_hidden" msgid "nav_assemblies_hidden"
msgstr "hidden" msgstr "hidden"
msgid "nav_assemblies_not_selected"
msgstr "no participation"
msgid "lists" msgid "lists"
msgstr "lists" msgstr "lists"
...@@ -1848,24 +1818,6 @@ msgstr "Redeem token '%(token)s' activated." ...@@ -1848,24 +1818,6 @@ msgstr "Redeem token '%(token)s' activated."
msgid "BadgeToken__deactivated %(token)s" msgid "BadgeToken__deactivated %(token)s"
msgstr "Redeem token '%(token)s' deactivated." msgstr "Redeem token '%(token)s' deactivated."
msgid "nav_channels_all"
msgstr "all"
msgid "nav_channels_accepted"
msgstr "accepted"
msgid "nav_channels_pending"
msgstr "pending"
msgid "nav_channels_planned"
msgstr "planned"
msgid "nav_channels_rejected"
msgstr "rejected"
msgid "nav_channels_hidden"
msgstr "hidden"
msgid "nav_conference" msgid "nav_conference"
msgstr "Conference" msgstr "Conference"
......
...@@ -8,22 +8,41 @@ ...@@ -8,22 +8,41 @@
<div class="card" id="logentries_{{ alc_ident }}"> <div class="card" id="logentries_{{ alc_ident }}">
<div class="card-header"> <div class="card-header">
<div class="d-inline-block float-end"> <div class="d-inline-block float-end">
<div class="btn-group d-none me-1" role="group" id="visible_logentries_{{ alc_ident }}"> <div class="btn-group d-none me-1"
<input type="radio" class="btn-check" name="visible_logentries" id="visible_logentries_all_{{ alc_ident }}" autocomplete="off" checked> role="group"
<label class="btn btn-sm btn-outline-primary" for="visible_logentries_all_{{ alc_ident }}">{% trans "activitylog_visibleentries_all" %}</label> id="visible_logentries_{{ alc_ident }}">
<input type="radio"
class="btn-check"
name="visible_logentries"
id="visible_logentries_all_{{ alc_ident }}"
autocomplete="off"
checked>
<label class="btn btn-sm btn-outline-primary"
for="visible_logentries_all_{{ alc_ident }}">{% trans "activitylog_visibleentries_all" %}</label>
<input type="radio" class="btn-check" name="visible_logentries" id="visible_logentries_msg_{{ alc_ident }}" autocomplete="off"> <input type="radio"
<label class="btn btn-sm btn-outline-primary" for="visible_logentries_msg_{{ alc_ident }}">{% trans "activitylog_visibleentries_msg" %}</label> class="btn-check"
name="visible_logentries"
id="visible_logentries_msg_{{ alc_ident }}"
autocomplete="off">
<label class="btn btn-sm btn-outline-primary"
for="visible_logentries_msg_{{ alc_ident }}">{% trans "activitylog_visibleentries_msg" %}</label>
</div> </div>
{% if add_comment_url %} {% if add_comment_url %}
<button class="btn btn-sm btn-primary" title="{% trans "activitylog_addcomment" %}" data-bs-toggle="modal" data-bs-target="#addCommentModal_{{ alc_ident }}"><i class="bi bi-chat-left-text"></i></button> <button class="btn btn-sm btn-primary"
title="{% trans "activitylog_addcomment" %}"
data-bs-toggle="modal"
data-bs-target="#addCommentModal_{{ alc_ident }}">
<i class="bi bi-chat-left-text"></i>
</button>
{% endif %} {% endif %}
</div> </div>
{% trans 'ActivityLogEntrys' %} {% trans "ActivityLogEntrys" %}
</div> </div>
<div class="card-body"> <div class="card-body">
{% for entry in object.logentries.all %} {% for entry in object.logentries.all %}
<div class="mb-3 {% if entry.kind == entry.Kind.SYSTEM %}text-muted{% endif %} logentry" data-has-msg="{% if entry.comment %}y{% else %}n{% endif %}"> <div class="mb-3 {% if entry.kind == entry.Kind.SYSTEM %}text-muted{% endif %} logentry"
data-has-msg="{% if entry.comment %}y{% else %}n{% endif %}">
{% if latest_note and latest_note.pk == entry.pk %}<a id="latest_note"></a>{% endif %} {% if latest_note and latest_note.pk == entry.pk %}<a id="latest_note"></a>{% endif %}
<div class="border-bottom border-secondary mb-1{% if not entry.comment %} text-muted{% endif %}"> <div class="border-bottom border-secondary mb-1{% if not entry.comment %} text-muted{% endif %}">
<abbr title="{{ entry.timestamp }}">{{ entry.timestamp|naturaltime }}</abbr> <abbr title="{{ entry.timestamp }}">{{ entry.timestamp|naturaltime }}</abbr>
...@@ -50,9 +69,7 @@ ...@@ -50,9 +69,7 @@
{% endif %} {% endif %}
{% if entry.comment %} {% if entry.comment %}
<i class="bi bi-chat-left-text float-start"></i> <i class="bi bi-chat-left-text float-start"></i>
<div class="ms-4 border-1 bg-primary-subtle"> <div class="ms-4 border-1 bg-primary-subtle">{{ entry.comment }}</div>
{{ entry.comment }}
</div>
{% endif %} {% endif %}
</div> </div>
{% endfor %} {% endfor %}
...@@ -62,22 +79,33 @@ ...@@ -62,22 +79,33 @@
</div> </div>
{% if add_comment_url %} {% if add_comment_url %}
<div class="modal fade" id="addCommentModal_{{ alc_ident }}" tabindex="-1" aria-labelledby="addCommentModalLabel" aria-hidden="true"> <div class="modal fade"
id="addCommentModal_{{ alc_ident }}"
tabindex="-1"
aria-labelledby="addCommentModalLabel"
aria-hidden="true">
<div class="modal-dialog"> <div class="modal-dialog">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<h1 class="modal-title fs-5" id="addCommentModalLabel">{% trans "activitylog_addcomment" %}</h1> <h1 class="modal-title fs-5" id="addCommentModalLabel">{% trans "activitylog_addcomment" %}</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> <button type="button"
class="btn-close"
data-bs-dismiss="modal"
aria-label="Close"></button>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<p>{% trans "activitylog_addcomment_help" %}</p> <p>{% trans "activitylog_addcomment_help" %}</p>
<form id="addcomment_{{ alc_ident }}" action="{{ add_comment_url }}" method="POST"> <form id="addcomment_{{ alc_ident }}"
action="{{ add_comment_url }}"
method="post">
{% csrf_token %} {% csrf_token %}
<textarea name="comment" class="form-control" placeholder="" required></textarea> <textarea name="comment" class="form-control" placeholder="" required></textarea>
</form> </form>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<button class="btn btn-primary" form="addcomment_{{ alc_ident }}"><i class="bi bi-chat-left-text"></i> {% trans "activitylog_addcomment_do" %}</button> <button class="btn btn-primary" form="addcomment_{{ alc_ident }}">
<i class="bi bi-chat-left-text"></i> {% trans "activitylog_addcomment_do" %}
</button>
</div> </div>
</div> </div>
</div> </div>
......
...@@ -40,15 +40,9 @@ ...@@ -40,15 +40,9 @@
</div> </div>
</div> </div>
<div class="col-md-3"> <div class="col-md-3">
<label class="form-label" for="id_state_assembly">{% trans "Assembly__state_assembly" %}</label> <label class="form-label" for="id_state">{% trans "Assembly__state" %}</label>
<div id="id_state_assembly">{{ form.instance.get_state_assembly_display }}</div> <div id="id_state">{{ form.instance.get_state_display }}</div>
</div> </div>
{% if conference.support_channels %}
<div class="col-md-3">
<label class="form-label" for="id_state_channel">{% trans "Assembly__state_channel" %}</label>
<div id="id_state_channel">{{ form.instance.get_state_channel_display }}</div>
</div>
{% endif %}
</div> </div>
<div class="row"> <div class="row">
......
...@@ -58,34 +58,27 @@ ...@@ -58,34 +58,27 @@
<div class="card-body text-center"> <div class="card-body text-center">
<p>{{ assembly.get_assembly_type_display }}</p> <p>{{ assembly.get_assembly_type_display }}</p>
<p> <p>
{% translate "Assembly__state_assembly" %} {% translate "Assembly__state" %}
<br> <br>
<span class="font-weight-bold{% if assembly.is_public %} text-success{% elif assembly.state_assembly == 'rejected' %} text-danger{% endif %}">{{ assembly.get_state_assembly_display }}</span> <span class="font-weight-bold {% if assembly.is_public %} text-success {% elif assembly.state == "rejected" %} text-danger {% endif %}">{{ assembly.get_state_display }}</span>
</p> </p>
{% if conference.support_channels %}
<p>
{% translate "Assembly__state_channel" %}
<br>
<span class="font-weight-bold{% if assembly.is_public %} text-success{% elif assembly.state_channel == 'rejected' %} text-danger{% endif %}">{{ assembly.get_state_channel_display }}</span>
</p>
{% endif %}
</div> </div>
</div> </div>
</div> </div>
</div> </div>
{% if assembly.state_assembly == "planned" %} {% if assembly.state == "planned" %}
<div class="row mt-3"> <div class="row mt-3">
<div class="col-md-12"> <div class="col-md-12">
<div class="card"> <div class="card">
<div class="card-header bg-warning">{% trans "Assembly__state_assembly-planned__hint" %}</div> <div class="card-header bg-warning">{% trans "Assembly__state-planned__hint" %}</div>
<div class="card-body">{% blocktrans %}Assembly__state_assembly-planned__description{% endblocktrans %}</div> <div class="card-body">{% blocktrans %}Assembly__state-planned__description{% endblocktrans %}</div>
</div> </div>
</div> </div>
</div> </div>
{% endif %} {% endif %}
{% if staff_access %} {% if staff_mode %}
<div class="row mt-3"> <div class="row mt-3">
<div class="col-md-12"> <div class="col-md-12">
<div class="card"> <div class="card">
...@@ -130,8 +123,8 @@ ...@@ -130,8 +123,8 @@
{% with la=assembly.linked_assemblies %} {% with la=assembly.linked_assemblies %}
{% if la|length > 0 %} {% if la|length > 0 %}
{% for linked in la %} {% for linked in la %}
{% if staff_access %} {% if staff_mode %}
<a href="{% url 'backoffice:assembly' pk=linked.pk %}">{{ linked.name }}</a> <a href="{% url "backoffice:assembly" pk=linked.pk %}">{{ linked.name }}</a>
{% else %} {% else %}
{{ linked.name }} {{ linked.name }}
{% endif %} {% endif %}
......
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
<div class="card-body"> <div class="card-body">
{% if assembly.basedata_readonly %} {% if assembly.basedata_readonly %}
<div class="alert alert-warning" <div class="alert alert-warning"
{% if staff_access %}style="text-decoration: line-through;"{% endif %}> {% if staff_mode %}style="text-decoration: line-through;"{% endif %}>
{% trans "assemblyedit_readonlybasedata" %} {% trans "assemblyedit_readonlybasedata" %}
</div> </div>
{% endif %} {% endif %}
......
...@@ -43,7 +43,7 @@ ...@@ -43,7 +43,7 @@
<ul> <ul>
{% for child in children %} {% for child in children %}
<li> <li>
{% if child.state_assembly == "hidden" %}<i class="bi bi-eye-slash" title="hidden"></i>{% endif %} {% if child.state == "hidden" %}<i class="bi bi-eye-slash" title="hidden"></i>{% endif %}
<a href="{% url 'backoffice:assembly' pk=child.id %}">{{ child.name }}</a> <a href="{% url 'backoffice:assembly' pk=child.id %}">{{ child.name }}</a>
<form action="{% url 'backoffice:assembly-editchildren' pk=assembly.id %}" <form action="{% url 'backoffice:assembly-editchildren' pk=assembly.id %}"
method="post" method="post"
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment