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

1155 add a column to track the reindexing curator #1180

Open
wants to merge 12 commits into
base: dev
Choose a base branch
from
Open
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Generated by Django 4.2.9 on 2025-01-09 05:07

from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
("sde_collections", "0075_alter_collection_reindexing_status_and_more"),
]

operations = [
migrations.AddField(
model_name="collection",
name="reindexing_curated_by",
field=models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.DO_NOTHING,
related_name="reindexing_curated_by",
to=settings.AUTH_USER_MODEL,
),
),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Generated by Django 4.2.9 on 2025-01-09 05:12

from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
("sde_collections", "0076_collection_reindexing_curated_by"),
]

operations = [
migrations.AlterField(
model_name="collection",
name="reindexing_curated_by",
field=models.ForeignKey(
blank=True,
default=None,
null=True,
on_delete=django.db.models.deletion.DO_NOTHING,
related_name="reindexing_curated_by",
to=settings.AUTH_USER_MODEL,
),
),
]
4 changes: 4 additions & 0 deletions sde_collections/models/collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,9 @@ class Collection(models.Model):
tracker = FieldTracker(fields=["workflow_status", "reindexing_status"])

curated_by = models.ForeignKey(User, on_delete=models.DO_NOTHING, null=True, blank=True)
reindexing_curated_by = models.ForeignKey(
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

write tests as well.

User, on_delete=models.DO_NOTHING, null=True, blank=True, default=None, related_name="reindexing_curated_by"
)
curation_started = models.DateTimeField("Curation Started", null=True, blank=True)

class Meta:
Expand Down Expand Up @@ -550,6 +553,7 @@ def _create_from_json(cls, json_results):
for collection in json_results:
print("Creating collection: ", collection["name"])
collection.pop("curated_by")
collection.pop("reindexing_curated_by")
cls.objects.create(**collection)

@classmethod
Expand Down
8 changes: 8 additions & 0 deletions sde_collections/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class Meta:
"workflow_status_display",
"reindexing_status_display",
"curated_by",
"reindexing_curated_by",
"division",
"document_type",
"name",
Expand All @@ -45,6 +46,13 @@ class Meta:
# "division": {"required": False},
# }

def update(self, instance, validated_data):
# If reindexing_status is REINDEXING_NOT_NEEDED, set Reindexing Curator field to None (reset to default)
if validated_data.get("reindexing_status") == 1:
validated_data["reindexing_curated_by"] = None

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we maintain the history of changes on this field?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

History is now maintained.

return super().update(instance, validated_data)


class CollectionReadSerializer(serializers.ModelSerializer):
class Meta:
Expand Down
109 changes: 92 additions & 17 deletions sde_indexing_helper/static/js/collection_list.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@ const COLUMNS = {
CURATOR: 6,
CONNECTOR_TYPE: 7,
REINDEXING_STATUS: 8,
WORKFLOW_STATUS_RAW: 9,
CURATOR_ID: 10,
REINDEXING_STATUS_RAW: 11
REINDEXING_CURATOR: 9,
WORKFLOW_STATUS_RAW: 10,
CURATOR_ID: 11,
REINDEXING_STATUS_RAW: 12,
REINDEXING_CURATOR_ID: 13
};

var uniqueId; //used for logic related to contents on column customization modal
Expand Down Expand Up @@ -122,11 +124,25 @@ let table = $("#collection_table").DataTable({
},
},
],
searchPanes: {
controls: true,
// layout: 'columns-6',
columns: [
COLUMNS.DIVISION,
COLUMNS.DELTA_URLS,
COLUMNS.CURATED_URLS,
COLUMNS.WORKFLOW_STATUS,
COLUMNS.CURATOR,
COLUMNS.CONNECTOR_TYPE,
COLUMNS.REINDEXING_STATUS
]
},

