mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-24 16:30:27 +08:00
Remove legacy grid backbone wrapper from code base
This commit is contained in:
@@ -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)}`;
|
||||
},
|
||||
});
|
||||
@@ -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"> `;
|
||||
}
|
||||
}
|
||||
|
||||
// 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>`;
|
||||
},
|
||||
};
|
||||
@@ -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) == "-" ? "↑" : "↓";
|
||||
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();
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user