diff --git a/.github/actions/gen-report/action.yml b/.github/actions/gen-report/action.yml index 81292f78103..35015045192 100644 --- a/.github/actions/gen-report/action.yml +++ b/.github/actions/gen-report/action.yml @@ -4,12 +4,12 @@ runs: using: "composite" steps: - name: Archive code coverage results - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: ${{github.job}} HTML REPORT path: report.html - name: Generate Report - uses: dorny/test-reporter@v2 + uses: dorny/test-reporter@v3 if: success() || failure() # run this step even if previous step failed with: name: ${{github.job}} REPORT # Name of the check run which will be created diff --git a/.github/actions/start-build/action.yml b/.github/actions/start-build/action.yml index 6cb181801e4..22d8deae0d5 100644 --- a/.github/actions/start-build/action.yml +++ b/.github/actions/start-build/action.yml @@ -4,7 +4,7 @@ runs: using: "composite" steps: - id: cache-objects - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: ~/.cache key: reqs_${{ hashFiles('poetry.lock') }} @@ -16,7 +16,7 @@ runs: with: ELASTICSEARCH6_ARCHIVE: ${{ env.ELASTICSEARCH6_ARCHIVE }} - name: Set up Python 3.12 - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: '3.12' - name: Install lxml diff --git a/.github/workflows/test-build.yml b/.github/workflows/test-build.yml index 33942968529..00c5820b5b8 100644 --- a/.github/workflows/test-build.yml +++ b/.github/workflows/test-build.yml @@ -17,9 +17,9 @@ jobs: build-cache: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v6 - id: cache-objects - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: ~/.cache key: reqs_${{ hashFiles('poetry.lock') }} @@ -50,7 +50,7 @@ jobs: # Maps tcp port 5432 on service container to the host - 5432:5432 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v6 - uses: ./.github/actions/start-build - name: Run tests run: poetry run python3 -m invoke test-ci-addons --junit @@ -77,7 +77,7 @@ jobs: # Maps tcp port 5432 on service container to the host - 5432:5432 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v6 - uses: ./.github/actions/start-build - name: Run tests run: poetry run python3 -m invoke test-ci-website --junit @@ -104,7 +104,7 @@ jobs: # Maps tcp port 5432 on service container to the host - 5432:5432 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v6 - uses: ./.github/actions/start-build - name: NVM & yarn install run: poetry run python3 -m invoke assets --dev @@ -133,7 +133,7 @@ jobs: # Maps tcp port 5432 on service container to the host - 5432:5432 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v6 - uses: ./.github/actions/start-build - name: Run tests run: poetry run python3 -m invoke test-ci-api2 --junit @@ -161,7 +161,7 @@ jobs: # Maps tcp port 5432 on service container to the host - 5432:5432 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v6 - uses: ./.github/actions/start-build - name: Run tests run: poetry run python3 -m invoke test-ci-api3-and-osf --junit @@ -194,7 +194,7 @@ jobs: - 1025:1025 - 8025:8025 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v6 - uses: ./.github/actions/start-build - name: Run tests run: poetry run python3 -m invoke test-ci-mailhog -n 1 --junit @@ -222,7 +222,7 @@ jobs: # Maps tcp port 5432 on service container to the host - 5432:5432 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v6 - uses: ./.github/actions/start-build - name: Run tests run: poetry run python3 -m invoke test-ci-scripts -n 1 --junit diff --git a/CHANGELOG b/CHANGELOG index d5d3acb5be4..ff834603cd5 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,6 +2,16 @@ We follow the CalVer (https://calver.org/) versioning scheme: YY.MINOR.MICRO. +26.8.0 (2026-04-23) +=================== + +- Miscellaneous improvements and bug fixes + +26.7.1 (2026-04-22) +=================== + +- Hotfix to improve notifications and logging for failed registrations + 26.7.0 (2026-04-08) =================== diff --git a/admin/base/urls.py b/admin/base/urls.py index d19d2dc638b..9ff5e03a03e 100644 --- a/admin/base/urls.py +++ b/admin/base/urls.py @@ -37,6 +37,7 @@ re_path(r'^cedar_metadata_templates/', include('admin.cedar.urls', namespace='cedar_metadata_templates')), re_path(r'^draft_registrations/', include('admin.draft_registrations.urls', namespace='draft_registrations')), re_path(r'^files/', include('admin.files.urls', namespace='files')), + re_path(r'^share_reindex/', include('admin.share_reindex.urls', namespace='share_reindex')), ]), ), ] diff --git a/admin/nodes/urls.py b/admin/nodes/urls.py index 087a1d57e94..12d533ccfd0 100644 --- a/admin/nodes/urls.py +++ b/admin/nodes/urls.py @@ -8,6 +8,7 @@ re_path(r'^flagged_spam$', views.NodeFlaggedSpamList.as_view(), name='flagged-spam'), re_path(r'^known_spam$', views.NodeKnownSpamList.as_view(), name='known-spam'), re_path(r'^known_ham$', views.NodeKnownHamList.as_view(), name='known-ham'), + re_path(r'^embargo_report/$', views.EmbargoReportView.as_view(), name='embargo-report'), re_path(r'^doi_backlog_list/$', views.DoiBacklogListView.as_view(), name='doi-backlog-list'), re_path(r'^approval_backlog_list/$', views.ApprovalBacklogListView.as_view(), name='approval-backlog-list'), re_path(r'^confirm_approve_backlog_list/$', views.ConfirmApproveBacklogView.as_view(), name='confirm-approve-backlog-list'), @@ -51,4 +52,7 @@ re_path(r'^(?P[a-z0-9]+)/system_tags/(?P[a-z0-9]+)/remove/$', views.NodeRemoveSystemTag.as_view(), name='remove-system-tag'), re_path(r'^(?P[a-z0-9]+)/update_permissions/$', views.NodeUpdatePermissionsView.as_view(), name='update-permissions'), re_path(r'^(?P[a-z0-9]+)/remove_file/$', views.NodeRemoveFileView.as_view(), name='remove-file'), + re_path(r'^(?P[a-z0-9]+)/add_osfstorage_file/$', views.NodeAddOsfStorageFileView.as_view(), name='add-osfstorage-file'), + re_path(r'^(?P[a-z0-9]+)/remove_osfstorage_file/$', views.NodeRemoveOsfStorageFileView.as_view(), name='remove-osfstorage-file'), + ] diff --git a/admin/nodes/views.py b/admin/nodes/views.py index 01ebad686ce..a97fec18597 100644 --- a/admin/nodes/views.py +++ b/admin/nodes/views.py @@ -16,13 +16,16 @@ View, FormView, ListView, + TemplateView ) +from django.core.paginator import Paginator, InvalidPage from admin.base.forms import GuidForm from admin.base.utils import change_embargo_date from admin.base.views import GuidView from admin.nodes.forms import AddSystemTagForm, RegistrationDateForm from admin.notifications.views import delete_selected_notifications +from addons.osfstorage.models import OsfStorageFolder from api.caching.tasks import update_storage_usage_cache from api.share.utils import update_share from framework import status @@ -39,6 +42,7 @@ SpamStatus, TrashedFile ) +from osf.models.sanctions import Embargo from osf.models.admin_log_entry import ( update_admin_log, NODE_REMOVED, @@ -50,6 +54,7 @@ REINDEX_SHARE, REINDEX_ELASTIC, ) +from osf.models.files import File from osf.utils.permissions import ADMIN, API_CONTRIBUTOR_PERMISSIONS from scripts.approve_registrations import approve_past_pendings from website import settings, search @@ -474,6 +479,54 @@ def get_context_data(self, **kwargs): } +class EmbargoReportView(PermissionRequiredMixin, TemplateView): + """Report view for inspecting current and overdue embargoed registrations. + + Shows: + - pending embargoes that should have been activated + - active embargoes that are past their end date + - upcoming active embargoes + """ + template_name = 'nodes/embargo_report.html' + permission_required = 'osf.view_registration' + raise_exception = True + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + pending_embargoes = Embargo.objects.pending_embargoes().select_related('initiated_by') + active_embargoes = Embargo.objects.active_embargoes().select_related('initiated_by') + + pending_overdue_embargoes = [ + embargo for embargo in pending_embargoes + if embargo.should_be_embargoed + ] + + overdue_embargoes = [ + embargo for embargo in active_embargoes + if embargo.should_be_completed + ] + + upcoming_queryset = active_embargoes.filter( + end_date__gte=timezone.now(), + ).order_by('end_date') + + page_number = self.request.GET.get('page') or 1 + paginator = Paginator(upcoming_queryset, 10) + try: + upcoming_page = paginator.page(page_number) + except InvalidPage: + upcoming_page = paginator.page(1) + + context.update({ + 'now': timezone.now(), + 'pending_overdue_embargoes': pending_overdue_embargoes, + 'overdue_embargoes': overdue_embargoes, + 'upcoming_embargoes': upcoming_page.object_list, + 'upcoming_page': upcoming_page, + }) + return context + + class ConfirmApproveBacklogView(RegistrationListView): template_name = 'nodes/registration_approval_list.html' permission_required = 'osf.view_registrationapproval' @@ -846,6 +899,72 @@ def _remove_file_from_schema_response_blocks(registration, removed_file_id): return redirect(self.get_success_url()) +class NodeAddOsfStorageFileView(NodeMixin, View): + """ Allows an authorized user to add a file to osfstorage of an archived node. + """ + permission_required = 'osf.change_node' + + def post(self, request, *args, **kwargs): + registration = self.get_object() + guid_id = request.POST.get('file-guid', '').strip() + guid = Guid.load(guid_id) + if not guid: + messages.error(request, 'No file found with the provided guid.') + return redirect(self.get_success_url()) + + file = guid.referent + if not isinstance(file, File): + messages.error(request, 'The guid provided does not correspond to a file.') + return redirect(self.get_success_url()) + + parent_node = registration.registered_from + if not parent_node: + messages.error(request, 'The registration does not have the parent node.') + return redirect(self.get_success_url()) + + if not parent_node.files.filter(id=file.id).exists(): + messages.error(request, 'The file with the provided guid is not part of the parent node.') + return redirect(self.get_success_url()) + + osfstorage = registration.get_addon('osfstorage') + # copy file to Archive of OSF Storage folder + archive_folder = OsfStorageFolder.objects.filter( + parent=osfstorage.get_root(), + name=osfstorage.archive_folder_name + ).first() + file.copy_under(archive_folder) + messages.success(request, 'The file was successfully added.') + return redirect(self.get_success_url()) + + +class NodeRemoveOsfStorageFileView(NodeMixin, View): + """ Allows an authorized user to remove a file from osfstorage of an archived node. + """ + permission_required = 'osf.change_node' + + def post(self, request, *args, **kwargs): + registration = self.get_object() + guid_id = request.POST.get('file-guid', '').strip() + guid = Guid.load(guid_id) + if not guid: + messages.error(request, 'No file found with the provided guid.') + return redirect(self.get_success_url()) + + file = guid.referent + if not isinstance(file, File): + messages.error(request, 'The guid provided does not correspond to a file.') + return redirect(self.get_success_url()) + + registration_file = registration.files.filter(id=file.id) + if not registration_file.exists(): + messages.error(request, 'The file with the provided guid is not part of the registration.') + return redirect(self.get_success_url()) + + registration_file.delete() + messages.success(request, 'The file was successfully removed.') + return redirect(self.get_success_url()) + + class RemoveStuckRegistrationsView(NodeMixin, View): """ Allows an authorized user to remove a registrations if it's stuck in the archiving process. """ diff --git a/admin/preprints/urls.py b/admin/preprints/urls.py index d6eabdd870c..960e2e297e5 100644 --- a/admin/preprints/urls.py +++ b/admin/preprints/urls.py @@ -17,6 +17,7 @@ re_path(r'^(?P\w+)/remove_user/(?P[a-z0-9]+)/$', views.PreprintRemoveContributorView.as_view(), name='remove-user'), re_path(r'^(?P\w+)/make_private/$', views.PreprintMakePrivate.as_view(), name='make-private'), re_path(r'^(?P\w+)/fix_editing/$', views.PreprintFixEditing.as_view(), name='fix-editing'), + re_path(r'^(?P\w+)/fix_coi/$', views.PreprintFixCOI.as_view(), name='fix-coi'), re_path(r'^(?P\w+)/make_public/$', views.PreprintMakePublic.as_view(), name='make-public'), re_path(r'^(?P\w+)/remove/$', views.PreprintDeleteView.as_view(), name='remove'), re_path(r'^(?P\w+)/restore/$', views.PreprintDeleteView.as_view(), name='restore'), diff --git a/admin/preprints/views.py b/admin/preprints/views.py index 99d18d83650..3153ae301c8 100644 --- a/admin/preprints/views.py +++ b/admin/preprints/views.py @@ -668,6 +668,22 @@ def post(self, request, *args, **kwargs): return redirect(self.get_success_url()) +class PreprintFixCOI(PreprintMixin, View): + """ Allows an authorized user to manually fix conflict of interest field. + """ + permission_required = 'osf.change_preprint' + + def post(self, request, *args, **kwargs): + preprint = self.get_object() + if preprint.conflict_of_interest_statement and not preprint.has_coi: + preprint.update_has_coi(auth=request, has_coi=True, ignore_permission=True) + messages.success(request, 'The COI was successfully fixed.') + else: + messages.error(request, 'The COI is either already fixed or the preprint does not have conflict of interest set.') + + return redirect(self.get_success_url()) + + class PreprintMakePublic(PreprintMixin, View): """ Allows an authorized user to manually make a private preprint public. """ diff --git a/admin/registration_schemas/views.py b/admin/registration_schemas/views.py index aa205839029..df8aef09887 100644 --- a/admin/registration_schemas/views.py +++ b/admin/registration_schemas/views.py @@ -17,7 +17,7 @@ class RegistrationSchemaDetailView(FormView, PermissionRequiredMixin, TemplateVi Allows authorized users to view and edit some attributes of a Registration Schema. """ template_name = 'registration_schemas/registration_schema.html' - permission_required = 'osf.view_registration_schema' + permission_required = 'osf.view_registrationschema' raise_exception = True form_class = RegistrationSchemaEditForm @@ -143,7 +143,7 @@ class RegistrationSchemaListView(PermissionRequiredMixin, ListView): Allows authorized users to view all Registration Schema. """ template_name = 'registration_schemas/registration_schema_list.html' - permission_required = 'osf.view_registration_schema' + permission_required = 'osf.view_registrationschema' raise_exception = True def get_queryset(self): diff --git a/admin/share_reindex/__init__.py b/admin/share_reindex/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/admin/share_reindex/urls.py b/admin/share_reindex/urls.py new file mode 100644 index 00000000000..9eeb5d6d290 --- /dev/null +++ b/admin/share_reindex/urls.py @@ -0,0 +1,9 @@ +from django.urls import re_path +from . import views + +app_name = 'admin' + +urlpatterns = [ + re_path(r'^$', views.FailedShareIndexedGuidList.as_view(), name='list'), + re_path(r'^(?P[^/]+)/$', views.FailedShareIndexedGuidReindex.as_view(), name='reindex-share-resource'), +] diff --git a/admin/share_reindex/views.py b/admin/share_reindex/views.py new file mode 100644 index 00000000000..0d68194f7e5 --- /dev/null +++ b/admin/share_reindex/views.py @@ -0,0 +1,52 @@ +from django.contrib.auth.mixins import PermissionRequiredMixin +from django.urls import reverse +from django.shortcuts import redirect +from django.views.generic import ListView, View +from osf.models import Guid +from urllib.parse import urlencode +from api.share.utils import get_not_indexed_guids_for_resource_with_no_indexed_guid, task__reindex_failed_or_not_indexed_resource_into_share + +class FailedShareIndexedGuidList(PermissionRequiredMixin, ListView): + paginate_by = 25 + template_name = 'share_reindex/list.html' + permission_required = 'osf.update_share_reindex' + raise_exception = True + model = Guid + + def get_queryset(self): + resource_type = self.request.GET.get('type', 'projects') + return get_not_indexed_guids_for_resource_with_no_indexed_guid(resource_type) + + def get_context_data(self, **kwargs): + query_set = kwargs.pop('object_list', self.object_list) + page_size = self.get_paginate_by(query_set) + paginator, page, query_set, is_paginated = self.paginate_queryset(query_set, page_size) + kwargs.setdefault('items_to_index', query_set) + kwargs.setdefault('page', page) + resource_type = self.request.GET.get('type', 'projects') + kwargs.setdefault('selected_resource_type', resource_type) + resource_type_detail_mapping = { + 'users': 'users:user', 'preprints': 'preprints:preprint', 'registries': 'nodes:node', 'projects': 'nodes:node', 'files': 'files:file' + } + + kwargs.setdefault('resource_detail', resource_type_detail_mapping.get(resource_type)) + resource_type_guid_reindex = { + 'users': 'users:reindex-share-user', 'preprints': 'preprints:reindex-share-preprint', 'registries': 'nodes:reindex-share-node', 'projects': 'nodes:reindex-share-node' + } + kwargs.setdefault('resource_guid_reindex', resource_type_guid_reindex.get(resource_type)) + status_msg = f'Reindex of {resource_type} started, please check later.' if self.request.GET.get('status') == 'indexing' else '' + kwargs.setdefault('share_reindex_message', status_msg) + return super().get_context_data(**kwargs) + + +class FailedShareIndexedGuidReindex(PermissionRequiredMixin, View): + permission_required = 'osf.update_share_reindex' + raise_exception = True + + def post(self, request, *args, **kwargs): + resource_type = self.kwargs.get('resource_type') + # reindex 100_000 guids in background task for specific resource_type and resource is public + task__reindex_failed_or_not_indexed_resource_into_share.delay(resource_type) + base_url = reverse('share_reindex:list') + query_string = urlencode({'type': resource_type, 'status': 'indexing'}) + return redirect(f"{base_url}?{query_string}") diff --git a/admin/templates/base.html b/admin/templates/base.html index e6f10794c29..31a89b74037 100644 --- a/admin/templates/base.html +++ b/admin/templates/base.html @@ -169,6 +169,7 @@
  • IA Backlog
  • DOI Backlog
  • Approval Backlog
  • +
  • Embargo Report
  • {% endif %} @@ -316,6 +317,9 @@ {% if perms.osf.change_cedarmetadatatemplate %}
  • Cedar Metadata Templates
  • {% endif %} + {% if perms.osf.update_share_reindex %} +
  • Share Reindex
  • + {% endif %} {% if perms.osf.change_maintenancestate %}
  • Maintenance Alerts
  • {% endif %} diff --git a/admin/templates/nodes/add_file_to_osfstorage.html b/admin/templates/nodes/add_file_to_osfstorage.html new file mode 100644 index 00000000000..3a27f36b26f --- /dev/null +++ b/admin/templates/nodes/add_file_to_osfstorage.html @@ -0,0 +1,36 @@ +{% if node.is_registration and node.archived %} + + Add File (Osfstorage) + + +{% endif %} \ No newline at end of file diff --git a/admin/templates/nodes/embargo_report.html b/admin/templates/nodes/embargo_report.html new file mode 100644 index 00000000000..bbc68c994d1 --- /dev/null +++ b/admin/templates/nodes/embargo_report.html @@ -0,0 +1,157 @@ +{% extends "base.html" %} +{% load node_extras %} + +{% block content %} + + +

    Upcoming Active Embargoes

    + + + + + + + + + + + + {% include "util/pagination.html" with items=upcoming_page status='' pagin=False order='' %} + + {% for embargo in upcoming_embargoes %} + {% with registration=embargo.registrations.first %} + {% if registration %} + + + + + + + + + {% endif %} + {% endwith %} + {% empty %} + + + + {% endfor %} + +
    RegistrationEmbargo IDStateEmbargo StartEmbargo EndInitiated By
    + + {{ registration.title | truncatechars:30 }} + + {{ embargo.id }}{{ embargo.state }}{{ embargo.initiation_date|date:"F j, Y P" }}{{ embargo.end_date|date:"F j, Y P" }} + {% if embargo.initiated_by %} + + {{ embargo.initiated_by.fullname }} + + {% else %} + — + {% endif %} +
    No active embargoes found.
    + +

    Pending Embargoes Past Pending Window

    +

    These embargoes are still awaiting approval but have passed the automatic activation window.

    + + + + + + + + + + + + + {% for embargo in pending_overdue_embargoes %} + {% with registration=embargo.registrations.first %} + {% if registration %} + + + + + + + + + {% endif %} + {% endwith %} + {% empty %} + + + + {% endfor %} + +
    RegistrationEmbargo IDStateEmbargo InitiationEmbargo EndInitiated By
    + + {{ registration.title | truncatechars:30 }} + + {{ embargo.id }}{{ embargo.state }}{{ embargo.initiation_date|date:"F j, Y P" }}{{ embargo.end_date|date:"F j, Y P" }} + {% if embargo.initiated_by %} + + {{ embargo.initiated_by.fullname }} + + {% else %} + — + {% endif %} +
    No pending embargoes past the pending window.
    + +

    Active Embargoes Past Pending Window

    +

    These embargoes have an end date in the past but the embargo is still marked as active.

    + + + + + + + + + + + + + {% for embargo in overdue_embargoes %} + {% with registration=embargo.registrations.first %} + {% if registration %} + + + + + + + + + {% endif %} + {% endwith %} + {% empty %} + + + + {% endfor %} + +
    RegistrationEmbargo IDStateEmbargo EndIs Registration Public?Initiated By
    + + {{ registration.title | truncatechars:30 }} + + {{ embargo.id }}{{ embargo.state }}{{ embargo.end_date|date:"F j, Y P" }} + {% if registration.is_public %} + Yes + {% else %} + No + {% endif %} + + {% if embargo.initiated_by %} + + {{ embargo.initiated_by.fullname }} + + {% else %} + — + {% endif %} +
    No overdue active embargoes found.
    + +{% endblock %} + diff --git a/admin/templates/nodes/node.html b/admin/templates/nodes/node.html index 3e86290b249..68e451a59d4 100644 --- a/admin/templates/nodes/node.html +++ b/admin/templates/nodes/node.html @@ -29,6 +29,13 @@ +
    +
    +
    + {% include "nodes/add_file_to_osfstorage.html" with node=node %} + {% include "nodes/remove_file_from_osfstorage.html" with node=node %} +
    +

    {{ node.type|cut:'osf.'|title }}: {{ node.title }} ({{node.guid}})

    diff --git a/admin/templates/nodes/remove_file_from_osfstorage.html b/admin/templates/nodes/remove_file_from_osfstorage.html new file mode 100644 index 00000000000..6c26c35ee89 --- /dev/null +++ b/admin/templates/nodes/remove_file_from_osfstorage.html @@ -0,0 +1,36 @@ +{% if node.is_registration and node.archived %} + + Remove File (Osfstorage) + + +{% endif %} \ No newline at end of file diff --git a/admin/templates/preprints/fix_coi.html b/admin/templates/preprints/fix_coi.html new file mode 100644 index 00000000000..1324c4b53c5 --- /dev/null +++ b/admin/templates/preprints/fix_coi.html @@ -0,0 +1,21 @@ +{% if perms.osf.change_preprint %} + + Fix COI + + +{% endif %} diff --git a/admin/templates/preprints/preprint.html b/admin/templates/preprints/preprint.html index d716b60aeb7..36066a94ccf 100644 --- a/admin/templates/preprints/preprint.html +++ b/admin/templates/preprints/preprint.html @@ -28,6 +28,7 @@ {% include "preprints/make_public.html" with preprint=preprint %} {% include "preprints/make_published.html" with preprint=preprint %} {% include "preprints/fix_editing.html" with preprint=preprint %} + {% include "preprints/fix_coi.html" with preprint=preprint %} {% include "preprints/assign_new_version.html" with preprint=preprint %} diff --git a/admin/templates/share_reindex/list.html b/admin/templates/share_reindex/list.html new file mode 100644 index 00000000000..34083b75696 --- /dev/null +++ b/admin/templates/share_reindex/list.html @@ -0,0 +1,133 @@ +{% extends "base.html" %} +{% load render_bundle from webpack_loader %} +{% load comment_extras %} + +{% load static %} +{% block top_includes %} + +{% endblock %} +{% block title %} + Share Reindex +{% endblock title %} +{% block content %} +

    Share Reindex

    + + {% include "util/pagination.html" with items=page extra_query_params="&type="|add:selected_resource_type %} + + +
    +
    +
    + + + +
    +
    + + SHARE Reindex All {{selected_resource_type}} + + + +
    +
    + +
    +

    {{share_reindex_message}}

    +
    + + +
    + + + + {% if selected_resource_type == 'projects' or selected_resource_type == 'preprints' or selected_resource_type == 'registries' %} + + {% elif selected_resource_type == 'users' %} + + {% else %} + + {% endif %} + + + {% if selected_resource_type != 'files' %} + + {% endif %} + + + + {% for item in items_to_index %} + + + {% if selected_resource_type == 'projects' or selected_resource_type == 'preprints' or selected_resource_type == 'registries' %} + + {% elif selected_resource_type == 'users' %} + + {% else %} + + {% endif %} + + + + {% if selected_resource_type != 'files' %} + + + {% endif %} + + + + {% endfor %} + +
    GuidTitleFullnameNameDatetime Last IndexedReindex
    + + {{item.first_guid}} + + {{item.title}}{{item.fullname}}{{item.name}}{{item.date_last_indexed}} + SHARE Reindex +
    + +{% endblock content %} \ No newline at end of file diff --git a/admin/templates/util/pagination.html b/admin/templates/util/pagination.html index 8a3a2d82ce6..59e726f52c9 100644 --- a/admin/templates/util/pagination.html +++ b/admin/templates/util/pagination.html @@ -3,11 +3,11 @@