diff --git a/InvenTree/InvenTree/models.py b/InvenTree/InvenTree/models.py
index 0f8350f84f..0448a69781 100644
--- a/InvenTree/InvenTree/models.py
+++ b/InvenTree/InvenTree/models.py
@@ -21,7 +21,8 @@ from django.dispatch import receiver
from mptt.models import MPTTModel, TreeForeignKey
from mptt.exceptions import InvalidMove
-from .validators import validate_tree_name
+from InvenTree.fields import InvenTreeURLField
+from InvenTree.validators import validate_tree_name
logger = logging.getLogger('inventree')
@@ -89,12 +90,15 @@ class ReferenceIndexingMixin(models.Model):
class InvenTreeAttachment(models.Model):
""" Provides an abstracted class for managing file attachments.
+ An attachment can be either an uploaded file, or an external URL
+
Attributes:
attachment: File
comment: String descriptor for the attachment
user: User associated with file upload
upload_date: Date the file was uploaded
"""
+
def getSubdir(self):
"""
Return the subdirectory under which attachments should be stored.
@@ -103,11 +107,32 @@ class InvenTreeAttachment(models.Model):
return "attachments"
+ def save(self, *args, **kwargs):
+ # Either 'attachment' or 'link' must be specified!
+ if not self.attachment and not self.link:
+ raise ValidationError({
+ 'attachment': _('Missing file'),
+ 'link': _('Missing external link'),
+ })
+
+ super().save(*args, **kwargs)
+
def __str__(self):
- return os.path.basename(self.attachment.name)
+ if self.attachment is not None:
+ return os.path.basename(self.attachment.name)
+ else:
+ return str(self.link)
attachment = models.FileField(upload_to=rename_attachment, verbose_name=_('Attachment'),
- help_text=_('Select file to attach'))
+ help_text=_('Select file to attach'),
+ blank=True, null=True
+ )
+
+ link = InvenTreeURLField(
+ blank=True, null=True,
+ verbose_name=_('Link'),
+ help_text=_('Link to external URL')
+ )
comment = models.CharField(blank=True, max_length=100, verbose_name=_('Comment'), help_text=_('File comment'))
@@ -123,7 +148,10 @@ class InvenTreeAttachment(models.Model):
@property
def basename(self):
- return os.path.basename(self.attachment.name)
+ if self.attachment:
+ return os.path.basename(self.attachment.name)
+ else:
+ return None
@basename.setter
def basename(self, fn):
diff --git a/InvenTree/InvenTree/serializers.py b/InvenTree/InvenTree/serializers.py
index 90cc857cdd..3785cfb292 100644
--- a/InvenTree/InvenTree/serializers.py
+++ b/InvenTree/InvenTree/serializers.py
@@ -239,22 +239,6 @@ class InvenTreeModelSerializer(serializers.ModelSerializer):
return data
-class InvenTreeAttachmentSerializer(InvenTreeModelSerializer):
- """
- Special case of an InvenTreeModelSerializer, which handles an "attachment" model.
-
- The only real addition here is that we support "renaming" of the attachment file.
- """
-
- # The 'filename' field must be present in the serializer
- filename = serializers.CharField(
- label=_('Filename'),
- required=False,
- source='basename',
- allow_blank=False,
- )
-
-
class InvenTreeAttachmentSerializerField(serializers.FileField):
"""
Override the DRF native FileField serializer,
@@ -284,6 +268,27 @@ class InvenTreeAttachmentSerializerField(serializers.FileField):
return os.path.join(str(settings.MEDIA_URL), str(value))
+class InvenTreeAttachmentSerializer(InvenTreeModelSerializer):
+ """
+ Special case of an InvenTreeModelSerializer, which handles an "attachment" model.
+
+ The only real addition here is that we support "renaming" of the attachment file.
+ """
+
+ attachment = InvenTreeAttachmentSerializerField(
+ required=False,
+ allow_null=False,
+ )
+
+ # The 'filename' field must be present in the serializer
+ filename = serializers.CharField(
+ label=_('Filename'),
+ required=False,
+ source='basename',
+ allow_blank=False,
+ )
+
+
class InvenTreeImageSerializerField(serializers.ImageField):
"""
Custom image serializer.
diff --git a/InvenTree/build/migrations/0033_auto_20211128_0151.py b/InvenTree/build/migrations/0033_auto_20211128_0151.py
new file mode 100644
index 0000000000..db8df848ce
--- /dev/null
+++ b/InvenTree/build/migrations/0033_auto_20211128_0151.py
@@ -0,0 +1,25 @@
+# Generated by Django 3.2.5 on 2021-11-28 01:51
+
+import InvenTree.fields
+import InvenTree.models
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('build', '0032_auto_20211014_0632'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='buildorderattachment',
+ name='link',
+ field=InvenTree.fields.InvenTreeURLField(blank=True, help_text='Link to external URL', null=True, verbose_name='Link'),
+ ),
+ migrations.AlterField(
+ model_name='buildorderattachment',
+ name='attachment',
+ field=models.FileField(blank=True, help_text='Select file to attach', null=True, upload_to=InvenTree.models.rename_attachment, verbose_name='Attachment'),
+ ),
+ ]
diff --git a/InvenTree/build/serializers.py b/InvenTree/build/serializers.py
index 4d3680ea98..35a3bb3baa 100644
--- a/InvenTree/build/serializers.py
+++ b/InvenTree/build/serializers.py
@@ -16,7 +16,7 @@ from rest_framework import serializers
from rest_framework.serializers import ValidationError
from InvenTree.serializers import InvenTreeModelSerializer, InvenTreeAttachmentSerializer
-from InvenTree.serializers import InvenTreeAttachmentSerializerField, UserSerializerBrief
+from InvenTree.serializers import UserSerializerBrief
import InvenTree.helpers
from InvenTree.serializers import InvenTreeDecimalField
@@ -516,8 +516,6 @@ class BuildAttachmentSerializer(InvenTreeAttachmentSerializer):
Serializer for a BuildAttachment
"""
- attachment = InvenTreeAttachmentSerializerField(required=True)
-
class Meta:
model = BuildOrderAttachment
@@ -525,6 +523,7 @@ class BuildAttachmentSerializer(InvenTreeAttachmentSerializer):
'pk',
'build',
'attachment',
+ 'link',
'filename',
'comment',
'upload_date',
diff --git a/InvenTree/build/templates/build/detail.html b/InvenTree/build/templates/build/detail.html
index 31e9f38080..8479c2819f 100644
--- a/InvenTree/build/templates/build/detail.html
+++ b/InvenTree/build/templates/build/detail.html
@@ -431,53 +431,17 @@ enableDragAndDrop(
}
);
-// Callback for creating a new attachment
-$('#new-attachment').click(function() {
-
- constructForm('{% url "api-build-attachment-list" %}', {
- fields: {
- attachment: {},
- comment: {},
- build: {
- value: {{ build.pk }},
- hidden: true,
- }
- },
- method: 'POST',
- onSuccess: reloadAttachmentTable,
- title: '{% trans "Add Attachment" %}',
- });
-});
-
-loadAttachmentTable(
- '{% url "api-build-attachment-list" %}',
- {
- filters: {
- build: {{ build.pk }},
- },
- onEdit: function(pk) {
- var url = `/api/build/attachment/${pk}/`;
-
- constructForm(url, {
- fields: {
- filename: {},
- comment: {},
- },
- onSuccess: reloadAttachmentTable,
- title: '{% trans "Edit Attachment" %}',
- });
- },
- onDelete: function(pk) {
-
- constructForm(`/api/build/attachment/${pk}/`, {
- method: 'DELETE',
- confirmMessage: '{% trans "Confirm Delete Operation" %}',
- title: '{% trans "Delete Attachment" %}',
- onSuccess: reloadAttachmentTable,
- });
+loadAttachmentTable('{% url "api-build-attachment-list" %}', {
+ filters: {
+ build: {{ build.pk }},
+ },
+ fields: {
+ build: {
+ value: {{ build.pk }},
+ hidden: true,
}
}
-);
+});
$('#edit-notes').click(function() {
constructForm('{% url "api-build-detail" build.pk %}', {
diff --git a/InvenTree/order/migrations/0053_auto_20211128_0151.py b/InvenTree/order/migrations/0053_auto_20211128_0151.py
new file mode 100644
index 0000000000..bbe029b4af
--- /dev/null
+++ b/InvenTree/order/migrations/0053_auto_20211128_0151.py
@@ -0,0 +1,35 @@
+# Generated by Django 3.2.5 on 2021-11-28 01:51
+
+import InvenTree.fields
+import InvenTree.models
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('order', '0052_auto_20211014_0631'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='purchaseorderattachment',
+ name='link',
+ field=InvenTree.fields.InvenTreeURLField(blank=True, help_text='Link to external URL', null=True, verbose_name='Link'),
+ ),
+ migrations.AddField(
+ model_name='salesorderattachment',
+ name='link',
+ field=InvenTree.fields.InvenTreeURLField(blank=True, help_text='Link to external URL', null=True, verbose_name='Link'),
+ ),
+ migrations.AlterField(
+ model_name='purchaseorderattachment',
+ name='attachment',
+ field=models.FileField(blank=True, help_text='Select file to attach', null=True, upload_to=InvenTree.models.rename_attachment, verbose_name='Attachment'),
+ ),
+ migrations.AlterField(
+ model_name='salesorderattachment',
+ name='attachment',
+ field=models.FileField(blank=True, help_text='Select file to attach', null=True, upload_to=InvenTree.models.rename_attachment, verbose_name='Attachment'),
+ ),
+ ]
diff --git a/InvenTree/order/serializers.py b/InvenTree/order/serializers.py
index 983cd01a63..0528d57596 100644
--- a/InvenTree/order/serializers.py
+++ b/InvenTree/order/serializers.py
@@ -24,7 +24,6 @@ from InvenTree.serializers import InvenTreeAttachmentSerializer
from InvenTree.serializers import InvenTreeModelSerializer
from InvenTree.serializers import InvenTreeDecimalField
from InvenTree.serializers import InvenTreeMoneySerializer
-from InvenTree.serializers import InvenTreeAttachmentSerializerField
from InvenTree.status_codes import StockStatus
from part.serializers import PartBriefSerializer
@@ -377,8 +376,6 @@ class POAttachmentSerializer(InvenTreeAttachmentSerializer):
Serializers for the PurchaseOrderAttachment model
"""
- attachment = InvenTreeAttachmentSerializerField(required=True)
-
class Meta:
model = PurchaseOrderAttachment
@@ -386,6 +383,7 @@ class POAttachmentSerializer(InvenTreeAttachmentSerializer):
'pk',
'order',
'attachment',
+ 'link',
'filename',
'comment',
'upload_date',
@@ -597,8 +595,6 @@ class SOAttachmentSerializer(InvenTreeAttachmentSerializer):
Serializers for the SalesOrderAttachment model
"""
- attachment = InvenTreeAttachmentSerializerField(required=True)
-
class Meta:
model = SalesOrderAttachment
@@ -607,6 +603,7 @@ class SOAttachmentSerializer(InvenTreeAttachmentSerializer):
'order',
'attachment',
'filename',
+ 'link',
'comment',
'upload_date',
]
diff --git a/InvenTree/order/templates/order/purchase_order_detail.html b/InvenTree/order/templates/order/purchase_order_detail.html
index 257707347a..3a6ea090d5 100644
--- a/InvenTree/order/templates/order/purchase_order_detail.html
+++ b/InvenTree/order/templates/order/purchase_order_detail.html
@@ -124,51 +124,16 @@
}
);
- loadAttachmentTable(
- '{% url "api-po-attachment-list" %}',
- {
- filters: {
- order: {{ order.pk }},
- },
- onEdit: function(pk) {
- var url = `/api/order/po/attachment/${pk}/`;
-
- constructForm(url, {
- fields: {
- filename: {},
- comment: {},
- },
- onSuccess: reloadAttachmentTable,
- title: '{% trans "Edit Attachment" %}',
- });
- },
- onDelete: function(pk) {
-
- constructForm(`/api/order/po/attachment/${pk}/`, {
- method: 'DELETE',
- confirmMessage: '{% trans "Confirm Delete Operation" %}',
- title: '{% trans "Delete Attachment" %}',
- onSuccess: reloadAttachmentTable,
- });
+ loadAttachmentTable('{% url "api-po-attachment-list" %}', {
+ filters: {
+ order: {{ order.pk }},
+ },
+ fields: {
+ order: {
+ value: {{ order.pk }},
+ hidden: true,
}
}
- );
-
- $("#new-attachment").click(function() {
-
- constructForm('{% url "api-po-attachment-list" %}', {
- method: 'POST',
- fields: {
- attachment: {},
- comment: {},
- order: {
- value: {{ order.pk }},
- hidden: true,
- },
- },
- reload: true,
- title: '{% trans "Add Attachment" %}',
- });
});
loadStockTable($("#stock-table"), {
diff --git a/InvenTree/order/templates/order/sales_order_detail.html b/InvenTree/order/templates/order/sales_order_detail.html
index 887ecd390c..1cf2ce06cc 100644
--- a/InvenTree/order/templates/order/sales_order_detail.html
+++ b/InvenTree/order/templates/order/sales_order_detail.html
@@ -110,55 +110,21 @@
},
label: 'attachment',
success: function(data, status, xhr) {
- location.reload();
+ reloadAttachmentTable();
}
}
);
- loadAttachmentTable(
- '{% url "api-so-attachment-list" %}',
- {
- filters: {
- order: {{ order.pk }},
+ loadAttachmentTable('{% url "api-so-attachment-list" %}', {
+ filters: {
+ order: {{ order.pk }},
+ },
+ fields: {
+ order: {
+ value: {{ order.pk }},
+ hidden: true,
},
- onEdit: function(pk) {
- var url = `/api/order/so/attachment/${pk}/`;
-
- constructForm(url, {
- fields: {
- filename: {},
- comment: {},
- },
- onSuccess: reloadAttachmentTable,
- title: '{% trans "Edit Attachment" %}',
- });
- },
- onDelete: function(pk) {
- constructForm(`/api/order/so/attachment/${pk}/`, {
- method: 'DELETE',
- confirmMessage: '{% trans "Confirm Delete Operation" %}',
- title: '{% trans "Delete Attachment" %}',
- onSuccess: reloadAttachmentTable,
- });
- }
}
- );
-
- $("#new-attachment").click(function() {
-
- constructForm('{% url "api-so-attachment-list" %}', {
- method: 'POST',
- fields: {
- attachment: {},
- comment: {},
- order: {
- value: {{ order.pk }},
- hidden: true
- }
- },
- onSuccess: reloadAttachmentTable,
- title: '{% trans "Add Attachment" %}'
- });
});
loadBuildTable($("#builds-table"), {
diff --git a/InvenTree/part/migrations/0075_auto_20211128_0151.py b/InvenTree/part/migrations/0075_auto_20211128_0151.py
new file mode 100644
index 0000000000..d484a7adce
--- /dev/null
+++ b/InvenTree/part/migrations/0075_auto_20211128_0151.py
@@ -0,0 +1,25 @@
+# Generated by Django 3.2.5 on 2021-11-28 01:51
+
+import InvenTree.fields
+import InvenTree.models
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('part', '0074_partcategorystar'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='partattachment',
+ name='link',
+ field=InvenTree.fields.InvenTreeURLField(blank=True, help_text='Link to external URL', null=True, verbose_name='Link'),
+ ),
+ migrations.AlterField(
+ model_name='partattachment',
+ name='attachment',
+ field=models.FileField(blank=True, help_text='Select file to attach', null=True, upload_to=InvenTree.models.rename_attachment, verbose_name='Attachment'),
+ ),
+ ]
diff --git a/InvenTree/part/serializers.py b/InvenTree/part/serializers.py
index 388faf1ca2..1be81c16ba 100644
--- a/InvenTree/part/serializers.py
+++ b/InvenTree/part/serializers.py
@@ -75,8 +75,6 @@ class PartAttachmentSerializer(InvenTreeAttachmentSerializer):
Serializer for the PartAttachment class
"""
- attachment = InvenTreeAttachmentSerializerField(required=True)
-
class Meta:
model = PartAttachment
@@ -85,6 +83,7 @@ class PartAttachmentSerializer(InvenTreeAttachmentSerializer):
'part',
'attachment',
'filename',
+ 'link',
'comment',
'upload_date',
]
diff --git a/InvenTree/part/templates/part/detail.html b/InvenTree/part/templates/part/detail.html
index a737bfa6fc..4cf6f5e824 100644
--- a/InvenTree/part/templates/part/detail.html
+++ b/InvenTree/part/templates/part/detail.html
@@ -999,36 +999,17 @@
});
onPanelLoad("part-attachments", function() {
- loadAttachmentTable(
- '{% url "api-part-attachment-list" %}',
- {
- filters: {
- part: {{ part.pk }},
- },
- onEdit: function(pk) {
- var url = `/api/part/attachment/${pk}/`;
-
- constructForm(url, {
- fields: {
- filename: {},
- comment: {},
- },
- title: '{% trans "Edit Attachment" %}',
- onSuccess: reloadAttachmentTable,
- });
- },
- onDelete: function(pk) {
- var url = `/api/part/attachment/${pk}/`;
-
- constructForm(url, {
- method: 'DELETE',
- confirmMessage: '{% trans "Confirm Delete Operation" %}',
- title: '{% trans "Delete Attachment" %}',
- onSuccess: reloadAttachmentTable,
- });
+ loadAttachmentTable('{% url "api-part-attachment-list" %}', {
+ filters: {
+ part: {{ part.pk }},
+ },
+ fields: {
+ part: {
+ value: {{ part.pk }},
+ hidden: true
}
}
- );
+ });
enableDragAndDrop(
'#attachment-dropzone',
@@ -1043,26 +1024,6 @@
}
}
);
-
- $("#new-attachment").click(function() {
-
- constructForm(
- '{% url "api-part-attachment-list" %}',
- {
- method: 'POST',
- fields: {
- attachment: {},
- comment: {},
- part: {
- value: {{ part.pk }},
- hidden: true,
- }
- },
- onSuccess: reloadAttachmentTable,
- title: '{% trans "Add Attachment" %}',
- }
- )
- });
});
diff --git a/InvenTree/stock/migrations/0070_auto_20211128_0151.py b/InvenTree/stock/migrations/0070_auto_20211128_0151.py
new file mode 100644
index 0000000000..a2f6ef322d
--- /dev/null
+++ b/InvenTree/stock/migrations/0070_auto_20211128_0151.py
@@ -0,0 +1,25 @@
+# Generated by Django 3.2.5 on 2021-11-28 01:51
+
+import InvenTree.fields
+import InvenTree.models
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('stock', '0069_auto_20211109_2347'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='stockitemattachment',
+ name='link',
+ field=InvenTree.fields.InvenTreeURLField(blank=True, help_text='Link to external URL', null=True, verbose_name='Link'),
+ ),
+ migrations.AlterField(
+ model_name='stockitemattachment',
+ name='attachment',
+ field=models.FileField(blank=True, help_text='Select file to attach', null=True, upload_to=InvenTree.models.rename_attachment, verbose_name='Attachment'),
+ ),
+ ]
diff --git a/InvenTree/stock/serializers.py b/InvenTree/stock/serializers.py
index 840eb4793e..c74d674275 100644
--- a/InvenTree/stock/serializers.py
+++ b/InvenTree/stock/serializers.py
@@ -420,8 +420,6 @@ class StockItemAttachmentSerializer(InvenTree.serializers.InvenTreeAttachmentSer
user_detail = InvenTree.serializers.UserSerializerBrief(source='user', read_only=True)
- attachment = InvenTree.serializers.InvenTreeAttachmentSerializerField(required=True)
-
# TODO: Record the uploading user when creating or updating an attachment!
class Meta:
@@ -432,6 +430,7 @@ class StockItemAttachmentSerializer(InvenTree.serializers.InvenTreeAttachmentSer
'stock_item',
'attachment',
'filename',
+ 'link',
'comment',
'upload_date',
'user',
diff --git a/InvenTree/stock/templates/stock/item.html b/InvenTree/stock/templates/stock/item.html
index 9bafc2633c..9cc6d85aeb 100644
--- a/InvenTree/stock/templates/stock/item.html
+++ b/InvenTree/stock/templates/stock/item.html
@@ -221,55 +221,16 @@
}
);
- loadAttachmentTable(
- '{% url "api-stock-attachment-list" %}',
- {
- filters: {
- stock_item: {{ item.pk }},
- },
- onEdit: function(pk) {
- var url = `/api/stock/attachment/${pk}/`;
-
- constructForm(url, {
- fields: {
- filename: {},
- comment: {},
- },
- title: '{% trans "Edit Attachment" %}',
- onSuccess: reloadAttachmentTable
- });
- },
- onDelete: function(pk) {
- var url = `/api/stock/attachment/${pk}/`;
-
- constructForm(url, {
- method: 'DELETE',
- confirmMessage: '{% trans "Confirm Delete Operation" %}',
- title: '{% trans "Delete Attachment" %}',
- onSuccess: reloadAttachmentTable,
- });
+ loadAttachmentTable('{% url "api-stock-attachment-list" %}', {
+ filters: {
+ stock_item: {{ item.pk }},
+ },
+ fields: {
+ stock_item: {
+ value: {{ item.pk }},
+ hidden: true,
}
}
- );
-
- $("#new-attachment").click(function() {
-
- constructForm(
- '{% url "api-stock-attachment-list" %}',
- {
- method: 'POST',
- fields: {
- attachment: {},
- comment: {},
- stock_item: {
- value: {{ item.pk }},
- hidden: true,
- },
- },
- reload: true,
- title: '{% trans "Add Attachment" %}',
- }
- );
});
loadStockTestResultsTable(
diff --git a/InvenTree/templates/attachment_button.html b/InvenTree/templates/attachment_button.html
index e1561010c0..d220f4829d 100644
--- a/InvenTree/templates/attachment_button.html
+++ b/InvenTree/templates/attachment_button.html
@@ -1,5 +1,8 @@
{% load i18n %}
+
\ No newline at end of file
diff --git a/InvenTree/templates/js/translated/attachment.js b/InvenTree/templates/js/translated/attachment.js
index 5ff5786588..5c5af5682f 100644
--- a/InvenTree/templates/js/translated/attachment.js
+++ b/InvenTree/templates/js/translated/attachment.js
@@ -6,10 +6,57 @@
*/
/* exported
+ addAttachmentButtonCallbacks,
loadAttachmentTable,
reloadAttachmentTable,
*/
+
+/*
+ * Add callbacks to buttons for creating new attachments.
+ *
+ * Note: Attachments can also be external links!
+ */
+function addAttachmentButtonCallbacks(url, fields={}) {
+
+ // Callback for 'new attachment' button
+ $('#new-attachment').click(function() {
+
+ var file_fields = {
+ attachment: {},
+ comment: {},
+ };
+
+ Object.assign(file_fields, fields);
+
+ constructForm(url, {
+ fields: file_fields,
+ method: 'POST',
+ onSuccess: reloadAttachmentTable,
+ title: '{% trans "Add Attachment" %}',
+ });
+ });
+
+ // Callback for 'new link' button
+ $('#new-attachment-link').click(function() {
+
+ var link_fields = {
+ link: {},
+ comment: {},
+ };
+
+ Object.assign(link_fields, fields);
+
+ constructForm(url, {
+ fields: link_fields,
+ method: 'POST',
+ onSuccess: reloadAttachmentTable,
+ title: '{% trans "Add Link" %}',
+ });
+ });
+}
+
+
function reloadAttachmentTable() {
$('#attachment-table').bootstrapTable('refresh');
@@ -20,6 +67,8 @@ function loadAttachmentTable(url, options) {
var table = options.table || '#attachment-table';
+ addAttachmentButtonCallbacks(url, options.fields || {});
+
$(table).inventreeTable({
url: url,
name: options.name || 'attachments',
@@ -34,56 +83,77 @@ function loadAttachmentTable(url, options) {
$(table).find('.button-attachment-edit').click(function() {
var pk = $(this).attr('pk');
- if (options.onEdit) {
- options.onEdit(pk);
- }
+ constructForm(`${url}${pk}/`, {
+ fields: {
+ link: {},
+ comment: {},
+ },
+ processResults: function(data, fields, opts) {
+ // Remove the "link" field if the attachment is a file!
+ if (data.attachment) {
+ delete opts.fields.link;
+ }
+ },
+ onSuccess: reloadAttachmentTable,
+ title: '{% trans "Edit Attachment" %}',
+ });
});
// Add callback for 'delete' button
$(table).find('.button-attachment-delete').click(function() {
var pk = $(this).attr('pk');
- if (options.onDelete) {
- options.onDelete(pk);
- }
+ constructForm(`${url}${pk}/`, {
+ method: 'DELETE',
+ confirmMessage: '{% trans "Confirm Delete" %}',
+ title: '{% trans "Delete Attachment" %}',
+ onSuccess: reloadAttachmentTable,
+ });
});
},
columns: [
{
field: 'attachment',
- title: '{% trans "File" %}',
- formatter: function(value) {
+ title: '{% trans "Attachment" %}',
+ formatter: function(value, row) {
- var icon = 'fa-file-alt';
+ if (row.attachment) {
+ var icon = 'fa-file-alt';
- var fn = value.toLowerCase();
+ var fn = value.toLowerCase();
- if (fn.endsWith('.csv')) {
- icon = 'fa-file-csv';
- } else if (fn.endsWith('.pdf')) {
- icon = 'fa-file-pdf';
- } else if (fn.endsWith('.xls') || fn.endsWith('.xlsx')) {
- icon = 'fa-file-excel';
- } else if (fn.endsWith('.doc') || fn.endsWith('.docx')) {
- icon = 'fa-file-word';
- } else if (fn.endsWith('.zip') || fn.endsWith('.7z')) {
- icon = 'fa-file-archive';
+ if (fn.endsWith('.csv')) {
+ icon = 'fa-file-csv';
+ } else if (fn.endsWith('.pdf')) {
+ icon = 'fa-file-pdf';
+ } else if (fn.endsWith('.xls') || fn.endsWith('.xlsx')) {
+ icon = 'fa-file-excel';
+ } else if (fn.endsWith('.doc') || fn.endsWith('.docx')) {
+ icon = 'fa-file-word';
+ } else if (fn.endsWith('.zip') || fn.endsWith('.7z')) {
+ icon = 'fa-file-archive';
+ } else {
+ var images = ['.png', '.jpg', '.bmp', '.gif', '.svg', '.tif'];
+
+ images.forEach(function(suffix) {
+ if (fn.endsWith(suffix)) {
+ icon = 'fa-file-image';
+ }
+ });
+ }
+
+ var split = value.split('/');
+ var filename = split[split.length - 1];
+
+ var html = ` ${filename}`;
+
+ return renderLink(html, value);
+ } else if (row.link) {
+ var html = ` ${row.link}`;
+ return renderLink(html, row.link);
} else {
- var images = ['.png', '.jpg', '.bmp', '.gif', '.svg', '.tif'];
-
- images.forEach(function(suffix) {
- if (fn.endsWith(suffix)) {
- icon = 'fa-file-image';
- }
- });
+ return '-';
}
-
- var split = value.split('/');
- var filename = split[split.length - 1];
-
- var html = ` ${filename}`;
-
- return renderLink(html, value);
}
},
{