Skip to content

Commit

Permalink
Add bulk actions on report overview (#3777)
Browse files Browse the repository at this point in the history
Co-authored-by: Rieven <[email protected]>
Co-authored-by: ammar92 <[email protected]>
Co-authored-by: stephanie0x00 <[email protected]>
Co-authored-by: Jan Klopper <[email protected]>
  • Loading branch information
5 people authored Nov 14, 2024
1 parent 56389a8 commit dbcb28f
Show file tree
Hide file tree
Showing 12 changed files with 1,485 additions and 151 deletions.
66 changes: 66 additions & 0 deletions rocky/assets/js/grabSelectionOnModalOpen.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { onDomReady } from "./imports/utils.js";
import {
renderRenameSelection,
renderDeleteSelection,
renderRerunSelection,
} from "./reportActionForms.js";

onDomReady(function () {
if (getSelection().length > 0) {
openDialogFromUrl(getAnchor());
} else {
closeDialog(getAnchor());
}
});

export function openDialogFromUrl(anchor) {
// If ID is present in the URL on DomReady, open the dialog immediately.
let id = window.location.hash.slice(1);

if (id) {
let modal = document.querySelector("#" + id);

if (anchor == "rename-modal") {
renderRenameSelection(modal, getSelection());
}
if (anchor == "delete-modal") {
renderDeleteSelection(modal, getSelection());
}
if (anchor == "rerun-modal") {
renderRerunSelection(modal, getSelection());
}
}
}

export function closeDialog(anchor) {
// If ID is present in the URL on DomReady, open the dialog immediately.
let id = window.location.hash.slice(1);

if (id) {
let modal = document.querySelector("#" + id);
modal.close();
}

let baseUrl = window.location.toString().split("#")[0];
window.history.pushState("", "Base URL", baseUrl);
}

export function getSelection() {
let checkedItems = document.querySelectorAll(".report-checkbox:checked");
return checkedItems;
}

addEventListener("hashchange", function () {
if (getSelection().length > 0) {
openDialogFromUrl(getAnchor());
} else {
closeDialog(getAnchor());
}
});

function getAnchor() {
let currentUrl = document.URL;
let urlParts = currentUrl.split("#");

return urlParts.length > 1 ? urlParts[1] : null;
}
210 changes: 210 additions & 0 deletions rocky/assets/js/reportActionForms.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
export function renderRenameSelection(modal, selection) {
let report_names = getReportNames(selection);
let report_types = getReportTypes(selection);
let references = [];

selection.forEach((input_element) => {
references.push(input_element.value);
});

let table_element = document.getElementById("rename-table");
let table_body = table_element.querySelector("tbody");
let table_row = table_element.querySelector("tr.rename-table-row");

table_body.innerHTML = "";

for (let i = 0; i < references.length; i++) {
let table_row_copy = table_row.cloneNode(true);

let type_ul = table_row_copy.querySelector("td.type ul");
let name_input_element = table_row_copy.querySelector(".report-name-input");
let reference_input_element = table_row_copy.querySelector(
".report-reference-input",
);
// let date_td = table_row_copy.querySelector("td.date");

name_input_element.setAttribute("value", report_names[i]);
reference_input_element.setAttribute("value", references[i]);

type_ul.innerHTML = report_types[i];
// date_td.innerText = "date";

table_body.appendChild(table_row_copy);
}
}

export function renderDeleteSelection(modal, selection) {
let report_names = getReportNames(selection);
let report_types = getReportTypes(selection);
let reference_dates = getReportReferenceDates(selection);
let creation_dates = getReportCreationDates(selection);
let report_oois = getReportOOIs(selection);
let references = [];

selection.forEach((input_element) => {
references.push(input_element.value);
});

let table_element = document.getElementById("delete-table");
let table_body = table_element.querySelector("tbody");
let table_row = table_element.querySelector("tr.delete-table-row");

table_body.innerHTML = "";

for (let i = 0; i < references.length; i++) {
let table_row_copy = table_row.cloneNode(true);

let reference_input_element = table_row_copy.querySelector(
".report-reference-input",
);

let type_ul = table_row_copy.querySelector("td.type ul");
let reference_date_td = table_row_copy.querySelector("td.reference_date");
let creation_date_td = table_row_copy.querySelector("td.creation_date");
let ooi_td = table_row_copy.querySelector("td.input_objects");
let name_span = table_row_copy.querySelector("td.name span.name-holder");

name_span.innerText = report_names[i];
reference_input_element.setAttribute("value", references[i]);

type_ul.innerHTML = report_types[i];
reference_date_td.innerText = reference_dates[i];
creation_date_td.innerText = creation_dates[i];
ooi_td.innerHTML = report_oois[i];

table_body.appendChild(table_row_copy);
}
}

export function renderRerunSelection(modal, selection) {
let report_names = getReportNames(selection);
let references = [];
let report_types = getReportTypes(selection);
let reference_dates = getReportReferenceDates(selection);
let creation_dates = getReportCreationDates(selection);
let report_oois = getReportOOIs(selection);

selection.forEach((input_element) => {
references.push(input_element.value);
});

let table_element = document.getElementById("rerun-table");
let table_body = table_element.querySelector("tbody");
let table_row = table_element.querySelector("tr.rerun-table-row");

table_body.innerHTML = "";

for (let i = 0; i < references.length; i++) {
let table_row_copy = table_row.cloneNode(true);

let reference_input_element = table_row_copy.querySelector(
".report-reference-input",
);

let type_ul = table_row_copy.querySelector("td.type ul");
let reference_date_td = table_row_copy.querySelector("td.reference_date");
let creation_date_td = table_row_copy.querySelector("td.creation_date");
let ooi_td = table_row_copy.querySelector("td.input_objects");
let name_span = table_row_copy.querySelector("td.name span.name-holder");

name_span.innerText = report_names[i];
reference_input_element.setAttribute("value", references[i]);

type_ul.innerHTML = report_types[i];
reference_date_td.innerText = reference_dates[i];
creation_date_td.innerText = creation_dates[i];
ooi_td.innerHTML = report_oois[i];

table_body.appendChild(table_row_copy);
}
}

export function getReportNames(selection) {
let report_names = [];

for (let i = 0; i < selection.length; i++) {
let report_name = selection[i]
.closest("tr")
?.querySelector("td.report_name a")?.innerText;

if (!report_name) {
continue;
}

report_names.push(report_name);
}

return report_names;
}

export function getReportTypes(selection) {
let report_types_list = [];

for (let i = 0; i < selection.length; i++) {
let report_types = selection[i]
.closest("tr")
?.querySelector("td.report_types ul.tags")?.innerHTML;

if (!report_types) {
continue;
}

report_types_list.push(report_types);
}

return report_types_list;
}

export function getReportOOIs(selection) {
let report_oois_list = [];

for (let i = 0; i < selection.length; i++) {
let report_oois = selection[i]
.closest("tr")
?.querySelector("td.report_oois")?.innerHTML;

if (!report_oois) {
continue;
}

report_oois_list.push(report_oois);
}

return report_oois_list;
}

export function getReportReferenceDates(selection) {
let reference_dates = [];

for (let i = 0; i < selection.length; i++) {
let reference_date = selection[i]
.closest("tr")
?.querySelector("td.report_reference_date")?.innerHTML;

if (!reference_date) {
continue;
}

reference_dates.push(reference_date);
}

return reference_dates;
}

export function getReportCreationDates(selection) {
let creation_dates = [];

for (let i = 0; i < selection.length; i++) {
let creation_date = selection[i]
.closest("tr")
?.querySelector("td.report_creation_date")?.innerHTML;

if (!creation_date) {
continue;
}

creation_dates.push(creation_date);
}

return creation_dates;
}
3 changes: 3 additions & 0 deletions rocky/reports/report_types/definitions.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ class BaseReport:
def __init__(self, octopoes_api_connector: OctopoesAPIConnector):
self.octopoes_api_connector = octopoes_api_connector

def collect_data(self, input_oois: Iterable[str], valid_time: datetime) -> dict[str, dict[str, Any]]:
raise NotImplementedError

@classmethod
def class_attributes(cls) -> dict[str, Any]:
return {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
{% load i18n %}

{% component 'modal' size='dialog-large' modal_id='delete-modal' %}
{% fill 'header' %}{% translate "Delete the following report(s):" %}{% endfill %}
{% fill 'content' %}
<p>
{% blocktranslate %}
Deleted reports are removed in the view from the moment of deletion. The report can still be accessed on timestamps before the deletion. Only the report is removed from the view, not the data it is based on.
{% endblocktranslate %}
</p>
<p>
{% blocktranslate %}
It is still possible to generate a new report for same date. If the report is part of a combined report, it will remain available in the combined report.
{% endblocktranslate %}
</p>
<form id="delete-form" class="inline layout-wide" method="post">
{% csrf_token %}
<table id="delete-table">
<thead>
<tr>
{% comment %} <th>{% translate "Report type" %}</th> {% endcomment %}
<th>{% translate "Name" %}</th>
<th>{% translate "Type" %}</th>
<th>{% translate "Input objects" %}</th>
<th>{% translate "Reference date" %}</th>
<th>{% translate "Creation date" %}</th>
</tr>
</thead>
<tbody>
<tr class="delete-table-row">
<td class="name">
<span class="name-holder"></span>
<input type="hidden" name="report_reference" class="report-reference-input" />
</td>
<td class="type">
<ul class="tags horizontal-view">
</ul>
</td>
<td class="input_objects"></td>
<td class="reference_date"></td>
<td class="creation_date"></td>
</tr>
</tbody>
</table>
</form>
{% endfill %}
{% fill "footer_buttons" %}
<button type="submit"
form="delete-form"
class="destructive"
name="action"
value="delete">{% translate "Delete" %}</button>
{% endfill %}
{% endcomponent %}
{% component_css_dependencies %}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{% load i18n %}

{% component "modal" size="dialog-large" modal_id="rename-modal" %}
{% fill "header" %}
{% translate "Rename the following report(s):" %}
{% endfill %}
{% fill "content" %}
<form id="rename-form" class="inline layout-wide" method="post">
{% csrf_token %}
<table id="rename-table">
<thead>
<tr>
<th>{% translate "Report type" %}</th>
<th>{% translate "Name" %}</th>
{% comment %} <th>{% translate "Reference date" %}</th> {% endcomment %}
</tr>
</thead>
<tbody>
<tr class="rename-table-row">
<td class="type">
<ul class="tags horizontal-view">
</ul>
</td>
<td class="name">
<input type="text" name="report_name" class="report-name-input">
<input type="hidden" name="report_reference" class="report-reference-input">
</td>
{% comment %} <td class="date"></td> {% endcomment %}
</tr>
</tbody>
</table>
</form>
{% endfill %}
{% fill "footer_buttons" %}
<button type="submit"
form="rename-form"
class="submit"
name="action"
value="rename">{% translate "Rename" %}</button>
{% endfill %}
{% endcomponent %}
{% component_css_dependencies %}
Loading

0 comments on commit dbcb28f

Please sign in to comment.