diff --git a/InvenTree/templates/js/translated/build.js b/InvenTree/templates/js/translated/build.js index d9a74a725b..deecfb9213 100644 --- a/InvenTree/templates/js/translated/build.js +++ b/InvenTree/templates/js/translated/build.js @@ -1721,7 +1721,7 @@ function loadBuildOutputAllocationTable(buildInfo, output, options={}) { formatter: function(value, row) { if (row.location && row.location_detail) { - var text = row.location_detail.name; + var text = shortenString(row.location_detail.pathstring); var url = `/stock/location/${row.location}/`; return renderLink(text, url); diff --git a/InvenTree/templates/js/translated/helpers.js b/InvenTree/templates/js/translated/helpers.js index 5d0aed8bce..2f1619c906 100644 --- a/InvenTree/templates/js/translated/helpers.js +++ b/InvenTree/templates/js/translated/helpers.js @@ -13,8 +13,10 @@ sanitizeInputString, select2Thumbnail, setupNotesField, + shortenString, thumbnailImage yesNoLabel, + withTitle, */ function yesNoLabel(value) { @@ -36,6 +38,40 @@ function deleteButton(url, text='{% trans "Delete" %}') { } +/* + * Ensure a string does not exceed a maximum length. + * Useful for displaying long strings in tables, + * to ensure a very long string does not "overflow" the table + */ +function shortenString(input_string, options={}) { + + var max_length = options.max_length || 100; + + if (input_string == null) { + return null; + } + + input_string = input_string.toString(); + + // Easy option: input string is already short enough + if (input_string.length <= max_length) { + return input_string; + } + + var N = Math.floor(max_length / 2 - 1); + + var output_string = input_string.slice(0, N) + '...' + input_string.slice(-N); + + return output_string; +} + + +function withTitle(html, title, options={}) { + + return `
${html}
`; +} + + /* Format a decimal (floating point) number, to strip trailing zeros */ function formatDecimal(number, places=5) { @@ -214,24 +250,29 @@ function makeProgressBar(value, maximum, opts={}) { } +/* + * Render a URL for display + */ function renderLink(text, url, options={}) { if (url === null || url === undefined || url === '') { return text; } - var max_length = options.max_length || -1; + var max_length = options.max_length || 100; - // Shorten the displayed length if required - if ((max_length > 0) && (text.length > max_length)) { - var slice_length = (max_length - 3) / 2; - - var text_start = text.slice(0, slice_length); - var text_end = text.slice(-slice_length); - - text = `${text_start}...${text_end}`; + if (max_length > 0) { + text = shortenString(text, { + max_length: max_length, + }); } - return `${text}`; + var extras = ''; + + if (options.tooltip != false) { + extras += ` title="${url}"`; + } + + return `${text}`; } diff --git a/InvenTree/templates/js/translated/part.js b/InvenTree/templates/js/translated/part.js index 5b504d8dda..3e305301a3 100644 --- a/InvenTree/templates/js/translated/part.js +++ b/InvenTree/templates/js/translated/part.js @@ -1442,13 +1442,13 @@ function loadPartTable(table, url, options={}) { switchable: false, formatter: function(value, row) { - var name = row.full_name; + var name = shortenString(row.full_name); var display = imageHoverIcon(row.thumbnail) + renderLink(name, `/part/${row.pk}/`); display += makePartIcons(row); - return display; + return withTitle(display, row.full_name); } }; @@ -1463,11 +1463,13 @@ function loadPartTable(table, url, options={}) { title: '{% trans "Description" %}', formatter: function(value, row) { + var text = shortenString(value); + if (row.is_template) { - value = `${value}`; + text = `${text}`; } - return value; + return withTitle(text, row.description); } }); @@ -1476,8 +1478,11 @@ function loadPartTable(table, url, options={}) { field: 'category_detail', title: '{% trans "Category" %}', formatter: function(value, row) { + + var text = shortenString(row.category_detail.pathstring); + if (row.category) { - return renderLink(value.pathstring, `/part/category/${row.category}/`); + return withTitle(renderLink(text, `/part/category/${row.category}/`), row.category_detail.pathstring); } else { return '{% trans "No category" %}'; } @@ -1563,10 +1568,11 @@ function loadPartTable(table, url, options={}) { title: '{% trans "Link" %}', formatter: function(value) { return renderLink( - value, value, + value, + value, { - max_length: 32, remove_http: true, + tooltip: true, } ); } @@ -1976,7 +1982,7 @@ function loadPartCategoryTable(table, options) { html += renderLink( value, - `/part/category/${row.pk}/` + `/part/category/${row.pk}/`, ); if (row.starred) { @@ -1991,6 +1997,9 @@ function loadPartCategoryTable(table, options) { title: '{% trans "Description" %}', switchable: true, sortable: false, + formatter: function(value) { + return withTitle(shortenString(value), value); + } }, { field: 'pathstring', @@ -1998,6 +2007,9 @@ function loadPartCategoryTable(table, options) { switchable: !tree_view, visible: !tree_view, sortable: true, + formatter: function(value) { + return withTitle(shortenString(value), value); + } }, { field: 'part_count', diff --git a/InvenTree/templates/js/translated/stock.js b/InvenTree/templates/js/translated/stock.js index b2933f5024..e047590c7a 100644 --- a/InvenTree/templates/js/translated/stock.js +++ b/InvenTree/templates/js/translated/stock.js @@ -1606,7 +1606,7 @@ function locationDetail(row, showLink=true) { text = '{% trans "Assigned to Sales Order" %}'; url = `/order/sales-order/${row.sales_order}/`; } else if (row.location && row.location_detail) { - text = row.location_detail.pathstring; + text = shortenString(row.location_detail.pathstring); url = `/stock/location/${row.location}/`; } else { text = '{% trans "No stock location set" %}'; @@ -1707,7 +1707,7 @@ function loadStockTable(table, options) { var thumb = row.part_detail.thumbnail; var name = row.part_detail.full_name; - var html = imageHoverIcon(thumb) + renderLink(name, url); + var html = imageHoverIcon(thumb) + renderLink(shortenString(name), url); html += makePartIcons(row.part_detail); @@ -1728,7 +1728,8 @@ function loadStockTable(table, options) { visible: params['part_detail'], switchable: params['part_detail'], formatter: function(value, row) { - return row.part_detail.IPN; + var ipn = row.part_detail.IPN; + return withTitle(shortenString(ipn), ipn); }, }; @@ -1744,7 +1745,8 @@ function loadStockTable(table, options) { visible: params['part_detail'], switchable: params['part_detail'], formatter: function(value, row) { - return row.part_detail.description; + var description = row.part_detail.description; + return withTitle(shortenString(description), description); } }); @@ -2420,12 +2422,18 @@ function loadStockLocationTable(table, options) { title: '{% trans "Description" %}', switchable: true, sortable: false, + formatter: function(value) { + return withTitle(shortenString(value), value); + } }, { field: 'pathstring', title: '{% trans "Path" %}', switchable: true, sortable: true, + formatter: function(value) { + return withTitle(shortenString(value), value); + } }, { field: 'items', diff --git a/InvenTree/templates/js/translated/tables.js b/InvenTree/templates/js/translated/tables.js index 90e5f3f324..807051e65f 100644 --- a/InvenTree/templates/js/translated/tables.js +++ b/InvenTree/templates/js/translated/tables.js @@ -169,42 +169,6 @@ function downloadTableData(table, opts={}) { - -/** - * Render a URL for display - * @param {String} text - * @param {String} url - * @param {object} options - * @returns link text - */ -function renderLink(text, url, options={}) { - if (url === null || url === undefined || url === '') { - return text; - } - - var max_length = options.max_length || -1; - - var extra = ''; - - if (options.download) { - var fn = url.split('/').at(-1); - extra += ` download='${fn}'`; - } - - // Shorten the displayed length if required - if ((max_length > 0) && (text.length > max_length)) { - var slice_length = (max_length - 3) / 2; - - var text_start = text.slice(0, slice_length); - var text_end = text.slice(-slice_length); - - text = `${text_start}...${text_end}`; - } - - return `${text}`; -} - - function enableButtons(elements, enabled) { for (let item of elements) { $(item).prop('disabled', !enabled);