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);