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

Enable/disable scheduled reports #3871

Merged
merged 20 commits into from
Nov 26, 2024
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
ff057f5
Enable disable scheduled reports
madelondohmen Nov 18, 2024
5802213
Sort generated reports on scheduled report page (desc)
madelondohmen Nov 19, 2024
ac4a26e
Add logger and success message
madelondohmen Nov 19, 2024
f4e52f6
Update template, add modal
madelondohmen Nov 19, 2024
78896bc
Add enabled-disabled tags
madelondohmen Nov 20, 2024
1fa4553
Update scheduled reports table conform design
madelondohmen Nov 20, 2024
109c859
Remove icon from enable button
madelondohmen Nov 20, 2024
e9a1ced
Update scheduled_reports_table.html
TwistMeister Nov 20, 2024
27e538f
Update documentation
madelondohmen Nov 20, 2024
9ead931
Merge branch 'feature/disable-scheduled-reports' of https://github.co…
madelondohmen Nov 20, 2024
e894e20
Merge branch 'main' into feature/disable-scheduled-reports
madelondohmen Nov 21, 2024
910e015
Small fix
madelondohmen Nov 21, 2024
9d9a60f
Merge branch 'feature/disable-scheduled-reports' of https://github.co…
madelondohmen Nov 21, 2024
37b383a
Create component for system-tag
madelondohmen Nov 21, 2024
280ce75
Split modal file from scheduled reports table
madelondohmen Nov 21, 2024
4ff3e22
Fix modal
madelondohmen Nov 21, 2024
469f445
Merge branch 'main' into feature/disable-scheduled-reports
madelondohmen Nov 21, 2024
4ee4428
Merge branch 'main' into feature/disable-scheduled-reports
stephanie0x00 Nov 25, 2024
ce7ebc3
Remove translation
madelondohmen Nov 25, 2024
442f6b5
Merge branch 'feature/disable-scheduled-reports' of https://github.co…
madelondohmen Nov 25, 2024
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
43 changes: 43 additions & 0 deletions rocky/assets/css/components/system-tag.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
.system-tag,
span.system-tag {
background-color: var(--colors-white);
border: 2px solid;
border-radius: var(--border-radius-xl);
padding: var(--spacing-grid-025) var(--spacing-grid-100);
box-sizing: border-box;
width: auto;

&::before {
content: none;
}

&.color-1 {
color: var(--colors-blue-600);
border-color: var(--colors-blue-600);
}

&.color-2 {
color: var(--colors-green-600);
border-color: var(--colors-green-600);
}

&.color-3 {
color: var(--colors-ochre-500);
border-color: var(--colors-ochre-500);
}

&.color-4 {
color: var(--colors-orange-600);
border-color: var(--colors-orange-600);
}

&.color-5 {
color: var(--colors-red-600);
border-color: var(--colors-red-600);
}

&.color-6 {
color: var(--colors-purrple-600);
border-color: var(--colors-purrple-600);
}
}
1 change: 1 addition & 0 deletions rocky/assets/css/main.scss
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
@import "components/sticky";
@import "components/sticky-column";
@import "components/state-tags";
@import "components/system-tag";
@import "components/table";
@import "components/toggle";
@import "components/toolbar";
Expand Down
4 changes: 4 additions & 0 deletions rocky/assets/css/themes/soft/fundamentals/border-radii.scss
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@
border-radius: var(--border-radius-l);
}

.border-radius-xl {
border-radius: var(--border-radius-xl);
}

.border-radius-round {
border-radius: var(--border-radius-round);
}
4 changes: 2 additions & 2 deletions rocky/components/modal/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ This outlines the basic usages and provides a code block example below, of how t

### Instantiate

