Remove legacy grid backbone wrapper from code base

This commit is contained in:
guerler
2024-02-11 08:20:18 -05:00
parent 19f4ac3252
commit 3388cda29e
3 changed files with 0 additions and 1348 deletions
-111
View File
@@ -1,111 +0,0 @@
import Backbone from "backbone";
import $ from "jquery";
import _ from "underscore";
export default Backbone.Model.extend({
defaults: {
url_base: "",
title_id: undefined,
async: false,
async_ops: [],
categorical_filters: [],
filters: {},
sort_key: null,
show_item_checkboxes: false,
advanced_search: false,
cur_page: 1,
num_pages: 1,
operation: undefined,
item_ids: undefined,
},
/**
* Add filtering criterion.
*/
add_filter: function (key, value, append) {
// Update URL arg with new condition.
if (append) {
// Update or append value.
var cur_val = this.attributes.filters[key];
var new_val;
if (cur_val === null || cur_val === undefined) {
new_val = value;
} else if (typeof cur_val == "string") {
if (cur_val == "All" || cur_val == value) {
new_val = value;
} else {
// Replace string with array.
var values = [];
values[0] = cur_val;
values[1] = value;
new_val = values;
}
} else {
// Current value is an array.
new_val = cur_val;
if (new_val.indexOf(value) === -1) {
new_val.push(value);
}
}
this.attributes.filters[key] = new_val;
} else {
// Replace value.
this.attributes.filters[key] = value;
}
},
/**
* Remove filtering criterion.
*/
remove_filter: function (key, condition) {
var cur_val = this.attributes.filters[key];
if (cur_val === null || cur_val === undefined) {
return false;
}
if (typeof cur_val === "string") {
// overwrite/remove condition.
this.attributes.filters[key] = "";
} else {
// filter contains an array of conditions.
var condition_index = _.indexOf(cur_val, condition);
if (condition_index !== -1) {
cur_val[condition_index] = "";
}
}
},
/**
* Returns URL data for obtaining a new grid.
*/
get_url_data: function () {
var url_data = {
async: this.attributes.async,
sort: this.attributes.sort_key,
page: this.attributes.cur_page,
show_item_checkboxes: this.attributes.show_item_checkboxes,
advanced_search: this.attributes.advanced_search,
};
// Add operation, item_ids only if they have values.
if (this.attributes.operation) {
url_data.operation = this.attributes.operation;
}
if (this.attributes.item_ids) {
url_data.id = this.attributes.item_ids;
}
// Add filter arguments to data, placing "f-" in front of all arguments.
var self = this;
_.each(_.pairs(self.attributes.filters), (k) => {
url_data[`f-${k[0]}`] = k[1];
});
return url_data;
},
// Return URL for obtaining a new grid
get_url: function (args) {
return `${this.get("url_base")}?${$.param(this.get_url_data())}&${$.param(args)}`;
},
});
-556
View File
@@ -1,556 +0,0 @@
import { sanitize } from "dompurify";
import $ from "jquery";
import _ from "underscore";
// grid view templates
export default {
// template
grid: function (options) {
let tmpl;
if (options.embedded) {
tmpl = this.grid_header(options) + this.grid_table(options);
} else {
tmpl = `
<div class="loading-elt-overlay"></div>
<table class="grid-table">
<tr>
<td width="75%">${this.grid_header(options)}</td>
<td></td>
<td></td>
</tr>
<tr>
<td width="100%" id="grid-message" valign="top"></td>
<td></td>
<td></td>
</tr>
</table>
${this.grid_table(options)}
`;
}
// add info text
if (options.info_text) {
tmpl += `<br><div class="toolParamHelp" style="clear: both;">${options.info_text}</div>`;
}
// return
return tmpl;
},
// template
grid_table: function () {
return `
<form method="post" onsubmit="return false;">
<table id="grid-table" class="grid">
<thead id="grid-table-header"></thead>
<tbody id="grid-table-body"></tbody>
<tfoot id="grid-table-footer"></tfoot>
</table>
</form>`;
},
// template
grid_header: function (options) {
var tmpl = '<div class="grid-header">';
if (!options.embedded) {
let id_str = "";
if (options.title_id) {
id_str += ` id="${options.title_id}"`;
}
tmpl += `<h2${id_str}>${options.title}</h2>`;
}
if (options.global_actions) {
tmpl += '<ul class="manage-table-actions">';
var show_popup = options.global_actions.length >= 3;
if (show_popup) {
tmpl +=
'<li><a class="action-button" id="popup-global-actions" class="menubutton">Actions</a></li>' +
'<div popupmenu="popup-global-actions">';
}
for (const action of options.global_actions) {
tmpl += `<li><a class="action-button use-target" target="${action.target}" href="${action.url_args}" onclick="return false;" >${action.label}</a></li>`;
}
if (show_popup) {
tmpl += "</div>";
}
tmpl += "</ul>";
}
if (options.insert) {
tmpl += options.insert;
}
// add grid filters
tmpl += this.grid_filters(options);
tmpl += "</div>";
// return template
return tmpl;
},
// template
header: function (options) {
// start
var tmpl = "<tr>";
// add checkbox
if (options.show_item_checkboxes) {
tmpl += "<th>";
if (options.items.length > 0) {
tmpl +=
'<input type="checkbox" id="check_all" name=select_all_checkbox value="true">' +
'<input type="hidden" name=select_all_checkbox value="true">';
}
tmpl += "</th>";
}
// create header elements
for (const column of options.columns) {
if (column.visible) {
tmpl += `<th id="${column.key}-header">`;
if (column.sortable) {
tmpl += `<a href="javascript:void(0)" class="sort-link" sort_key="${column.key}">${column.label}</a>`;
} else {
tmpl += column.label;
}
tmpl += `<span class="sort-arrow">${column.extra}</span></th>`;
}
}
// finalize
tmpl += "</tr>";
// return template
return tmpl;
},
// template
body: function (options) {
// initialize
var tmpl = "";
var items_length = options.items.length;
// empty grid?
if (items_length === 0) {
// No results.
const filters = options.filters;
const searchTerm = filters["free-text-search"] || "";
const tags = filters.tags && filters.tags !== "All" ? `tags:${filters.tags} ` : "";
const name = filters.name && filters.name !== "All" ? `name:${filters.name}` : "";
const searchMsg = searchTerm || `${tags}${name}`;
const noItemsMsg = searchMsg ? `No matching entries found for <strong>${searchMsg}</strong>` : "No items";
tmpl += `<tr><td colspan="100"><em>${noItemsMsg}</em></td></tr>`;
}
// create rows
for (const item of options.items) {
// Tag current
tmpl += "<tr ";
if (options.current_item_id == item.id) {
tmpl += 'class="current"';
}
tmpl += ">";
// Item selection column
if (options.show_item_checkboxes) {
tmpl += `<td style="width: 1.5em;"><input type="checkbox" name="id" value="${item.encode_id}" id="${item.encode_id}" class="grid-row-select-checkbox" /></td>`;
}
// Data columns
for (const column of options.columns) {
if (column.visible) {
// Nowrap
var nowrap = "";
if (column.nowrap) {
nowrap = 'style="white-space:nowrap;"';
}
// get column settings
var column_settings = item.column_config[column.label];
// load attributes
var link = column_settings.link;
var value = column_settings.value;
var target = column_settings.target;
// unescape value
if ($.type(value) === "string") {
value = value.replace(/\/\//g, "/");
}
// Attach popup menu?
var popup_id = "";
if (column.attach_popup) {
popup_id = `grid-${item.encode_id}-popup`;
}
// Check for row wrapping
tmpl += `<td ${nowrap}>`;
// Determine cell content
if (column.delayed) {
tmpl += `<div class="delayed-value-${column.key}" data-id="${item.encode_id}" data-value="${value}"><span class="fa fa-spinner fa-spin"></span></div>`;
} else if (column.attach_popup && link) {
tmpl += `<div class="btn-group">
<button class="btn btn-secondary use-target" target="${target}" href="${link}" onclick="return false;">${value}</button>
<button id="${popup_id}" class="btn btn-secondary dropdown-toggle dropdown-toggle-split" data-toggle="dropdown"/>
</div>`;
} else if (column.attach_popup) {
tmpl += `<button id="${popup_id}" class="btn dropdown-toggle" data-toggle="dropdown">${value}</button>`;
} else if (link) {
tmpl += `<a class="use-target" target="${target}" href="${link}" onclick="return false;">${value}</a>`;
} else {
tmpl += `<label>${value || ""}</label>`;
}
tmpl += "</td>";
}
}
tmpl += "</tr>";
}
return tmpl;
},
// template
footer: function (options) {
// create template string
var tmpl = "";
// paging
if (options.use_paging && options.num_pages > 1) {
// get configuration
var num_page_links = options.num_page_links;
var cur_page_num = options.cur_page_num;
var num_pages = options.num_pages;
// First pass on min page.
var page_link_range = num_page_links / 2;
var min_page = cur_page_num - page_link_range;
var min_offset = 0;
if (min_page <= 0) {
// Min page is too low.
min_page = 1;
min_offset = page_link_range - (cur_page_num - min_page);
}
// Set max page.
var max_range = page_link_range + min_offset;
var max_page = cur_page_num + max_range;
var max_offset;
if (max_page <= num_pages) {
// Max page is fine.
max_offset = 0;
} else {
// Max page is too high.
max_page = num_pages;
// +1 to account for the +1 in the loop below.
max_offset = max_range - (max_page + 1 - cur_page_num);
}
// Second and final pass on min page to add any unused
// offset from max to min.
if (max_offset !== 0) {
min_page -= max_offset;
if (min_page < 1) {
min_page = 1;
}
}
// template header
tmpl += '<tr id="page-links-row">';
if (options.show_item_checkboxes) {
tmpl += "<td></td>";
}
tmpl += '<td colspan="100">' + '<span id="page-link-container">' + "Page:";
if (min_page > 1) {
tmpl +=
'<span class="page-link-grid" id="page-link-1"><a href="javascript:void(0);" page_num="1" onclick="return false;">1</a></span> ...';
}
// create page urls
for (var page_index = min_page; page_index < max_page + 1; page_index++) {
if (page_index == options.cur_page_num) {
tmpl += `<span class="page-link-grid inactive-link" id="page-link-${page_index}">${page_index}</span>`;
} else {
tmpl += `<span class="page-link-grid" id="page-link-${page_index}"><a href="javascript:void(0);" onclick="return false;" page_num="${page_index}">${page_index}</a></span>`;
}
}
// show last page
if (max_page < num_pages) {
tmpl += `...<span class="page-link-grid" id="page-link-${num_pages}"><a href="javascript:void(0);" onclick="return false;" page_num="${num_pages}">${num_pages}</a></span>`;
}
tmpl += "</span>";
// Show all link
tmpl += `
<span class="page-link-grid" id="show-all-link-span"> | <a href="javascript:void(0);" onclick="return false;" page_num="all">Show All</a></span>
</td>
</tr>`;
}
// Grid operations for multiple items.
if (options.show_item_checkboxes) {
// start template
tmpl += `
<tr>
<input type="hidden" id="operation" name="operation" value="">
<td></td>
<td colspan="100">
For <span class="grid-selected-count"></span> selected items:
`;
// configure buttons for operations
for (const operation of options.operations) {
if (operation.allow_multiple) {
tmpl += `<input type="button" value="${operation.label}" class="operation-button action-button">&nbsp;`;
}
}
// finalize template
tmpl += "</td>" + "</tr>";
}
// count global operations
var found_global = false;
for (const operation of options.operations) {
if (operation.global_operation) {
found_global = true;
break;
}
}
// add global operations
if (found_global) {
tmpl += "<tr>" + '<td colspan="100">';
for (const operation of options.operations) {
if (operation.global_operation) {
tmpl += `<a class="action-button" href="${operation.global_operation}">${operation.label}</a>`;
}
}
tmpl += "</td>" + "</tr>";
}
// add legend
if (options.legend) {
tmpl += `<tr><td colspan="100">${options.legend}</td></tr>`;
}
// return
return tmpl;
},
// template
message: function (options) {
var status = options.status;
if (["success", "ok"].indexOf(status) != -1) {
status = "done";
}
return `<p><div class="${status}message transient-message">${_.escape(
options.message
)}</div><div style="clear: both"></div></p>`;
},
// template
grid_filters: function (options) {
// get filters
var default_filter_dict = options.default_filter_dict;
var filters = options.filters;
// show advanced search if flag set or if there are filters for advanced search fields
var advanced_search_display = "none";
if (options.advanced_search) {
advanced_search_display = "block";
}
// identify columns with advanced filtering
var show_advanced_search_link = false;
for (const column of options.columns) {
if (column.filterable == "advanced") {
var column_key = column.key;
var f_key = filters[column_key];
var d_key = default_filter_dict[column_key];
if (f_key && d_key && f_key != d_key) {
advanced_search_display = "block";
}
show_advanced_search_link = true;
}
}
// hide standard search if advanced is shown
var standard_search_display = "block";
if (advanced_search_display == "block") {
standard_search_display = "none";
}
//
// standard search
//
var tmpl = `<div id="standard-search" style="display: ${standard_search_display};"><table><tr><td style="padding: 0;"><table>`;
// add standard filters
for (const column of options.columns) {
if (column.filterable == "standard") {
tmpl += this.grid_column_filter(options, column);
}
}
// finalize standard search
tmpl += "</table>" + "</td>" + "</tr>" + "<tr>" + "<td>";
// show advanced search link in standard display
if (show_advanced_search_link) {
tmpl += '<a href="javascript:void(0)" class="advanced-search-toggle">Advanced Search</a>';
}
// finalize standard search display
tmpl += "</td>" + "</tr>" + "</table>" + "</div>";
//
// advanced search
//
tmpl += `<div id="advanced-search" style="display: ${advanced_search_display}; margin-top: 5px;"><table><tr><td style="text-align: left" colspan="100"><a href="javascript:void(0)" class="advanced-search-toggle">Close Advanced Search</a></td></tr>`;
// add advanced filters
for (const column of options.columns) {
if (column.filterable == "advanced") {
tmpl += this.grid_column_filter(options, column);
}
}
// finalize advanced search template
tmpl += "</table>" + "</div>";
// return template
return tmpl;
},
// template
grid_column_filter: function (options, column) {
// collect parameters
var filters = options.filters;
var column_label = column.label;
var column_key = column.key;
if (column.filterable == "advanced") {
column_label = column_label.toLowerCase();
}
// start
var tmpl = "<tr>";
if (column.filterable == "advanced") {
tmpl += `<td align="left" style="padding-left: 10px">${column_label}:</td>`;
}
tmpl += '<td style="padding-bottom: 1px;">';
if (column.is_text) {
tmpl += `<form class="text-filter-form" column_key="${column_key}" action="${options.url}" method="get" >`;
// Carry forward filtering criteria with hidden inputs.
for (const column of options.columns) {
var filter_value = filters[column.key];
if (filter_value && filter_value != "All") {
if (column.is_text) {
filter_value = JSON.stringify(filter_value);
}
tmpl += `<input type="hidden" id="${column.key}" name="f-${column.key}" value="${filter_value}"/>`;
}
}
// Print current filtering criteria and links to delete.
tmpl += `<span id="${column_key}-filtering-criteria">`;
// add filters
var column_filter = filters[column_key];
if (column_filter) {
// identify type
var type = $.type(column_filter);
// single filter value
if (type == "string") {
if (column_filter != "All") {
// append template
tmpl += this.filter_element(column_key, column_filter);
}
}
// multiple filter values
if (type == "array") {
for (const i in column_filter) {
// copy filters and remove entry
var params = column_filter;
params = params.slice(i);
// append template
tmpl += this.filter_element(column_key, column_filter[i]);
}
}
}
// close span
tmpl += "</span>";
// Set value, size of search input field. Minimum size is 20 characters.
var value = "";
var size = 20;
if (column.filterable == "standard") {
value = column.label.toLowerCase();
if (value.length < 20) {
size = value.length;
}
// +4 to account for space after placeholder
size = size + 4;
}
// print input field for column
tmpl += `
<span class="search-box">
<input class="search-box-input" id="input-${column_key}-filter" name="f-${column_key}" type="text" placeholder="${value}" size="${size}"/>
<button type="submit" style="background: transparent; border: none; padding: 4px; margin: 0px;">
<i class="fa fa-search"></i>
</button>
</span>
</form>`;
} else {
// filter criteria
tmpl += `<span id="${column_key}-filtering-criteria">`;
// add category filters
var seperator = false;
for (var cf_label in options.categorical_filters[column_key]) {
// get category filter
var cf = options.categorical_filters[column_key][cf_label];
// each filter will have only a single argument, so get that single argument
var cf_key = "";
var cf_arg = "";
for (var key in cf) {
cf_key = key;
cf_arg = cf[key];
}
// add seperator
if (seperator) {
tmpl += " | ";
}
seperator = true;
// add category
var filter = filters[column_key];
if (filter && cf[column_key] && filter == cf_arg) {
tmpl += `<span class="categorical-filter ${column_key}-filter current-filter">${cf_label}</span>`;
} else {
tmpl += `<span class="categorical-filter ${column_key}-filter"><a href="javascript:void(0);" filter_key="${cf_key}" filter_val="${cf_arg}">${cf_label}</a></span>`;
}
}
tmpl += "</span>";
}
tmpl += "</td>" + "</tr>";
// return template
return tmpl;
},
// template for filter items
filter_element: function (filter_key, filter_value) {
filter_value = sanitize(filter_value);
return `<span class="text-filter-val">${filter_value}<a href="javascript:void(0);" filter_key="${filter_key}" filter_val="${filter_value}"><i class="fa fa-times" style="padding-left: 5px; padding-bottom: 6px;"/></a></span>`;
},
};
-681
View File
@@ -1,681 +0,0 @@
import { getGalaxyInstance } from "app";
import Backbone from "backbone";
import $ from "jquery";
import GridModel from "mvc/grid/grid-model";
import Templates from "mvc/grid/grid-template";
import PopupMenu from "mvc/ui/popup-menu";
import { init_refresh_on_change } from "onload/globalInits/init_refresh_on_change";
import slugify from "slugify";
import LoadingIndicator from "ui/loading-indicator";
import _ from "underscore";
import Utils from "utils/utils";
// This is necessary so that, when nested arrays are used in ajax/post/get methods, square brackets ('[]') are
// not appended to the identifier of a nested array.
$.ajaxSettings.traditional = true;
// grid view
export default Backbone.View.extend({
// model
grid: null,
// Initialize
initialize: function (grid_config) {
this.grid = new GridModel();
this.title = grid_config.title;
this.active_tab = grid_config.active_tab;
var self = this;
if (grid_config.url_base && !grid_config.items) {
LoadingIndicator.markViewAsLoading(this);
var url_data = grid_config.url_data || {};
_.each(grid_config.filters, (v, k) => {
url_data[`f-${k}`] = v;
});
$.ajax({
url: `${grid_config.url_base}?${$.param(url_data)}`,
success: function (response) {
response.embedded = grid_config.embedded;
response.filters = grid_config.filters || {};
self.init_grid(response);
},
});
} else {
// set element
this.setElement("<div>");
this.init_grid(grid_config);
}
// fix padding
if (grid_config.use_panels) {
$("#center").css({
padding: "10px",
overflow: "auto",
});
}
},
openAdvancedSearch: function () {
var isOpen = $("#advanced-search").is(":visible");
if (!isOpen) {
$("#standard-search").slideToggle("fast");
$("#advanced-search").slideToggle("fast");
}
},
// refresh frames
handle_refresh: function (refresh_frames) {
if (refresh_frames) {
if ($.inArray("history", refresh_frames) > -1) {
const Galaxy = getGalaxyInstance();
if (Galaxy && Galaxy.currHistoryPanel) {
Galaxy.currHistoryPanel.loadCurrentHistory();
}
}
}
},
// Initialize
init_grid: function (grid_config) {
this.grid.set(grid_config);
// get options
var options = this.grid.attributes;
if (this.allow_title_display && options.title) {
Utils.setWindowTitle(options.title);
}
// handle refresh requests
this.handle_refresh(options.refresh_frames);
// strip protocol and domain
var url = this.grid.get("url_base");
url = url.replace(/^.*\/\/[^/]+/, "");
this.grid.set("url_base", url);
// append main template
this.$el.html(Templates.grid(options));
// add a class identifier for styling purposes
this.$el.addClass(this.getRootClassName(grid_config));
// update div contents
this.$el.find("#grid-table-header").html(Templates.header(options));
this.$el.find("#grid-table-body").html(Templates.body(options));
this.$el.find("#grid-table-footer").html(Templates.footer(options));
// update message
if (options.message) {
this.$el.find("#grid-message").html(Templates.message(options));
var self = this;
if (options.use_hide_message) {
window.setTimeout(() => {
self.$el.find("#grid-message").html("");
}, 5000);
}
}
// configure elements
this.init_grid_elements();
this.init_grid_controls();
// attach global event handler
// TODO: redundant (the onload/standard page handlers do this) - but needed because these are constructed after page ready
init_refresh_on_change();
},
// Initialize grid controls
init_grid_controls: function () {
// link
var self = this;
// Initialize grid operation button.
this.$el.find(".operation-button").each(function () {
$(this).off();
$(this).click(function () {
self.submit_operation(this);
return false;
});
});
// Initialize text filters to select text on click and use normal font when user is typing.
this.$el.find("input[type=text]").each(function () {
$(this).off();
$(this)
.click(function () {
$(this).select();
})
.keyup(function () {
$(this).css("font-style", "normal");
});
});
// Initialize sort links.
this.$el.find(".sort-link").each(function () {
$(this).off();
$(this).click(function () {
self.set_sort_condition($(this).attr("sort_key"));
return false;
});
});
// Initialize text filters.
this.$el.find(".text-filter-form").each(function () {
$(this).off();
$(this).submit(function () {
var column_key = $(this).attr("column_key");
var text_input_obj = $(`#input-${column_key}-filter`);
var text_input = text_input_obj.val();
text_input_obj.val("");
self.add_filter_condition(column_key, text_input);
return false;
});
});
// Initialize categorical filters.
this.$el.find(".text-filter-val > a").each(function () {
$(this).off();
$(this).click(function () {
// Remove visible element.
$(this).parent().remove();
// Remove filter condition.
self.remove_filter_condition($(this).attr("filter_key"), $(this).attr("filter_val"));
// Return
return false;
});
});
// Initialize categorical filters.
this.$el.find(".categorical-filter > a").each(function () {
$(this).off();
$(this).click(function () {
self.set_categorical_filter($(this).attr("filter_key"), $(this).attr("filter_val"));
return false;
});
});
// Initialize standard, advanced search toggles.
this.$el.find(".advanced-search-toggle").each(function () {
$(this).off();
$(this).click(() => {
self.$el.find("#standard-search").slideToggle("fast");
self.$el.find("#advanced-search").slideToggle("fast");
return false;
});
});
// Add event to check all box
this.$el.find("#check_all").off();
this.$el.find("#check_all").on("click", () => {
self.check_all_items();
});
},
// Initialize grid elements.
init_grid_elements: function () {
// Initialize grid selection checkboxes.
this.$el.find(".grid").each(function () {
var checkboxes = $(this).find("input.grid-row-select-checkbox");
var check_count = $(this).find("span.grid-selected-count");
var update_checked = () => {
check_count.text($(checkboxes).filter(":checked").length);
};
$(checkboxes).each(function () {
$(this).change(update_checked);
});
update_checked();
});
// Initialize ratings.
if (this.$el.find(".community_rating_star").length !== 0) {
this.$el.find(".community_rating_star").rating({});
}
// get options
var options = this.grid.attributes;
var self = this;
//
// add page click events
//
this.$el.find(".page-link-grid > a").each(function () {
$(this).click(function () {
self.set_page($(this).attr("page_num"));
return false;
});
});
//
// add inbound/outbound events
//
this.$el.find(".use-target").each(function () {
$(this).click(function () {
self.execute({
href: $(this).attr("href"),
target: $(this).attr("target"),
});
return false;
});
});
// empty grid?
var items_length = options.items.length;
if (items_length === 0) {
return;
}
// add operation popup menus
_.each(options.items, (item, index) => {
var button = self.$(`#grid-${item.encode_id}-popup`).off();
var popup = new PopupMenu(button);
_.each(options.operations, (operation) => {
self.add_operation(popup, operation, item);
});
});
},
/** Add an operation to the items menu */
add_operation: function (popup, operation, item) {
var self = this;
var settings = item.operation_config[operation.label];
if (settings.allowed && operation.allow_popup) {
popup.addItem({
html: operation.label,
href: settings.url_args,
target: settings.target,
confirmation_text: operation.confirm,
func: function (e) {
e.preventDefault();
var label = $(e.target).html();
if (operation.onclick) {
operation.onclick(item.encode_id);
} else {
self.execute(this.findItemByHtml(label));
}
},
});
}
},
// Add a condition to the grid filter; this adds the condition and refreshes the grid.
add_filter_condition: function (name, value) {
// Do nothing is value is empty.
if (value === "") {
return false;
}
// Add condition to grid.
this.grid.add_filter(name, value, true);
this.render_filter_button(name, value);
// execute
this.go_page_one();
this.execute();
},
render_filter_button: function (name, value) {
// Add button that displays filter and provides a button to delete it.
var t = $(Templates.filter_element(name, value));
var self = this;
t.click(function () {
// Remove visible element.
$(this).remove();
// Remove filter condition.
self.remove_filter_condition(name, value);
});
// append to container
var container = this.$el.find(`#${name}-filtering-criteria`);
container.append(t);
},
// Remove a condition to the grid filter; this adds the condition and refreshes the grid.
remove_filter_condition: function (name, value) {
// Remove filter condition.
this.grid.remove_filter(name, value);
// Execute
this.go_page_one();
this.execute();
},
// Set sort condition for grid.
set_sort_condition: function (col_key) {
// Set new sort condition. New sort is col_key if sorting new column; if reversing sort on
// currently sorted column, sort is reversed.
var cur_sort = this.grid.get("sort_key");
var new_sort = col_key;
if (cur_sort.indexOf(col_key) !== -1) {
// Reverse sort.
if (cur_sort.substring(0, 1) !== "-") {
new_sort = `-${col_key}`;
}
}
// Remove sort arrows elements.
this.$el.find(".sort-arrow").remove();
// Add sort arrow element to new sort column.
var sort_arrow = new_sort.substring(0, 1) == "-" ? "&uarr;" : "&darr;";
var t = $(`<span>${sort_arrow}</span>`).addClass("sort-arrow");
// Add to header
this.$el.find(`#${col_key}-header`).append(t);
// Update grid.
this.grid.set("sort_key", new_sort);
this.go_page_one();
this.execute();
},
// Set new value for categorical filter.
set_categorical_filter: function (name, new_value) {
// Update filter hyperlinks to reflect new filter value.
var category_filter = this.grid.get("categorical_filters")[name];
var cur_value = this.grid.get("filters")[name];
var self = this;
this.$el.find(`.${name}-filter`).each(function () {
var text = $.trim($(this).text());
var filter = category_filter[text];
var filter_value = filter[name];
if (filter_value == new_value) {
// Remove filter link since grid will be using this filter. It is assumed that
// this element has a single child, a hyperlink/anchor with text.
$(this).empty();
$(this).addClass("current-filter");
$(this).append(text);
} else if (filter_value == cur_value) {
// Add hyperlink for this filter since grid will no longer be using this filter. It is assumed that
// this element has a single child, a hyperlink/anchor.
$(this).empty();
var t = $(`<a href="javascript:void(0)" role="button">${text}</a>`);
t.click(() => {
self.set_categorical_filter(name, filter_value);
});
$(this).removeClass("current-filter");
$(this).append(t);
}
});
// Update grid.
this.grid.add_filter(name, new_value);
this.go_page_one();
this.execute();
},
// Set page to view.
set_page: function (new_page) {
// Update page hyperlink to reflect new page.
var self = this;
this.$el.find(".page-link").each(function () {
var id = $(this).attr("id");
var // Id has form 'page-link-<page_num>
page_num = parseInt(id.split("-")[2], 10);
var cur_page = self.grid.get("cur_page");
var text;
if (page_num === new_page) {
// Remove link to page since grid will be on this page. It is assumed that
// this element has a single child, a hyperlink/anchor with text.
text = $(this).children().text();
$(this).empty();
$(this).addClass("inactive-link");
$(this).text(text);
} else if (page_num === cur_page) {
// Add hyperlink to this page since grid will no longer be on this page. It is assumed that
// this element has a single child, a hyperlink/anchor.
text = $(this).text();
$(this).empty();
$(this).removeClass("inactive-link");
var t = $(`<a href="javascript:void(0)" role="button">${text}</a>`);
t.click(() => {
self.set_page(page_num);
});
$(this).append(t);
}
});
if (new_page === "all") {
this.grid.set("cur_page", new_page);
} else {
this.grid.set("cur_page", parseInt(new_page, 10));
}
this.execute();
},
// confirmation/submission of operation request
submit_operation: function (operation_button, confirmation_text) {
// identify operation
var operation_name = $(operation_button).val();
// verify any item is selected
var number_of_checked_ids = this.$el.find('input[name="id"]:checked').length;
if (number_of_checked_ids < 1) {
return false;
}
// Check to see if there's grid confirmation text for this operation
var operation = _.findWhere(this.grid.attributes.operations, {
label: operation_name,
});
if (operation && !confirmation_text) {
confirmation_text = operation.confirm || "";
}
// collect ids
var item_ids = [];
this.$el.find("input[name=id]:checked").each(function () {
item_ids.push($(this).val());
});
// execute operation
var options = {
operation: operation_name,
id: item_ids,
confirmation_text: confirmation_text,
};
if (operation.target == "top" || operation.target == "center") {
options = _.extend(options, {
href: operation.href,
target: operation.target,
});
}
this.execute(options);
return true;
},
check_all_items: function () {
var check = this.$(".grid-row-select-checkbox");
var state = this.$("#check_all").prop("checked");
_.each(check, (c) => {
$(c).prop("checked", state);
});
this.init_grid_elements();
},
// Go back to page one; this is useful when a filter is applied.
go_page_one: function () {
// Need to go back to page 1 if not showing all.
var cur_page = this.grid.get("cur_page");
if (cur_page !== null && cur_page !== undefined && cur_page !== "all") {
this.grid.set("cur_page", 1);
}
},
//
// execute operations and hyperlink requests
//
execute: function (options) {
// get url
var id = null;
var href = null;
var operation = null;
var confirmation_text = null;
var target = null;
// check for options
if (options) {
// get options
href = options.href;
operation = options.operation;
id = options.id;
confirmation_text = options.confirmation_text;
target = options.target;
// check if input contains the operation tag
if (href !== undefined && href.indexOf("operation=") != -1) {
// Get operation, id in hyperlink's href.
var href_parts = href.split("?");
if (href_parts.length > 1) {
var href_parms_str = href_parts[1];
var href_parms = href_parms_str.split("&");
for (var index = 0; index < href_parms.length; index++) {
if (href_parms[index].indexOf("operation") != -1) {
// Found operation parm; get operation value.
operation = href_parms[index].split("=")[1];
operation = operation.replace(/\+/g, " ");
} else if (href_parms[index].indexOf("id") != -1) {
// Found id parm; get id value.
id = href_parms[index].split("=")[1];
}
}
}
}
}
// check for operation details
if (operation && id) {
// show confirmation box
if (
confirmation_text &&
confirmation_text !== "" &&
confirmation_text != "None" &&
confirmation_text != "null"
) {
if (!window.confirm(confirmation_text)) {
return false;
}
}
// use small characters for operation?!
operation = operation.toLowerCase();
// Update grid.
this.grid.set({
operation: operation,
item_ids: id,
});
// Do operation. If operation cannot be performed asynchronously, redirect to location.
if (target == "top") {
window.top.location = `${href}?${$.param(this.grid.get_url_data())}`;
} else if (target == "center") {
$("#galaxy_main").attr("src", `${href}?${$.param(this.grid.get_url_data())}`);
} else {
this.update_grid();
}
// done
return false;
}
// refresh grid
if (href) {
this.go_to(target, href);
return false;
}
// refresh grid
this.update_grid();
// done
return false;
},
// go to url
go_to: function (target, href) {
// get slide status
var advanced_search = this.$el.find("#advanced-search").is(":visible");
this.grid.set("advanced_search", advanced_search);
// get default url
if (!href) {
href = `${this.grid.get("url_base")}?${$.param(this.grid.get_url_data())}`;
}
// clear grid of transient request attributes.
this.grid.set({
operation: undefined,
item_ids: undefined,
});
switch (target) {
case "center":
$("#galaxy_main").attr("src", href);
break;
case "top":
window.top.location = href;
break;
default:
window.location = href;
}
},
// Update grid.
update_grid: function () {
// If there's an operation, do POST; otherwise, do GET.
var method = this.grid.get("operation") ? "POST" : "GET";
// Show overlay to indicate loading and prevent user actions.
this.$el.find(".loading-elt-overlay").show();
var self = this;
$.ajax({
type: method,
url: self.grid.get("url_base"),
data: self.grid.get_url_data(),
error: function () {
alert("Grid refresh failed");
},
success: function (response_text) {
// backup
var embedded = self.grid.get("embedded");
var insert = self.grid.get("insert");
var advanced_search = self.$el.find("#advanced-search").is(":visible");
// request new configuration
var json = response_text;
// update
json.embedded = embedded;
json.insert = insert;
json.advanced_search = advanced_search;
// Initialize new grid config
self.init_grid(json);
// Hide loading overlay.
self.$el.find(".loading-elt-overlay").hide();
},
complete: function () {
// Clear grid of transient request attributes.
self.grid.set({
operation: undefined,
item_ids: undefined,
});
},
});
},
// Generates a class name at the root of the view that we can
// use for conditional styling in the various kinds of grids
// instead of acres of if/then statements in javascript
getRootClassName({ title = "grid" }) {
return slugify(title).toLowerCase();
},
});