-
-
Notifications
You must be signed in to change notification settings - Fork 1k
SAK-52090 Gradebook add filter for gb items #14292
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
Changes from all commits
2c8918c
a22bc2b
4070572
eac5b51
c3522eb
ba8fc5e
e7b5395
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,8 @@ | ||
| GB_HIDDEN_ITEMS_KEY = portal.user.id + "#gradebook#hiddenitems"; | ||
| GB_SCROLL_LEFT_KEY = portal.user.id + "#gradebook#scrollleft"; | ||
tsarchghs marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| GbGradeTable = { _onReadyCallbacks: [] }; | ||
| GbGradeTable.itemFilterText = ""; | ||
|
|
||
| GbGradeTable.dropdownShownHandler = e => { | ||
|
|
||
|
|
@@ -57,6 +59,13 @@ GbGradeTable.updateViewPreferences = function () { | |
| }); | ||
| }; | ||
|
|
||
| GbGradeTable.persistScrollPosition = function() { | ||
| const tableContainer = document.querySelector(".tabulator-tableholder"); | ||
| if (tableContainer) { | ||
| sessionStorage.setItem(GB_SCROLL_LEFT_KEY, tableContainer.scrollLeft); | ||
| } | ||
| }; | ||
|
|
||
| var sakaiReminder = new SakaiReminder(); | ||
|
|
||
| GbGradeTable.unpack = function (s, rowCount, columnCount) { | ||
|
|
@@ -191,6 +200,35 @@ TrimPathFragmentCache.prototype.setHTML = function (target, values) { | |
| GbGradeTable.replaceContents(target, this.getFragment(values)); | ||
| } | ||
|
|
||
| GbGradeTable.buildItemFilterHaystacks = function() { | ||
| GbGradeTable.columns.forEach(column => { | ||
| const haystack = [ | ||
| column?.title, | ||
| column?.abbrevTitle, | ||
| column?.name, | ||
| column?.categoryName, | ||
| ].filter(Boolean).join(" ").toLowerCase(); | ||
| column._itemFilterHaystack = haystack; | ||
| }); | ||
| }; | ||
|
Comment on lines
+203
to
+213
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @coderabbitai lets write columnSearchText or something else instead of haystack
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @kunaljaykam, great suggestion! Using a more descriptive name like To keep the naming consistent, I'd recommend updating:
This would make the code more self-documenting and easier to understand for anyone reading it. 🧠 Learnings used |
||
|
|
||
| GbGradeTable.matchesItemFilter = function(column) { | ||
| if (!GbGradeTable.itemFilterText) { | ||
| return true; | ||
| } | ||
|
|
||
| return (column?._itemFilterHaystack || "").indexOf(GbGradeTable.itemFilterText) !== -1; | ||
| }; | ||
|
|
||
| GbGradeTable.isColumnHidden = function(column) { | ||
| return column.hidden || !GbGradeTable.matchesItemFilter(column); | ||
| }; | ||
|
|
||
| GbGradeTable.setItemFilterText = function(text) { | ||
| GbGradeTable.itemFilterText = (text || "").toString().trim().toLowerCase(); | ||
| GbGradeTable.redrawTable(true); | ||
| }; | ||
|
|
||
| $(document).ready(function() { | ||
| // need TrimPath to load before parsing templates | ||
| GbGradeTable.templates = { | ||
|
|
@@ -751,6 +789,7 @@ GbGradeTable.renderTable = function (elementId, tableData) { | |
| GbGradeTable.columns = tableData.columns; | ||
| let hiddenItems = JSON.parse(sessionStorage.getItem(GB_HIDDEN_ITEMS_KEY)) || []; | ||
| GbGradeTable.columns.filter(c => hiddenItems.includes(c.assignmentId)).forEach(c => c.hidden = true); | ||
| GbGradeTable.buildItemFilterHaystacks(); | ||
| GbGradeTable.settings = tableData.settings; | ||
| GbGradeTable.courseGradeId = tableData.courseGradeId; | ||
| GbGradeTable.gradebookId = tableData.gradebookId; | ||
|
|
@@ -904,6 +943,16 @@ GbGradeTable.renderTable = function (elementId, tableData) { | |
| } | ||
| }); | ||
|
|
||
| // Restore horizontal scroll position if we stored it before a page refresh (eg, after saving an edited item) | ||
| const storedScrollLeft = sessionStorage.getItem(GB_SCROLL_LEFT_KEY); | ||
| if (storedScrollLeft !== null) { | ||
| const tableContainer = document.querySelector(".tabulator-tableholder"); | ||
| if (tableContainer) { | ||
| tableContainer.scrollLeft = parseInt(storedScrollLeft, 10); | ||
| } | ||
| sessionStorage.removeItem(GB_SCROLL_LEFT_KEY); | ||
tsarchghs marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| GbGradeTable.instance.on("headerClick", (e, column) => { | ||
| if (e.target.classList.contains('gb-title')) { | ||
| const table = column.getTable(); | ||
|
|
@@ -1208,7 +1257,39 @@ GbGradeTable.renderTable = function (elementId, tableData) { | |
| $input.val("").trigger("keyup"); | ||
| } | ||
| }); | ||
|
|
||
|
|
||
| let itemFilterTimeout; | ||
| let previousItemFilterText = ""; | ||
| const $itemFilterInput = $("#itemFilterInput"); | ||
| if ($itemFilterInput.length) { | ||
| $itemFilterInput | ||
| .on("keyup", function (event) { | ||
| clearTimeout(itemFilterTimeout); | ||
| itemFilterTimeout = setTimeout(function () { | ||
| const currentFilterText = event.target.value; | ||
| if (currentFilterText !== previousItemFilterText) { | ||
| previousItemFilterText = currentFilterText; | ||
| GbGradeTable.setItemFilterText(currentFilterText); | ||
| } | ||
| }, 300); | ||
| }) | ||
| .on("keydown", function (event) { | ||
| if (event.key === "Enter") { | ||
| clearTimeout(itemFilterTimeout); | ||
| GbGradeTable.setItemFilterText(event.target.value); | ||
| return false; | ||
| } | ||
| }); | ||
| } | ||
|
|
||
| $(document).on("click", ".gb-item-filter-clear-button", function (event) { | ||
| event.preventDefault(); | ||
| const $input = $("#itemFilterInput"); | ||
| if ($input.val().length > 0) { | ||
| $input.val("").trigger("keyup"); | ||
| } | ||
| }); | ||
|
|
||
| rubricGradingRow = 0; | ||
| rubricGradingCol = 0; | ||
|
|
||
|
|
@@ -1240,6 +1321,9 @@ GbGradeTable.renderTable = function (elementId, tableData) { | |
| .on("click", ".gb-dropdown-menu .edit-assignment-details", function () { | ||
| const cellElement = $(this).closest(".tabulator-cell, .tabulator-col"); | ||
|
|
||
| // Persist current horizontal position so we can restore after the page reloads from the edit | ||
| GbGradeTable.persistScrollPosition(); | ||
|
|
||
| GbGradeTable.ajax({ | ||
| action: "editAssignment", | ||
| assignmentId: cellElement.data("assignment-id"), | ||
|
|
@@ -1862,7 +1946,7 @@ GbGradeTable.getFilteredColumns = function() { | |
|
|
||
| return GbGradeTable._fixedColumns.concat( | ||
| GbGradeTable.columns | ||
| .filter(col => !col.hidden) | ||
| .filter(col => !GbGradeTable.isColumnHidden(col)) | ||
| .map((column, colIndex) => ({ | ||
| field: (GbGradeTable._fixedColumns.length + colIndex).toString(), | ||
| formatter: GbGradeTable.cellFormatter, | ||
|
|
@@ -1886,7 +1970,7 @@ GbGradeTable.getFilteredData = function() { | |
| GbGradeTable.applyColumnFilter = function(data) { | ||
| for (var i=GbGradeTable.columns.length-1; i>=0; i--) { | ||
| var column = GbGradeTable.columns[i]; | ||
| if (column.hidden) { | ||
| if (GbGradeTable.isColumnHidden(column)) { | ||
| for(var row=0; row<data.length; row++) { | ||
| data[row] = data[row] | ||
| .slice(0, i + GbGradeTable.FIXED_COLUMN_OFFSET) | ||
|
|
@@ -2872,7 +2956,7 @@ GbGradeTable.refreshSummaryLabels = function() { | |
| var visibleColumns = 0; | ||
| var totalColumns = GbGradeTable.columns.length; | ||
| $.each(GbGradeTable.columns, function(i, col) { | ||
| if (!col.hidden) { | ||
| if (!GbGradeTable.isColumnHidden(col)) { | ||
| visibleColumns = visibleColumns + 1; | ||
| } | ||
| }); | ||
|
|
@@ -2892,13 +2976,13 @@ GbGradeTable.refreshSummaryLabels = function() { | |
| if (col.type === 'category') { | ||
| totalCategories += 1; | ||
|
|
||
| if (!col.hidden) { | ||
| if (!GbGradeTable.isColumnHidden(col)) { | ||
| visibleCategories += 1; | ||
| } | ||
| } else if (col.type === 'assignment') { | ||
| totalAssignments += 1; | ||
|
|
||
| if (!col.hidden) { | ||
| if (!GbGradeTable.isColumnHidden(col)) { | ||
| visibleAssignments += 1; | ||
| } | ||
| } | ||
|
|
@@ -3138,30 +3222,49 @@ GbGradeTable.focusColumnForAssignmentId = function(assignmentId, showPopupForNew | |
| if (assignmentId) { | ||
| GbGradeTable.addReadyCallback(function() { | ||
| const col = GbGradeTable.colForAssignment(assignmentId); | ||
| const cell = GbGradeTable.instance.getRows()[0].getCells()[col]; | ||
|
|
||
| if (showPopupForNewItem === true) { | ||
| GbGradeTable.instance.scrollToColumn(col, "end", false); | ||
|
|
||
| const $selectedField = $(cell.getElement()); | ||
| setTimeout(() => GbGradeTable.instance.addRange(cell, cell), 100); | ||
| $selectedField.attr('data-bs-toggle','popover'); | ||
| $selectedField.attr('data-bs-placement','top'); | ||
| $selectedField.attr('data-bs-container','body'); | ||
| $selectedField.attr('data-bs-content',GbGradeTable.templates['newGradeItemPopoverMessage'].process()); | ||
| $selectedField.attr('data-bs-title',GbGradeTable.templates['newGradeItemPopoverTitle'].process()); | ||
| $selectedField.attr('data-bs-template','<div class="popover" role="tooltip"><div class="popover-arrow"></div><h3 class="mt-0 popover-header"></h3><div class="popover-body p-2"></div></div>'); | ||
|
|
||
| $('body, button').on('click keyup touchend', function (e) { | ||
| if ($(e.target).data("bs-toggle") !== 'popover' | ||
| && $(e.target).parents('.popover.in').length === 0) { | ||
| document.querySelectorAll('[data-bs-toggle="popover"]').forEach(el => { | ||
| bootstrap.Popover.getInstance(el)?.hide(); | ||
| }); | ||
| } | ||
| }) | ||
| new bootstrap.Popover($selectedField[0]).show(); | ||
| const rows = GbGradeTable.instance.getRows(); | ||
|
|
||
| if (col < 0) { | ||
| return; | ||
| } | ||
|
|
||
| GbGradeTable.instance.scrollToColumn(col, "end", false); | ||
|
|
||
| const firstRow = rows && rows.length ? rows[0] : null; | ||
| if (!firstRow) { | ||
| return; | ||
| } | ||
|
|
||
| setTimeout(() => { | ||
| const cell = firstRow.getCells()[col]; | ||
| if (!cell) { | ||
| return; | ||
| } | ||
|
|
||
| GbGradeTable.instance.addRange(cell, cell); | ||
| cell.getElement().focus(); | ||
|
|
||
| if (showPopupForNewItem === true) { | ||
|
|
||
| const $selectedField = $(cell.getElement()); | ||
| $selectedField.attr('data-bs-toggle','popover'); | ||
| $selectedField.attr('data-bs-placement','top'); | ||
| $selectedField.attr('data-bs-container','body'); | ||
| $selectedField.attr('data-bs-content',GbGradeTable.templates['newGradeItemPopoverMessage'].process()); | ||
| $selectedField.attr('data-bs-title',GbGradeTable.templates['newGradeItemPopoverTitle'].process()); | ||
| $selectedField.attr('data-bs-template','<div class="popover" role="tooltip"><div class="popover-arrow"></div><h3 class="mt-0 popover-header"></h3><div class="popover-body p-2"></div></div>'); | ||
|
|
||
| $('body, button').on('click keyup touchend', function (e) { | ||
| if ($(e.target).data("bs-toggle") !== 'popover' | ||
| && $(e.target).parents('.popover.in').length === 0) { | ||
| document.querySelectorAll('[data-bs-toggle="popover"]').forEach(el => { | ||
| bootstrap.Popover.getInstance(el)?.hide(); | ||
| }); | ||
| } | ||
| }) | ||
| new bootstrap.Popover($selectedField[0]).show(); | ||
| } | ||
| }, 200); | ||
| }); | ||
| } | ||
| }; | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.