First you need to add `{% load component_tags %}` at the top of your template. Next you need to add the following code block at the bottom, to include the corresponding JS (if you haven't already you also need to add `{% load compress %}`).
First you need to add `{% load component_tags %}` at the top of your template. Next you need to add the following code block at the bottom, to include the corresponding JS (if you haven't already you also need to add `{% load compress %}` and `{% load static %}`).

```
{% block html_at_end_body %}
Expand Down Expand Up @@ -58,7 +58,7 @@ Including `{% component_css_dependencies %}` is needed to inject the reference t
{% fill "content" %}
<form id="content-form" class="horizontal-view" action="" method="post">
{% csrf_token %}
{% blocktranslate %}
{% blocktranslate with context_data_variable=context_data_variable %}
<p>You can use {{ context_data_variable }} and HTML here <code>valid_time</code>!</p>
{% endblocktranslate %}
</form>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{% load i18n %}

{% component "modal" size="dialog-small" modal_id=modal_id %}
{% fill "header" %}
{% translate "Disable schedule" %}
{% endfill %}
{% fill "content" %}
<form id="content-form" class="horizontal-view" action="" method="post">
{% csrf_token %}
<p>
{% blocktranslate with report_name=schedule.recipe.report_name_format %}
Are you sure you want to disable the schedule for {{ report_name }}?
The recipe will still exist and the schedule can be enabled later on.
{% endblocktranslate %}
</p>
</form>
{% endfill %}
{% fill "footer_buttons" %}
<a class="button destructive"
href="{% url "enable_disable_scheduled_reports" organization.code %}?schedule_id={{ schedule.schedule_id }}">{% translate "Disable schedule" %}</a>
<button class="ghost close-modal-button">{% translate "Cancel" %}</button>
{% endfill %}
{% endcomponent %}
{% component_css_dependencies %}
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
{% load i18n %}
{% load static %}
{% load ooi_extra %}
{% load report_extra %}
{% load compress %}
{% load component_tags %}

{% if scheduled_reports %}
<p class="de-emphasized">
Expand All @@ -11,10 +14,11 @@
<caption class="visually-hidden">{% translate "Scheduled reports:" %}</caption>
<thead>
<tr>
<th scope="col">{% translate "Report Name" %}</th>
<th scope="col">{% translate "Report types" %}</th>
<th scope="col">{% translate "Name" %}</th>
<th scope="col">{% translate "Report type" %}</th>
<th scope="col">{% translate "Scheduled for" %}</th>
<th scope="col">{% translate "Recurrence" %}</th>
<th scope="col">{% translate "Schedule status" %}</th>
<th scope="col" class="actions"></th>
</tr>
</thead>
Expand All @@ -26,27 +30,36 @@
<td>
<ul class="tags horizontal-view">
{% if schedule.recipe.parent_report_type == "aggregate-organisation-report" %}
<li>
<span class="label tags-color-{{ schedule.recipe.parent_report_type|get_report_type_label_style }}">{{ schedule.recipe.parent_report_type|get_report_type_name }}</span>
<li class="label tags-color-{{ schedule.recipe.parent_report_type|get_report_type_label_style }}">
{{ schedule.recipe.parent_report_type|get_report_type_name }}
</li>
{% else %}
{% for report_type in schedule.recipe.report_types %}
{% if forloop.counter0 < 2 %}
<li>
<span class="label tags-color-{{ report_type|get_report_type_label_style }}">{{ report_type|get_report_type_name }}</span>
</li>
<li class="label tags-color-{{ report_type|get_report_type_label_style }}">{{ report_type|get_report_type_name }}</li>
{% endif %}
{% if forloop.counter0 == 2 %}
<li>
<span class="label tags-color-grey-2">+ {{ schedule.recipe.report_types|length|add:"-2" }}</span>
</li>
<li class="label tags-color-grey-2">+ {{ schedule.recipe.report_types|length|add:"-2" }}</li>
{% endif %}
{% endfor %}
{% endif %}
</ul>
</td>
<td class="nowrap">{{ schedule.deadline_at }}</td>
<td class="nowrap">
{% if not schedule.enabled %}
{% translate "-" %}
madelondohmen marked this conversation as resolved.
Show resolved Hide resolved
{% else %}
{{ schedule.deadline_at }}
{% endif %}
</td>
<td class="nowrap">{{ schedule.cron }}</td>
<td class="nowrap">
{% if schedule.enabled %}
<span class="label system-tag color-2">{% translate "Enabled" %}</span>
{% else %}
<span class="label system-tag color-3">{% translate "Disabled" %}</span>
{% endif %}
</td>
<td class="actions">
<button class="expando-button"
data-icon-open-class="icon ti-chevron-down"
Expand All @@ -64,10 +77,8 @@
<thead>
<tr>
<th scope="col" class="nowrap">{% translate "Name" %}</th>
<th scope="col">{% translate "Report type" %}</th>
<th scope="col">{% translate "Input object" %}</th>
<th scope="col">{% translate "Input" %}</th>
<th scope="col" class="nowrap">{% translate "Reference date" %}</th>
<th scope="col" class="nowrap">{% translate "Creation date" %}</th>
</tr>
</thead>
<tbody>
Expand All @@ -77,28 +88,35 @@
<a href="{% url "view_report" organization.code %}?report_id={{ report.reference }}&observed_at={{ report.observed_at|date:"Y-m-d H:i:s:u" }}"
title="{% translate "Show report details" %}">{{ report.name }}</a>
</td>
<td>
<span class="label tags-color-{{ report.report_type|get_report_type_label_style }}">{{ report.report_type|get_report_type_name }}</span>
</td>
<td>
{% if report.input_oois|length == 1 %}
{% with ooi=report.input_oois.0 %}
<a href="{% ooi_url 'ooi_detail' ooi organization.code query=ooi.mandatory_fields %}">{{ ooi|human_readable }}</a>
{% endwith %}
{% else %}
{{ report.input_oois|length }}
{{ report.input_oois|length }} {% translate "objects" %}
underdarknl marked this conversation as resolved.
Show resolved Hide resolved
{% endif %}
</td>
<td class="nowrap">{{ report.observed_at|date }}</td>
<td class="nowrap">{{ report.date_generated }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
<div class="horizontal-view toolbar">
<a class="button ghost"
href="{% ooi_url "ooi_edit" schedule.recipe organization.code %}"><span aria-hidden="true" class="icon ti-edit action-button"></span>{% translate "Edit report recipe" %}</a>
{% if schedule.enabled %}
{% include "report_overview/modal_partials/enable_disable_schedule_modal.html" with modal_id="disable-schedule-modal-"|add:schedule.schedule_id %}

<a class="button ghost"
href="{% ooi_url "ooi_edit" schedule.recipe organization.code %}"><span aria-hidden="true" class="icon ti-edit action-button"></span>{% translate "Edit report recipe" %}</a>
<a class="button ghost destructive"
href="#disable-schedule-modal-{{ schedule.schedule_id }}">{% translate "Disable schedule" %}</a>
{% else %}
<a class="button"
href="{% url "enable_disable_scheduled_reports" organization.code %}?schedule_id={{ schedule.schedule_id }}">{% translate "Enable schedule" %}</a>
<a class="button ghost"
href="{% ooi_url "ooi_edit" schedule.recipe organization.code %}"><span aria-hidden="true" class="icon ti-edit action-button"></span>{% translate "Edit report recipe" %}</a>
{% endif %}
</div>
</td>
</tr>
Expand All @@ -110,3 +128,8 @@
{% else %}
<p>{% translate "No scheduled reports have been generated yet." %}</p>
{% endif %}
{% block html_at_end_body %}
{% compress js %}
<script src="{% static "modal/script.js" %}" nonce="{{ request.csp_nonce }}" type="module"></script>
{% endcompress %}
{% endblock html_at_end_body %}
12 changes: 11 additions & 1 deletion rocky/reports/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,22 @@
ReportTypesSelectionMultiReportView,
SetupScanMultiReportView,
)
from reports.views.report_overview import ReportHistoryView, ScheduledReportsView, SubreportView
from reports.views.report_overview import (
ReportHistoryView,
ScheduledReportsEnableDisableView,
ScheduledReportsView,
SubreportView,
)

# Report overview urls
urlpatterns = [
path("", ReportsLandingView.as_view(), name="reports"),
path("scheduled-reports/", ScheduledReportsView.as_view(), name="scheduled_reports"),
path(
"scheduled-reports/enable-disable",
ScheduledReportsEnableDisableView.as_view(),
name="enable_disable_scheduled_reports",
),
path("report-history/", ReportHistoryView.as_view(), name="report_history"),
path("report-history/subreports", SubreportView.as_view(), name="subreports"),
]
Expand Down
52 changes: 52 additions & 0 deletions rocky/reports/views/report_overview.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

import structlog
from django.contrib import messages
from django.http import HttpResponse
from django.shortcuts import redirect
from django.urls import reverse
from django.utils.translation import gettext_lazy as _
from django.views.generic import ListView
Expand Down Expand Up @@ -70,9 +72,11 @@ def get_queryset(self) -> list[dict[str, Any]]:
recipe_tree = recipe_ooi_tree.store.values()
recipe_ooi = next(ooi for ooi in recipe_tree if isinstance(ooi, ReportRecipe))
report_oois = [ooi for ooi in recipe_tree if isinstance(ooi, Report)]
report_oois.sort(key=lambda ooi: ooi.date_generated, reverse=True)
recipes.append(
{
"schedule_id": schedule["id"],
"enabled": schedule["enabled"],
"recipe": recipe_ooi,
"cron": schedule["schedule"],
"deadline_at": datetime.fromisoformat(schedule["deadline_at"]),
Expand All @@ -88,6 +92,54 @@ def get_context_data(self, **kwargs):
return context


class ScheduledReportsEnableDisableView(BreadcrumbsReportOverviewView, SchedulerView, ListView):
"""
Cancel the selected report(s)
"""

task_type = "report"
template_name = "report_overview/scheduled_reports.html"

def get_queryset(self) -> ReportList:
return ReportList(self.octopoes_api_connector, valid_time=self.observed_at)

def get(self, request, *args, **kwargs) -> HttpResponse:
schedule_id = request.GET.get("schedule_id")
schedule = self.get_schedule_details(schedule_id)
is_schedule_enabled = schedule.enabled

self.edit_report_schedule(schedule_id, {"enabled": not is_schedule_enabled})

logger.info(
_("Schedule {}").format("disabled" if is_schedule_enabled else "enabled"),
event_code="0800081" if is_schedule_enabled else "0800082",
schedule_id=schedule_id,
)

report_recipe_id = schedule.data["report_recipe_id"]
report_recipe = self.octopoes_api_connector.get(
Reference.from_str(f"ReportRecipe|{report_recipe_id}"), valid_time=datetime.now(timezone.utc)
)

if is_schedule_enabled:
messages.success(
self.request,
_(
"Schedule disabled successfully. '{}' will not be generated "
"automatically until the schedule is enabled again."
).format(report_recipe.report_name_format),
)
else:
messages.success(
self.request,
_("Schedule enabled successfully. '{}' will be generated according to schedule.").format(
report_recipe.report_name_format
),
)

return redirect(reverse("scheduled_reports", kwargs={"organization_code": self.organization.code}))


class ReportHistoryView(BreadcrumbsReportOverviewView, OctopoesView, ListView):
"""
Shows all the reports that have ever been generated for the organization.
Expand Down
14 changes: 13 additions & 1 deletion rocky/rocky/locale/django.pot
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-11-18 15:24+0000\n"
"POT-Creation-Date: 2024-11-18 16:15+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <[email protected]>\n"
Expand Down Expand Up @@ -4297,6 +4297,10 @@ msgstr ""
msgid "Scheduled for"
msgstr ""

#: reports/templates/report_overview/scheduled_reports_table.html
msgid "Canceled"
msgstr ""

#: reports/templates/report_overview/scheduled_reports_table.html
msgid "Scheduled Reports:"
msgstr ""
Expand All @@ -4314,6 +4318,14 @@ msgstr ""
msgid "Edit report recipe"
msgstr ""

#: reports/templates/report_overview/scheduled_reports_table.html
msgid "Cancel schedule"
msgstr ""

#: reports/templates/report_overview/scheduled_reports_table.html
msgid "Restart schedule"
msgstr ""

#: reports/templates/report_overview/scheduled_reports_table.html
msgid "No scheduled reports have been generated yet."
msgstr ""
Expand Down
6 changes: 6 additions & 0 deletions rocky/rocky/views/scheduler.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,12 @@ def get_json_task_details(self) -> JsonResponse | None:
except SchedulerError as error:
return messages.error(self.request, error.message)

def get_schedule_details(self, schedule_id: str) -> ScheduleResponse:
try:
return self.scheduler_client.get_schedule_details(schedule_id)
except SchedulerError as error:
return messages.error(self.request, error.message)

def get_schedule_with_filters(self, filters: dict[str, list[dict[str, str]]]) -> ScheduleResponse:
try:
return self.scheduler_client.post_schedule_search(filters).results[0]
Expand Down
Loading