columnDefs: [
// hide the data columns
{
targets: [COLUMNS.WORKFLOW_STATUS_RAW, COLUMNS.CURATOR_ID, COLUMNS.REINDEXING_STATUS_RAW],
visible: false,
targets: [COLUMNS.WORKFLOW_STATUS_RAW, COLUMNS.CURATOR_ID, COLUMNS.REINDEXING_STATUS_RAW, COLUMNS.REINDEXING_CURATOR_ID],
visible: false, width: "0px", responsivePriority: -1
},
{ width: "200px", targets: COLUMNS.URL },
{
Expand Down Expand Up @@ -229,13 +245,6 @@ let table = $("#collection_table").DataTable({
targets: [COLUMNS.CURATED_URLS],
type: "num-fmt",
},
// hide the data panes
{
searchPanes: {
show: false,
},
targets: [COLUMNS.WORKFLOW_STATUS_RAW, COLUMNS.CURATOR_ID, COLUMNS.REINDEXING_STATUS_RAW],
},
{
searchPanes: {
dtOpts: {
Expand All @@ -253,29 +262,37 @@ let table = $("#collection_table").DataTable({
targets: [COLUMNS.CONNECTOR_TYPE],
},
],
autoWidth: false,
});

$("#collection-dropdown-4").on("change", function () {
$("#workflow-status-selector").on("change", function () {
table
.columns(COLUMNS.WORKFLOW_STATUS_RAW)
.search(this.value ? "^" + this.value + "$" : "", true, false)
.draw();
});

$("#collection-dropdown-5").on("change", function () {
$("#curator-selector").on("change", function () {
table
.columns(COLUMNS.CURATOR_ID)
.search(this.value ? "^" + this.value + "$" : "", true, false)
.draw();
});

$("#collection-dropdown-6").on("change", function () {
$("#reindexing-status-selector").on("change", function () {
table
.columns(COLUMNS.REINDEXING_STATUS_RAW)
.search(this.value ? "^" + this.value + "$" : "", true, false)
.draw();
});

$("#reindexing-curator-selector").on("change", function () {
table
.columns(COLUMNS.REINDEXING_CURATOR_ID)
.search(this.value ? "^" + this.value + "$" : "", true, false)
.draw();
});

$("#nameFilter").on("keyup", function () {
table.columns(COLUMNS.NAME).search(this.value).draw();
});
Expand Down Expand Up @@ -426,6 +443,37 @@ function handleCuratorSelect() {
});
}

function handleReindexingCuratorSelect() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make this code dry and reuse code that we already have for CuratorSelect

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tried to modularize the handleReindexingCuratorSelect() and handleCuratorSelect() functions into one, but ended up with too much if-else statements. So leaving as it is for better understandability.

$("body").on("click", ".reindexing_curator_select", function () {
const collection_id = $(this).data("collection-id");
const reindexing_curator_id = $(this).attr("value");
const reindexing_curator_text = $(this).text();

// Update button text and style
const $button = $(`#reindexing-curator-button-${collection_id}`).last();
$button
.text(reindexing_curator_text)
.removeClass("btn-light btn-danger btn-warning btn-info btn-success btn-primary btn-dark")
.addClass("btn-success");

// Update DataTable
const rowIndex = table.row("#" + collection_id).index();
table.data()[rowIndex][COLUMNS.REINDEXING_CURATOR] = createReindexingCuratorButton(reindexing_curator_text);
// table.searchPanes.rebuildPane(COLUMNS.REINDEXING_CURATOR);

// Send update to server
postReindexingCurator(collection_id, reindexing_curator_id);
});
}

// Helper function to create reindexing curator button HTML
function createReindexingCuratorButton(reindexing_curator_text) {
const buttonClass = reindexing_curator_text === "None" ? "btn-dark" : "btn-success";
return `<div class="dropdown reindexing_curator_dropdown">
<button class="btn ${buttonClass} btn-sm dropdown-toggle">${reindexing_curator_text}</button>
</div>`;
}

function postReindexingStatus(collection_id, reindexing_status) {
var url = `/api/collections/${collection_id}/`;
$.ajax({
Expand All @@ -440,6 +488,16 @@ function postReindexingStatus(collection_id, reindexing_status) {
},
success: function (data) {
toastr.success("Reindexing Status Updated!");

// If reindexing_status is REINDEXING_NOT_NEEDED, set Reindexing Curator field to None (reset to default)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Take a look at the post_save method in collection.py and refactor it based on standards.

if (reindexing_status == 1) {
const $button = $(`#reindexing-curator-button-${collection_id}`).last();
$button.text("None").removeClass("btn-success").addClass("btn-dark");
// Update DataTable
const rowIndex = table.row("#" + collection_id).index();
table.data()[rowIndex][COLUMNS.REINDEXING_CURATOR] = createReindexingCuratorButton("None");
// table.searchPanes.rebuildPane(COLUMNS.REINDEXING_CURATOR);
}
},
});
}
Expand Down Expand Up @@ -481,6 +539,24 @@ function postCurator(collection_id, curator_id) {
});
}

function postReindexingCurator(collection_id, reindexing_curator_id) {
var url = `/api/collections/${collection_id}/`;
$.ajax({
url: url,
type: "PUT",
data: {
reindexing_curated_by: reindexing_curator_id,
csrfmiddlewaretoken: csrftoken,
},
headers: {
"X-CSRFToken": csrftoken,
},
success: function (data) {
toastr.success("Reindexing Curator Updated!");
},
});
}

$(document).ready(function () {
setupClickHandlers();

Expand All @@ -489,8 +565,6 @@ $(document).ready(function () {

// Remove the search input and add custom titles
var paneTitles = [
null,
null,
"Division",
"Delta URLs",
"Curated URLs",
Expand Down Expand Up @@ -545,6 +619,7 @@ function setupClickHandlers() {
handleWorkflowStatusSelect();
handleReindexingStatusSelect();
handleCuratorSelect();
handleReindexingCuratorSelect();
}

function clearSearchValues() {
Expand Down
48 changes: 45 additions & 3 deletions sde_indexing_helper/templates/sde_collections/collection_list.html
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,13 @@ <h2 class="title">Welcome back!</h2>
<th class="text-center noBorder" style="padding-right:25px !important">Curator</th>
<th class="text-center noBorder" style="padding-right:25px !important">Connector Type</th>
<th class="text-center noBorder" style="padding-right:25px !important">Reindexing Status</th>
<th class="text-center noBorder" style="padding-right:25px !important">Reindexing Curator</th>

<!-- Hidden Columns - Used for internal data storage -->
<th class="hideDisplay"></th>
<th class="hideDisplay"></th>
<th class="hideDisplay"></th>
<th class="hideDisplay"></th>
</tr>

<!-- Filter Row - Contains inputs and dropdowns for filtering table data -->
Expand Down Expand Up @@ -70,7 +72,7 @@ <h2 class="title">Welcome back!</h2>

<!-- Dropdown filter for Workflow Status -->
<td class="filterRowBottom">
<select id="collection-dropdown-4" class="select-dropdown selectStyling">
<select id="workflow-status-selector" class="select-dropdown selectStyling">
<option value="">SELECT</option>
{% for choice in workflow_status_choices %}
<option value="{{ choice }}"
Expand All @@ -81,7 +83,7 @@ <h2 class="title">Welcome back!</h2>

<!-- Dropdown filter for Curator -->
<td class="filterRowBottom">
<select id="collection-dropdown-5" class="select-dropdown selectStyling">
<select id="curator-selector" class="select-dropdown selectStyling">
<option value="">SELECT</option>
{% for curator in curators %}
<option value="{{ curator.pk }}"
Expand All @@ -100,7 +102,7 @@ <h2 class="title">Welcome back!</h2>

<!-- Dropdown filter for Reindexing Status -->
<td class="filterRowBottom">
<select id="collection-dropdown-6" class="select-dropdown selectStyling">
<select id="reindexing-status-selector" class="select-dropdown selectStyling">
<option value="">SELECT</option>
{% for choice in reindexing_status_choices %}
<option value="{{ choice }}"
Expand All @@ -109,10 +111,22 @@ <h2 class="title">Welcome back!</h2>
</select>
</td>

<!-- Dropdown filter for Reindexing Curator -->
<td class="filterRowBottom">
<select id="reindexing-curator-selector" class="select-dropdown selectStyling">
<option value="">SELECT</option>
{% for curator in curators %}
<option value="{{ curator.pk }}"
data-collection-id={{ collection.id }}>{{ curator.username }}</option>
{% endfor %}
</select>
</td>

<!-- Hidden cells corresponding to hidden columns -->
<td class="hideDisplay"></td> <!-- Stores raw workflow_status value (number) -->
<td class="hideDisplay"></td> <!-- Stores raw curated_by_id value -->
<td class="hideDisplay"></td> <!-- Stores raw reindexing_status value (number) -->
<td class="hideDisplay"></td> <!-- Stores raw reindexing_curated_by_id value -->
</tr>
</thead>
<tbody>
Expand Down Expand Up @@ -246,10 +260,38 @@ <h2 class="title">Welcome back!</h2>
</div>
</td>

<!-- Reindexing Curator Dropdown -->
<td class="noBorder">
<div class="dropdown reindexing_curator_dropdown"
data-match-pattern
remove_protocol
row
url>
<!-- Reindexing Curator button - green if assigned, dark if not -->
<button class="btn {% if collection.reindexing_curated_by %} btn-success {% else %} btn-dark {% endif %} btn-sm dropdown-toggle"
type="button"
id="reindexing-curator-button-{{ collection.id }}"
data-toggle="dropdown"
aria-haspopup="true"
aria-expanded="false">{{ collection.reindexing_curated_by }}</button>
<!-- Dropdown menu with all possible curators -->
<div class="dropdown-menu"
aria-labelledby="reindexing-curator-button-{{ collection.id }}">
{% for curator in curators %}
<a key="{{ curator.pk }}"
class="dropdown-item reindexing_curator_select"
value="{{ curator.pk }}"
data-collection-id={{ collection.id }}>{{ curator.username }}</a>
{% endfor %}
</div>
</div>
</td>

<!-- Hidden columns for internal use -->
<td class="hideDisplay">{{ collection.workflow_status }}</td>
<td class="hideDisplay">{{ collection.curated_by_id }}</td>
<td class="hideDisplay">{{ collection.reindexing_status }}</td>
<td class="hideDisplay">{{ collection.reindexing_curated_by_id }}</td>
</tr>
{% endfor %}
</tbody>
Expand Down
Loading