Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New attendances list page works #20

Merged
merged 46 commits into from
Jun 26, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
04e114d
preparing for new attendance list page/js
xjlin0 May 23, 2022
574bdf1
implmented search for gatherings
xjlin0 May 24, 2022
7d02a63
add initial search for attending meet list, but category should chang…
xjlin0 May 24, 2022
6b59c59
add content_type & object_id index for generic relations
xjlin0 May 24, 2022
3bcfe85
change attendingMeet and assembly's category to FK Category model in …
xjlin0 May 28, 2022
8d2c014
fix search of attending-meet list with category migration
xjlin0 May 28, 2022
b696f53
fix attendee upate page for saving attending meet datagrid popup
xjlin0 May 29, 2022
ca53ca2
fix UI overwrite entire attending meet infos
xjlin0 May 29, 2022
ef2958e
found a way to filter meets by user's groups, next is to implmente gr…
xjlin0 May 30, 2022
f174bf8
add allowed_groups in meet infos for future filtering based on user's…
xjlin0 Jun 4, 2022
05dcced
fix legacy attendance page of new category endpoint
xjlin0 Jun 4, 2022
466e94b
migrate attendance category
xjlin0 Jun 5, 2022
ba7503c
move attendance list to a new view , page loads but category endpoint…
xjlin0 Jun 5, 2022
b80aab8
new attendance page loads but api/organization_meet_character_attendi…
xjlin0 Jun 5, 2022
83faa3d
updated sort default for attending endpoints for organization_meet_ch…
xjlin0 Jun 5, 2022
c1f206d
change load access data script to accept new category id in Attending…
xjlin0 Jun 5, 2022
a7167fe
first working pagination with grouping
xjlin0 Jun 6, 2022
45601e3
group paging now works for gatherings list page
xjlin0 Jun 8, 2022
bc75c1a
fixed remote grouping page changing paging size?
xjlin0 Jun 9, 2022
f54d3c6
remove excess infos from Gatherings auto-generated from celery
xjlin0 Jun 9, 2022
80d0e10
now the searchText of gatheringsDatagrid won't be saved
xjlin0 Jun 9, 2022
fb40968
gatherings_list_view now can remember user's choice of meets and dates
xjlin0 Jun 9, 2022
dc4048e
now search text not remembere in datagrid_attendingmeets_list_view
xjlin0 Jun 9, 2022
58d8afb
now the character selection can be limited by Meets in datagrid_atten…
xjlin0 Jun 9, 2022
e45a086
implmented remote group for attending meet api & page
xjlin0 Jun 11, 2022
e71ad65
prepare to reload entire grid to reload attending lookup
xjlin0 Jun 11, 2022
08afbeb
resolve attending not showing by https://js.devexpress.com/Documentat…
xjlin0 Jun 11, 2022
bdd343c
search attendingmeet now works with or without grouping
xjlin0 Jun 13, 2022
5279050
fixed gathings counting for search with or without grouping
xjlin0 Jun 13, 2022
5c4ebe1
copying some fixes from attendingmeet to attendance list, ready to de…
xjlin0 Jun 13, 2022
873b80d
now attendance list show records
xjlin0 Jun 17, 2022
ad4b54b
fix self and coworker activities page
xjlin0 Jun 17, 2022
8ac8aa1
fix error of attendinmeet list page
xjlin0 Jun 18, 2022
10d87c6
add allowed model to prevent believer/baptized meets shows up in atte…
xjlin0 Jun 18, 2022
c8721b8
search in attendance list page works now
xjlin0 Jun 18, 2022
019bdcd
make search text NOT remembered for attendance list page
xjlin0 Jun 18, 2022
b979357
sorting works in new attendances list page
xjlin0 Jun 22, 2022
9982e9d
refactor Attendance query so it's easier to understand
xjlin0 Jun 22, 2022
77a65e5
now coworkers and general users can see different gathring/attendingm…
xjlin0 Jun 24, 2022
4a6ba75
add note and remove searchText in state in gathring/attendingmeet/att…
xjlin0 Jun 24, 2022
4264b8e
make DjangoAdmin for attendance and attendingmeet faster with raw_id_…
xjlin0 Jun 25, 2022
6d34c89
use autocomplete_fields to replace raw_id_fields, better ajax with se…
xjlin0 Jun 25, 2022
535b9ac
fix some Django Admin UI misbehaves for non-superusers/staff
xjlin0 Jun 25, 2022
112263d
Cascading Lookups in attending meet list page popup editor, limited b…
xjlin0 Jun 25, 2022
c287665
the team and character dropdown in attendence list page pop up editor…
xjlin0 Jun 26, 2022
23c50bb
search dropdown in popup editor of attendance list page now works
xjlin0 Jun 26, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@ All libraries are included to facilitate offline development, it will take port
* Install pre-commit for python, such as `pip3 install pre-commit` (pre-commit settings are at .git/hooks/pre-commit).
* There is no need to have local docker machine, Django or Postgres running.
* Install and start [docker desktop](https://www.docker.com/products/docker-desktop) (including docker compose), and [add local repo directory to file sharing in docker desktop preference](https://docs.docker.com/desktop/mac/#file-sharing).
* build and start the CentOS based local machine by `docker-compose -f local.yml build && docker-compose -f local.yml up -d`
* build and start the CentOS based local machine by `docker-compose -f local.yml build && docker-compose -f local.yml up -d`, your site will be at http://0.0.0.0:8008/


## DB SQL Backup & Restore process (with local.yml)
Expand Down Expand Up @@ -391,11 +391,11 @@ All libraries are included to facilitate offline development, it will take port
- [x] [PR#28](https://github.com/xjlin0/attendees30/pull/28) from Attendee detail and attendee list page
- [x] [PR#30](https://github.com/xjlin0/attendees30/pull/30) importer load_access_csv need to import bap date and believer, not only by membership.
- [x] Move "age, grade and mobility" from Attending.infos to Attendee.infos.fixed, since same attendee may join many activities
- [x] [2PR#18](https://github.com/xjlin0/attendees32/pull/19) AttendingMeet list (server side processing)
- [x] [2PR#19](https://github.com/xjlin0/attendees32/pull/19) AttendingMeet list (server side processing)
- [x] [2PR#18](https://github.com/xjlin0/attendees32/pull/18) new AttendingMeet datagrid filtered by meets and date ranges
- [ ] auto-generation of AttendingMeet by django-schedule with certain Past
- [ ] Attendance list (server side processing with auto-generation)
- [ ] new attendance datagrid filtered by meets and date ranges, since current datagrid_assembly_all_attendances & datagrid_coworker_organization_attendances cannot show correct attendings with real data (returning attendings only limit to 20 and not matching to filtered attendance's attending -- refresh the datagrid & reloading attending lookup with attendance filters)
- [x] [2PR#20](https://github.com/xjlin0/attendees32/pull/20) new attendance datagrid filtered by meets and date ranges, since current datagrid_assembly_all_attendances & datagrid_coworker_organization_attendances cannot show correct attendings with real data (returning attendings only limit to 20 and not matching to filtered attendance's attending -- refresh the datagrid & reloading attending lookup with attendance filters)
- [ ] auto-generation attendance by attending meet and recent attendance status
- [ ] member list (attendance level with editing category)
- [ ] Create roaster page (no real-time update for multiple coworkers in v1)
Expand Down
14 changes: 10 additions & 4 deletions attendees/occasions/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from django_json_widget.widgets import JSONEditorWidget
from attendees.occasions.models import Attendance, MessageTemplate, Assembly, Price, Character, Meet, Gathering, Team
from django.conf import settings
from attendees.persons.models import PgHistoryPage
from attendees.persons.models import PgHistoryPage, Category
from attendees.whereabouts.models import Organization, Division


Expand Down Expand Up @@ -62,6 +62,8 @@ class AssemblyAdmin(PgHistoryPage, admin.ModelAdmin):
def formfield_for_foreignkey(self, db_field, request, **kwargs):
if db_field.name == "division":
kwargs["queryset"] = Division.objects.all() if request.user.is_superuser else Division.objects.filter(organization=request.user.organization)
if db_field.name == "category":
kwargs["queryset"] = Category.objects.filter(type='assembly')
return super().formfield_for_foreignkey(db_field, request, **kwargs)

def get_queryset(self, request):
Expand Down Expand Up @@ -99,6 +101,10 @@ def get_queryset(self, request):


class AttendanceAdmin(PgHistoryPage, admin.ModelAdmin):
autocomplete_fields = ('attending', 'gathering',)
formfield_overrides = {
models.JSONField: {"widget": JSONEditorWidget},
}
list_display_links = ("get_attendee",)
list_filter = (
("gathering", admin.RelatedOnlyFieldListFilter),
Expand All @@ -122,7 +128,7 @@ class AttendanceAdmin(PgHistoryPage, admin.ModelAdmin):
tuple(["start", "finish"]),
tuple(["gathering", "team"]),
tuple(["attending", "character"]),
tuple(["free", "display_order", "category"]),
tuple(["display_order", "category"]),
tuple(["id", "created", "modified"]),
tuple(["infos"]),
),
Expand All @@ -140,7 +146,7 @@ def get_queryset(self, request):
if request.user.is_superuser:
return qs
else:
if request.resolver_match.func.__name__ == "changelist_view":
if request.resolver_match.func.__name__ == "changelist_view" and not messages.get_messages(request):
messages.warning(
request,
"Not all, but only those records accessible to you will be listed here.",
Expand Down Expand Up @@ -196,7 +202,7 @@ def get_queryset(self, request):
if request.user.is_superuser:
return qs
else:
if request.resolver_match.func.__name__ == "changelist_view":
if request.resolver_match.func.__name__ == "changelist_view" and not messages.get_messages(request):
messages.warning(
request,
"Not all, but only those records accessible to you will be listed here.",
Expand Down
6 changes: 3 additions & 3 deletions attendees/occasions/migrations/0002_assembly.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ class Migration(migrations.Migration):
('is_removed', models.BooleanField(default=False)),
('display_order', models.SmallIntegerField(blank=False, default=0, null=False)),
('division', models.ForeignKey(on_delete=models.SET(0), to='whereabouts.Division')),
('category', models.CharField(default='normal', help_text='normal, no-display, etc', max_length=20, blank=False, null=False, db_index=True)),
('category', models.ForeignKey(help_text='normal, no-display, etc', default=33, on_delete=models.deletion.DO_NOTHING, to='persons.Category')),
('infos', models.JSONField(blank=True, default=dict, help_text='example: {"need_age": 18}, please keep {} here even there\'s no data', null=True)),
('slug', models.SlugField(max_length=50, unique=True, help_text='format: Organization_name-Assembly_name')),
('display_name', models.CharField(max_length=50, blank=False, null=False, help_text='Uniq within Organization, adding year helps')),
('infos', models.JSONField(blank=True, default=dict, help_text='example: {"need_age": 18}, please keep {} here even there\'s no data', null=True)),
],
options={
'db_table': 'occasions_assemblies',
Expand Down Expand Up @@ -57,8 +57,8 @@ class Migration(migrations.Migration):
('division', models.ForeignKey(db_constraint=False, on_delete=models.deletion.DO_NOTHING, related_name='+', related_query_name='+', to='whereabouts.division')),
('display_order', models.SmallIntegerField(default=0)),
('infos', models.JSONField(blank=True, default=dict, help_text='example: {"need_age": 18}, please keep {} here even there\'s no data', null=True)),
('category', models.ForeignKey(db_constraint=False, default=33, help_text='normal, no-display, etc', on_delete=models.deletion.DO_NOTHING, related_name='+', related_query_name='+', to='persons.category')),
('slug', models.SlugField(db_index=False, help_text='format: Organization_name-Assembly_name')),
('category', models.CharField(default='normal', help_text='normal, no-display, etc', max_length=20)),
('display_name', models.CharField(help_text='Uniq within Organization, adding year helps', max_length=50)),
('start', models.DateTimeField(blank=True, help_text='optional', null=True)),
('finish', models.DateTimeField(blank=True, help_text='optional', null=True)),
Expand Down
4 changes: 4 additions & 0 deletions attendees/occasions/migrations/0005_meet.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ class Migration(migrations.Migration):
},
bases=(models.Model, Utility),
),
migrations.AddIndex(
model_name='Meet',
index=models.Index(condition=models.Q(('is_removed', False)), fields=['site_type', 'site_id'], name='meet_sites'),
),
migrations.AddIndex(
model_name='Meet',
index=GinIndex(fields=['infos'], name='meet_infos_gin'),
Expand Down
6 changes: 5 additions & 1 deletion attendees/occasions/migrations/0006_gathering.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,11 @@ class Migration(migrations.Migration):
),
migrations.AddConstraint(
model_name='gathering',
constraint=models.UniqueConstraint(fields=('meet_id', 'site_type', 'site_id', 'start'), condition=models.Q(is_removed=False), name='uniq_meet_location_time'),
constraint=models.UniqueConstraint(fields=('meet_id', 'site_type', 'site_id', 'start'), condition=models.Q(is_removed=False), name='gathering_uniq_meet_location_time'),
),
migrations.AddIndex(
model_name='gathering',
index=models.Index(condition=models.Q(('is_removed', False)), fields=['site_type', 'site_id'], name='gathering_sites'),
),
migrations.AddIndex(
model_name='Gathering',
Expand Down
4 changes: 4 additions & 0 deletions attendees/occasions/migrations/0007_team.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ class Migration(migrations.Migration):
},
bases=(models.Model, Utility),
),
migrations.AddIndex(
model_name='Team',
index=models.Index(condition=models.Q(('is_removed', False)), fields=['site_type', 'site_id'], name='team_sites'),
),
migrations.AddIndex(
model_name='Team',
index=GinIndex(fields=['infos'], name='team_infos_gin'),
Expand Down
4 changes: 2 additions & 2 deletions attendees/occasions/migrations/0008_attendance.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class Migration(migrations.Migration):
('team', models.ForeignKey(blank=True, default=None, help_text='empty for main meet', null=True, on_delete=django.db.models.deletion.SET_NULL, to='occasions.Team')),
# ('free', models.SmallIntegerField(blank=True, default=0, help_text='multitasking: the person cannot join other gatherings if negative', null=True)),
('display_order', models.SmallIntegerField(blank=False, default=0, null=False)),
('category', models.CharField(max_length=20, null=False, blank=False, default="scheduled", db_index=True, help_text="RSVPed, leave, remote, etc")),
('category', models.ForeignKey(default=1, help_text='RSVPed, leave, remote, etc', on_delete=models.SET(1), to='persons.category')),
('infos', models.JSONField(blank=True, default=dict, help_text='Example: {"kid_points": 5}. Please keep {} here even no data', null=True)),
],
options={
Expand Down Expand Up @@ -67,7 +67,7 @@ class Migration(migrations.Migration):
('attending', models.ForeignKey(db_constraint=False, on_delete=models.deletion.DO_NOTHING, related_name='+', related_query_name='+', to='persons.attending')),
('character', models.ForeignKey(db_constraint=False, on_delete=models.deletion.DO_NOTHING, related_name='+', related_query_name='+', to='occasions.character')),
('gathering', models.ForeignKey(db_constraint=False, on_delete=models.deletion.DO_NOTHING, related_name='+', related_query_name='+', to='occasions.gathering')),
('category', models.CharField(default='scheduled', help_text='RSVPed, leave, remote, etc', max_length=20)),
('category', models.ForeignKey(db_constraint=False, default=1, help_text='RSVPed, leave, remote, etc', on_delete=models.SET(1), related_name='+', related_query_name='+', to='persons.category')),
('team', models.ForeignKey(blank=True, db_constraint=False, default=None, help_text='empty for main meet', null=True, on_delete=models.deletion.DO_NOTHING, related_name='+', related_query_name='+', to='occasions.team')),
('start', models.DateTimeField(blank=True, help_text='optional', null=True)),
('finish', models.DateTimeField(blank=True, help_text='optional', null=True)),
Expand Down
13 changes: 6 additions & 7 deletions attendees/occasions/models/assembly.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,12 @@ class Assembly(TimeStampedModel, SoftDeletableModel, Utility):
)
start = models.DateTimeField(null=True, blank=True, help_text="optional")
finish = models.DateTimeField(null=True, blank=True, help_text="optional")
# contacts = models.ManyToManyField('whereabouts.Place', through='AssemblyContact')
category = models.CharField(
max_length=20,
default="normal",
blank=False,
category = models.ForeignKey(
"persons.Category",
null=False,
db_index=True,
blank=False,
default=33, # public
on_delete=models.deletion.DO_NOTHING,
help_text="normal, no-display, etc",
)
display_name = models.CharField(
Expand Down Expand Up @@ -96,7 +95,7 @@ class AssembliesHistory(pghistory.get_event_model(
display_order = models.SmallIntegerField(default=0)
infos = models.JSONField(blank=True, default=dict, help_text='example: {"need_age": 18}, please keep {} here even there\'s no data', null=True)
slug = models.SlugField(db_index=False, help_text='format: Organization_name-Assembly_name')
category = models.CharField(default='normal', help_text='normal, no-display, etc', max_length=20)
category = models.ForeignKey(db_constraint=False, default=33, help_text='normal, no-display, etc', on_delete=models.deletion.DO_NOTHING, related_name='+', related_query_name='+', to='persons.category')
display_name = models.CharField(help_text='Uniq within Organization, adding year helps', max_length=50)
start = models.DateTimeField(blank=True, help_text='optional', null=True)
finish = models.DateTimeField(blank=True, help_text='optional', null=True)
Expand Down
12 changes: 6 additions & 6 deletions attendees/occasions/models/attendance.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,12 @@ class Attendance(TimeStampedModel, SoftDeletableModel, Utility):
# null=True,
# help_text="multitasking: the person cannot join other gatherings if negative",
# )
category = models.CharField(
max_length=20,
null=False,
category = models.ForeignKey(
"persons.Category",
default=1, # scheduled
blank=False,
db_index=True,
default="scheduled",
null=False,
on_delete=models.SET(1),
help_text="RSVPed, leave, remote, etc",
)
display_order = models.SmallIntegerField(default=0, blank=False, null=False)
Expand Down Expand Up @@ -137,7 +137,7 @@ class AttendancesHistory(pghistory.get_event_model(
attending = models.ForeignKey(db_constraint=False, on_delete=models.deletion.DO_NOTHING, related_name='+', related_query_name='+', to='persons.attending')
character = models.ForeignKey(db_constraint=False, on_delete=models.deletion.DO_NOTHING, related_name='+', related_query_name='+', to='occasions.character')
gathering = models.ForeignKey(db_constraint=False, on_delete=models.deletion.DO_NOTHING, related_name='+', related_query_name='+', to='occasions.gathering')
category = models.CharField(default='scheduled', help_text='RSVPed, leave, remote, etc', max_length=20)
category = models.ForeignKey(db_constraint=False, help_text="RSVPed, leave, remote, etc", default=1, on_delete=models.SET(1), related_name='+', related_query_name='+', to='persons.category')
team = models.ForeignKey(blank=True, db_constraint=False, default=None, help_text='empty for main meet', null=True, on_delete=models.deletion.DO_NOTHING, related_name='+', related_query_name='+', to='occasions.team')
start = models.DateTimeField(blank=True, help_text='optional', null=True)
finish = models.DateTimeField(blank=True, help_text='optional', null=True)
Expand Down
7 changes: 6 additions & 1 deletion attendees/occasions/models/gathering.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,15 @@ class Meta:
models.UniqueConstraint(
fields=["meet_id", "site_type", "site_id", "start"],
condition=models.Q(is_removed=False),
name="uniq_meet_location_time",
name="gathering_uniq_meet_location_time",
)
]
indexes = [
models.Index(
fields=["site_type", "site_id"],
condition=models.Q(is_removed=False),
name="gathering_sites",
),
GinIndex(
fields=["infos"],
name="gathering_infos_gin",
Expand Down
5 changes: 5 additions & 0 deletions attendees/occasions/models/meet.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,11 @@ def schedule_text(self, timezone_name=settings.TIME_ZONE, format='%H:%M%p %a'):
class Meta:
db_table = "occasions_meets"
indexes = [
models.Index(
fields=["site_type", "site_id"],
condition=models.Q(is_removed=False),
name="meet_sites",
),
GinIndex(
fields=["infos"],
name="meet_infos_gin",
Expand Down
5 changes: 5 additions & 0 deletions attendees/occasions/models/team.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ class Team(TimeStampedModel, SoftDeletableModel, Utility):
class Meta:
db_table = "occasions_teams"
indexes = [
models.Index(
fields=["site_type", "site_id"],
condition=models.Q(is_removed=False),
name="team_sites",
),
GinIndex(
fields=["infos"],
name="team_infos_gin",
Expand Down
1 change: 1 addition & 0 deletions attendees/occasions/serializers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@
from .character_assembly_serializer import CharacterAssemblySerializer
from .gathering import GatheringSerializer
from .team import TeamSerializer
from .attendance_etc_serializer import AttendanceEtcSerializer
47 changes: 47 additions & 0 deletions attendees/occasions/serializers/attendance_etc_serializer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
from rest_framework import serializers

from attendees.occasions.models import Attendance


class AttendanceEtcSerializer(serializers.ModelSerializer):
gathering__meet__assembly = serializers.IntegerField(read_only=True, source='assembly')
gathering_name = serializers.CharField(read_only=True)
attending_name = serializers.CharField(read_only=True)

class Meta:
model = Attendance
fields = "__all__"

def create(self, validated_data):
"""
Create or update `AttendingMeet` instance, given the validated data.
"""
attendance_id = self._kwargs["data"].get("id")
obj, created = Attendance.objects.update_or_create(
id=attendance_id,
defaults=validated_data,
)
return obj

def update(self, instance, validated_data):
"""
Update and return an existing `AttendingMeet` instance, given the validated data.

"""

# if (
# True
# ): # need validations such as if the assembly matching meet, it's better to validate on UI first
# instance.meet = validated_data.get("meet", instance.meet)
# instance.meet.assembly = validated_data.get('assembly', instance.meet.assembly)
# instance.meet.save()
instance.gathering = validated_data.get("gathering", instance.gathering)
instance.attending = validated_data.get("attending", instance.attending)
instance.start = validated_data.get("start", instance.start)
instance.finish = validated_data.get("finish", instance.finish)
instance.character = validated_data.get("character", instance.character)
instance.category = validated_data.get("category", instance.category)
instance.team = validated_data.get("team", instance.team)
instance.infos = {**instance.infos, **validated_data.get("infos", {})}
instance.save()
return instance
Loading