Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
a45770f
[ENG-8769] Update waitress (#11290)
Vlad0n20 Oct 16, 2025
b796c25
[ENG-8177] Institution dashboard not showing user affiliations for Pr…
antkryt Oct 16, 2025
74b052a
fixed affiliation update for write contributors in registrations
ihorsokhanexoft Aug 7, 2025
02f1bdb
removed redundant blank line
ihorsokhanexoft Aug 7, 2025
cf67c7d
fixed tests
ihorsokhanexoft Aug 8, 2025
dd26ec1
fixed tests
ihorsokhanexoft Aug 8, 2025
8c222ff
fixed a test
ihorsokhanexoft Aug 8, 2025
a04d2c6
[ENG-9015] Redesign legacy pages (#11353)
futa-ikeda Oct 17, 2025
a95c48c
ENG-9127 add contributors from parent project to component
mkovalua Oct 17, 2025
bbc065e
implement unit test for component project contributors from parent pr…
mkovalua Oct 20, 2025
05484eb
Merge pull request #11376 from mkovalua/feature/ENG-9127
brianjgeiger Oct 21, 2025
5413b85
[ENG-9128] [Post-Release] P57 - [Contributors] Unregistered user’s “S…
Ostap-Zherebetskyi Oct 22, 2025
30e0c3d
[ENG-8655] Fix/eng 8655 (#11375)
Vlad0n20 Oct 23, 2025
3f8b884
[ENG-9122]Update create_at field for versioned preprint (#11383)
Vlad0n20 Oct 23, 2025
0a92941
[ENG-9002] allow gdpr delete for sole contribs (#11334)
antkryt Oct 23, 2025
62812c7
[ENG-8479] Update user template for admin app (#11346)
Vlad0n20 Oct 23, 2025
30b96ab
Merge pull request #11390 from CenterForOpenScience/develop
adlius Oct 23, 2025
c24abb2
[ENG-6223] chore: remove 'old' institution dashboard stuff (#11365)
aaxelb Oct 23, 2025
4277e44
fix test (#11394)
adlius Oct 27, 2025
aa51a32
Merge branch 'fix/ENG-8526-2' of github.com:ihorsokhanexoft/osf.io in…
ihorsokhanexoft Oct 28, 2025
39f9f97
don't expect errors in tests
ihorsokhanexoft Nov 21, 2025
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
16 changes: 16 additions & 0 deletions admin/templates/users/user.html
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,22 @@ <h2>User: <b>{{ user.username }}</b> <a href="{{ user.absolute_url }}"> ({{user.
<td>Full Name</td>
<td>{{ user.fullname }}</td>
</tr>
<tr>
<td>First Name</td>
<td>{{ user.given_name }}</td>
</tr>
<tr>
<td>Last Name</td>
<td>{{ user.family_name }}</td>
</tr>
<tr>
<td>Middle Name</td>
<td>{{ user.middle_names }}</td>
</tr>
<tr>
<td>Suffix</td>
<td>{{ user.suffix }}</td>
</tr>
<tr>
<td>Username</td>
<td>{{ user.username }}</td>
Expand Down
17 changes: 17 additions & 0 deletions api/base/pagination.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,23 @@ def paginate_queryset(self, queryset, request, view=None):
return super().paginate_queryset(queryset, request, view=None)


class JSONAPINoPagination(pagination.BasePagination):
'''do not accept page params nor paginate the queryset, but (for consistency with
JSONAPIPagination) do format the data into a jsonapi doc

possible future improvement: format jsonapi docs somewhere more reasonable
(like the renderer?) and delete this pagination class
'''
def paginate_queryset(self, queryset, request, view=None):
return queryset # let it be

def get_paginated_response(self, data):
return Response({
'data': data,
'meta': {'total': len(data)},
})


class MaxSizePagination(JSONAPIPagination):
page_size = 1000
max_page_size = None
Expand Down
21 changes: 0 additions & 21 deletions api/base/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -266,27 +266,6 @@ def assert_resource_type(obj, resource_tuple):
assert isinstance(obj, resource_tuple), f'obj must be {a_or_an} {error_message}; got {obj}'


class MockQueryset(list):
"""
This class is meant to convert a simple list into a filterable queryset look-a-like.
"""

def __init__(self, items, search, default_attrs=None, **kwargs):
self.search = search

for item in items:
if default_attrs:
item.update(default_attrs)
self.add_dict_as_item(item)

def __len__(self):
return self.search.count()

def add_dict_as_item(self, dict):
item = type('item', (object,), dict)
self.append(item)


def toggle_view_by_flag(flag_name, old_view, new_view):
'''toggle between view implementations based on a feature flag

Expand Down
39 changes: 0 additions & 39 deletions api/institutions/renderers.py

This file was deleted.

110 changes: 8 additions & 102 deletions api/institutions/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
from api.base.serializers import YearmonthField
from api.nodes.serializers import CompoundIDField
from api.base.exceptions import RelationshipPostMakesNoChanges
from api.base.utils import absolute_reverse


class InstitutionSerializer(JSONAPISerializer):
Expand Down Expand Up @@ -205,30 +204,6 @@ def create(self, validated_data):
}


class InstitutionSummaryMetricSerializer(JSONAPISerializer):

class Meta:
type_ = 'institution-summary-metrics'

id = IDField(source='institution_id', read_only=True)
public_project_count = ser.IntegerField(read_only=True)
private_project_count = ser.IntegerField(read_only=True)
user_count = ser.IntegerField(read_only=True)

links = LinksField({
'self': 'get_absolute_url',
})

def get_absolute_url(self, obj):
return absolute_reverse(
'institutions:institution-summary-metrics',
kwargs={
'institution_id': self.context['request'].parser_context['kwargs']['institution_id'],
'version': 'v2',
},
)


class UniqueDeptIDField(CompoundIDField):
"""Creates a unique department ID of the form "<institution-id>-<dept-id>"."""

Expand All @@ -255,74 +230,12 @@ class Meta:
name = ser.CharField(read_only=True)
number_of_users = ser.IntegerField(read_only=True)

links = LinksField({
'self': 'get_absolute_url',
})

filterable_fields = frozenset([
'id',
'name',
'number_of_users',
])

def get_absolute_url(self, obj):
return absolute_reverse(
'institutions:institution-department-metrics',
kwargs={
'institution_id': self.context['request'].parser_context['kwargs']['institution_id'],
'version': 'v2',
},
)
raise NotImplementedError()


class OldInstitutionUserMetricsSerializer(JSONAPISerializer):
class InstitutionUserMetricsSerializer(JSONAPISerializer):
'''serializer for institution-users metrics

used only when the INSTITUTIONAL_DASHBOARD_2024 feature flag is NOT active
(and should be removed when that flag is permanently active)
'''

class Meta:
type_ = 'institution-users'

id = IDField(source='user_id', read_only=True)
user_name = ser.CharField(read_only=True)
public_projects = ser.IntegerField(source='public_project_count', read_only=True)
private_projects = ser.IntegerField(source='private_project_count', read_only=True)
department = ser.CharField(read_only=True)

user = RelationshipField(
related_view='users:user-detail',
related_view_kwargs={'user_id': '<user_id>'},
)

links = LinksField({
'self': 'get_absolute_url',
})

filterable_fields = frozenset([
'id',
'user_name',
'public_projects',
'private_projects',
'department',
])

def get_absolute_url(self, obj):
return absolute_reverse(
'institutions:institution-user-metrics',
kwargs={
'institution_id': self.context['request'].parser_context['kwargs']['institution_id'],
'version': 'v2',
},
)


class NewInstitutionUserMetricsSerializer(JSONAPISerializer):
'''serializer for institution-users metrics

used only when the INSTITUTIONAL_DASHBOARD_2024 feature flag is active
(and should be renamed without "New" when that flag is permanently active)
'''

class Meta:
Expand Down Expand Up @@ -360,11 +273,6 @@ class Meta:
)
contacts = ser.SerializerMethodField()

links = LinksField({})

def get_absolute_url(self):
return None # there is no detail view for institution-users

def get_contacts(self, obj):
user = OSFUser.load(obj._d_['user_id'])
if not user:
Expand All @@ -380,12 +288,12 @@ def get_contacts(self, obj):
).order_by('sender_name')
return list(results)

def get_absolute_url(self, obj):
raise NotImplementedError()

class NewInstitutionSummaryMetricsSerializer(JSONAPISerializer):
'''serializer for institution-summary metrics

used only when the INSTITUTIONAL_DASHBOARD_2024 feature flag is active
(and should be renamed without "New" when that flag is permanently active)
class InstitutionSummaryMetricsSerializer(JSONAPISerializer):
'''serializer for institution-summary metrics
'''

class Meta:
Expand Down Expand Up @@ -414,10 +322,8 @@ class Meta:
related_view_kwargs={'institution_id': '<institution_id>'},
)

links = LinksField({})

def get_absolute_url(self):
return None # there is no detail view for institution-users
def get_absolute_url(self, obj):
raise NotImplementedError()


class InstitutionRelated(JSONAPIRelationshipSerializer):
Expand Down
4 changes: 2 additions & 2 deletions api/institutions/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
re_path(r'^(?P<institution_id>\w+)/relationships/registrations/$', views.InstitutionRegistrationsRelationship.as_view(), name=views.InstitutionRegistrationsRelationship.view_name),
re_path(r'^(?P<institution_id>\w+)/relationships/nodes/$', views.InstitutionNodesRelationship.as_view(), name=views.InstitutionNodesRelationship.view_name),
re_path(r'^(?P<institution_id>\w+)/users/$', views.InstitutionUserList.as_view(), name=views.InstitutionUserList.view_name),
re_path(r'^(?P<institution_id>\w+)/metrics/summary/$', views.institution_summary_metrics_detail_view, name=views.institution_summary_metrics_detail_view.view_name),
re_path(r'^(?P<institution_id>\w+)/metrics/summary/$', views.InstitutionSummaryMetricsDetail.as_view(), name=views.InstitutionSummaryMetricsDetail.view_name),
re_path(r'^(?P<institution_id>\w+)/metrics/departments/$', views.InstitutionDepartmentList.as_view(), name=views.InstitutionDepartmentList.view_name),
re_path(r'^(?P<institution_id>\w+)/metrics/users/$', views.institution_user_metrics_list_view, name=views.institution_user_metrics_list_view.view_name),
re_path(r'^(?P<institution_id>\w+)/metrics/users/$', views.InstitutionUserMetricsList.as_view(), name=views.InstitutionUserMetricsList.view_name),
]
Loading
Loading