diff --git a/geonode/base/forms.py b/geonode/base/forms.py
index 62bc078506a..f9292102122 100644
--- a/geonode/base/forms.py
+++ b/geonode/base/forms.py
@@ -740,6 +740,7 @@ class Meta:
"was_approved",
"was_published",
"funders",
+ "related_identifier",
)
diff --git a/geonode/base/models.py b/geonode/base/models.py
index 858e25bbf29..a377b951d57 100644
--- a/geonode/base/models.py
+++ b/geonode/base/models.py
@@ -671,9 +671,8 @@ def __str__(self):
class RelatedIdentifier(models.Model):
- related_identifier = models.CharField(
- max_length=255, help_text=_("Identifiers of related resources. These must be globally unique identifiers.")
- )
+ related_identifer_help_text = _("Identifiers of related resources. These must be globally unique identifiers.")
+ related_identifier = models.CharField(max_length=255, help_text=related_identifer_help_text)
related_identifier_type = models.ForeignKey(RelatedIdentifierType, on_delete=models.CASCADE)
relation_type = models.ForeignKey(RelationType, on_delete=models.CASCADE)
@@ -685,32 +684,45 @@ class FundingReference(models.Model):
"""Funding Reference Identifiers"""
funder_name = models.CharField(
- max_length=255, help_text=_("Name of the funding provider. (e.g. European Commission)")
+ blank=True, null=True, max_length=255, help_text=_("Name of the funding provider. (e.g. European Commission)")
)
funder_identifier = models.CharField(
+ blank=True,
+ null=True,
max_length=255,
help_text=_(
"Uniquely identifies a funding entity, according to various types. (e.g. http://doi.org/10.13039/501100000780)"
),
)
- funder_identifier_type = models.CharField(max_length=255, help_text=_("The type of the Identifier. (e.g. BMBF)"))
+ funder_identifier_type = models.CharField(
+ blank=True, null=True, max_length=255, help_text=_("The type of the Identifier. (e.g. BMBF)")
+ )
def __str__(self):
return f"{self.funder_name}"
class Funder(models.Model):
- funding_reference = models.ForeignKey(FundingReference, null=False, blank=False, on_delete=models.CASCADE)
+ funders_help_text = _("List of funders, funded dataset creators")
+
+ funding_reference = models.ForeignKey(FundingReference, null=True, blank=True, on_delete=models.CASCADE)
award_number = models.CharField(
- max_length=255, help_text=_("The code assigned by the funder to a sponsored award (grant). (e.g. 282625)")
+ blank=True,
+ null=True,
+ max_length=255,
+ help_text=funders_help_text,
)
award_uri = models.CharField(
+ blank=True,
+ null=True,
max_length=255,
help_text=_(
"The URI leading to a page provided by the funder for more information about the award (grant). (e.g. http://cordis.europa.eu/project/rcn/100180_en.html)"
),
)
award_title = models.CharField(
+ blank=True,
+ null=True,
max_length=255,
help_text=_(
"The human readable title of the award (grant). (e.g. MOTivational strength of ecosystem services)"
@@ -1137,7 +1149,7 @@ class ResourceBase(PolymorphicModel, PermissionLevelMixin, ItemBase):
Funder, verbose_name=_("Funder names"), null=True, blank=True, help_text=funders_help_text
)
related_projects = models.ManyToManyField(
- RelatedProject, verbose_name=_("related project"), null=True, blank=True, help_text=related_projects_help_text
+ RelatedProject, verbose_name=_("Related project"), null=True, blank=True, help_text=related_projects_help_text
)
use_contraints = models.TextField(
diff --git a/geonode/layers/templates/datasets/dataset_metadata_advanced.html b/geonode/layers/templates/datasets/dataset_metadata_advanced.html
index d1c4b202bce..be512acfea4 100644
--- a/geonode/layers/templates/datasets/dataset_metadata_advanced.html
+++ b/geonode/layers/templates/datasets/dataset_metadata_advanced.html
@@ -129,11 +129,9 @@
{% trans "Edit Metadata" %}
{% block funder_form %}
+
-
+
+
{% endblock funder_form %}
+ {% block related_identifier_form %}
+
+
+
+ {% endblock related_identifier_form %}
@@ -377,8 +485,9 @@ {% trans "ERROR" %}
});
+ {% comment %} {% endcomment %}
{% endblock %}
\ No newline at end of file
diff --git a/geonode/layers/views.py b/geonode/layers/views.py
index b5ed1a52584..0a8f5c36c4e 100644
--- a/geonode/layers/views.py
+++ b/geonode/layers/views.py
@@ -53,7 +53,7 @@
from geonode.base.auth import get_or_create_token
from geonode.base.forms import CategoryForm, TKeywordForm, ThesaurusAvailableForm
from geonode.base.views import batch_modify
-from geonode.base.models import Thesaurus, TopicCategory, Funder
+from geonode.base.models import Thesaurus, TopicCategory, Funder, RelatedIdentifier
from geonode.base.enumerations import CHARSETS
from geonode.decorators import check_keyword_write_perms
from geonode.layers.forms import DatasetForm, DatasetTimeSerieForm, LayerAttributeForm, NewLayerUploadForm
@@ -363,6 +363,14 @@ def dataset_metadata(
extra=0,
min_num=1,
)
+
+ RelatedIdentifierFormset = modelformset_factory(
+ RelatedIdentifier,
+ fields=["related_identifier", "related_identifier_type", "relation_type"],
+ can_delete=True,
+ extra=0,
+ min_num=1,
+ )
current_keywords = [keyword.name for keyword in layer.keywords.all()]
topic_category = layer.category
@@ -419,10 +427,15 @@ def dataset_metadata(
"errors": [re.sub(re.compile("<.*?>"), "", str(err)) for err in attribute_form.errors],
}
return HttpResponse(json.dumps(out), content_type="application/json", status=400)
- funders_intial_values = Funder.objects.all().filter(resourcebase=layer)
+
funder_form = FunderFormset(
request.POST,
- prefix="funder_form",
+ prefix="form_funder",
+ )
+
+ related_identifier_form = RelatedIdentifierFormset(
+ request.POST,
+ prefix="form_related_identifier",
)
category_form = CategoryForm(
request.POST,
@@ -483,7 +496,13 @@ def dataset_metadata(
)
funders_intial_values = Funder.objects.all().filter(resourcebase=layer)
- funder_form = FunderFormset(prefix="funder_form", queryset=funders_intial_values)
+ funder_form = FunderFormset(prefix="form_funder", queryset=funders_intial_values)
+
+ related_identifier_intial_values = RelatedIdentifier.objects.all().filter(resourcebase=layer)
+ related_identifier_form = RelatedIdentifierFormset(
+ prefix="form_related_identifier", queryset=related_identifier_intial_values
+ )
+
category_form = CategoryForm(
prefix="category_choice_field", initial=topic_category.id if topic_category else None
)
@@ -555,6 +574,7 @@ def dataset_metadata(
and dataset_form.is_valid()
and attribute_form.is_valid()
and funder_form.is_valid()
+ and related_identifier_form.is_valid()
and category_form.is_valid()
and tkeywords_form.is_valid()
and timeseries_form.is_valid()
@@ -580,7 +600,13 @@ def dataset_metadata(
layer.set_contact_roles_from_metadata_edit(dataset_form)
funder_form.save()
instance = funder_form.save(commit=False)
+
layer.funders.add(*instance)
+
+ related_identifier_form.save()
+ instance = related_identifier_form.save(commit=False)
+ layer.related_identifier.add(*instance)
+
layer.save()
new_keywords = current_keywords if request.keyword_readonly else dataset_form.cleaned_data["keywords"]
@@ -694,6 +720,7 @@ def dataset_metadata(
"attribute_form": attribute_form,
"timeseries_form": timeseries_form,
"funder_form": funder_form,
+ "related_identifier_form": related_identifier_form,
"category_form": category_form,
"tkeywords_form": tkeywords_form,
"preview": getattr(settings, "GEONODE_CLIENT_LAYER_PREVIEW_LIBRARY", "mapstore"),
diff --git a/geonode/static/geonode/js/utils/formsetsInTabs.js b/geonode/static/geonode/js/utils/formsetsInTabs.js
index 5b78f4ac0be..8be8629a2c1 100644
--- a/geonode/static/geonode/js/utils/formsetsInTabs.js
+++ b/geonode/static/geonode/js/utils/formsetsInTabs.js
@@ -1,38 +1,66 @@
+for (let name of formsetsInTabs) {
-let totalForms = $('#id_' + prefix + '-TOTAL_FORMS').val();
-let initialForms = $('#id_' + prefix + '-INITIAL_FORMS').val();
-let maxForms = $('#id_' + prefix + '-MAX_NUM_FORMS').val();
-let minForms = $('#id_' + prefix + '-MIN_NUM_FORMS').val();
-let deleteInput = $("#id_FORM-xx-DELETE")
-let hiddenInput = $("#id_FORM-xx-id")
+ form = $('#' + name)
+ reOrder(form)
+ hideDeleteCheckbox(form)
+}
+
+
+function dataForm(form) {
+ instance = form.attr('id')
+ totalForms = $('#id_' + instance + '-TOTAL_FORMS').val();
+ initialForms = $('#id_' + instance + '-INITIAL_FORMS').val();
+ maxForms = $('#id_' + instance + '-MAX_NUM_FORMS').val();
+ minForms = $('#id_' + instance + '-MIN_NUM_FORMS').val();
+
+ allDelete = form.find('#DELETE')
-let allDelete = $('#DELETE')
+ actualForms = totalForms
-let actualForms = totalForms
+ templateTab = form.find('.templateTab')
+ templateContent = form.find('.templateContent')
+ allTabs = form.find('.allTabs')
+ allForms = form.find('.allContent')
+
+
+
+ return {
+ totalForms,
+ initialForms,
+ maxForms,
+ minForms,
+ allDelete,
+ actualForms,
+ templateTab,
+ templateContent,
+ allTabs,
+ allForms,
+ }
+}
-let templateTab = $('.templateTab')
-let templateContent = $('.templateContent')
-let allTabs = $('.allTabs')
-let allforms = $('.allContent')
-reOrder()
-hideDeleteCheckbox()
-$("#nav-add").on("click", function () {
+function addNewTab(element) {
+ button = $("#" + element.id)
+ form = $(element).closest("div[id^='form']")
+ infosForm = dataForm(form)
+ prefix = form.attr("id")
+ actualForms = infosForm.actualForms
label = Number(actualForms) + 1
- removeActive()
- newTab = templateTab.clone(true).removeClass('hidden')
+ removeActive(form)
+ newTab = infosForm.templateTab.clone(true).removeClass('hidden')
newTab.removeClass('templateTab').removeClass('nav-empty')
newTab.attr('id', '')
newTab.find('a').attr('href', '#' + prefix + '-' + actualForms)
newTab.attr('aria-controls', prefix + '-' + actualForms)
newTab.find('.newTabTex').text(label)
newTab.find('.newTabTex').addClass('tabTex').removeClass('newTabTex')
- newTab.insertBefore($('.li-add'))
- newTab.addClass('active')
+ newTab.insertBefore(form.find('.li-add'))
+ newTab.addClass('active')
+ templateContent = infosForm.templateContent
newContent = templateContent.clone(true).removeClass('hidden')
newContent.removeClass('templateContent').removeClass('nav-empty')
newContent.attr('id', prefix + '-' + actualForms)
@@ -42,38 +70,50 @@ $("#nav-add").on("click", function () {
$(this).attr('name', $(this).attr('name').replace("__prefix__", actualForms))
$(this).attr('id', $(this).attr('id').replace("__prefix__", actualForms))
})
- newContent.insertBefore($('.templateContent'))
+ newContent.insertBefore(form.find('.templateContent'))
actualForms++
$('#id_' + prefix + '-TOTAL_FORMS').attr("value", actualForms)
-});
+};
-$(".nav-remove").on("click", function () {
- removeActive()
- number = $(this).parent('a').attr('href').split('-')[1]
- tabToRemove = $(this).parent('a').parent('li')
+function removeTab(element) {
+ removeActive(form)
+ element = $(element)
+ form = element.closest("div[id^=form]")
+ infosForm = dataForm(form)
+ prefix = form.attr("id")
+ actualForms = infosForm.actualForms
+
+ number = element.parent('a').attr('href').split('-')[1]
+ tabToRemove = element.parent('a').parent('li')
tabToRemove.remove()
- contentToRemove = $('#' + prefix + '-' + number)
- contentToRemove.find('#DELETE input').prop("checked", true)
+ contentToRemove = form.find('#' + prefix + '-' + number)
+ contentToRemove.find('#DELETE input')
contentToRemove.removeAttr('role')
toDjango = contentToRemove.children('div')
- toDjango.hide().insertAfter(templateContent)
+ template = form.find('.templateContent')
+ toDjango.hide().insertAfter(template).find('#DELETE input').prop("checked", true)
contentToRemove.remove()
- $('.allContent').find('.tab-pane').first().addClass('active')
- $('.allTabs').find('li:first').addClass('active').find('a').attr('aria-expanded', true)
- reOrder()
+
+ form.find('.allContent').find('.tab-pane').first().addClass('active')
+ form.find('.allTabs').find('li:first').addClass('active').find('a').attr('aria-expanded', true)
+ reOrder(form)
actualForms--
+ return
-});
-function reOrder() {
+
+};
+
+function reOrder(form) {
+ prefix = form.attr("id")
counter = 0
- $('.allTabs').find('li:first').addClass('active').find('a').attr('aria-expanded', true)
- $('.allTabs').find('li a').each(
+
+ form.find('.allTabs').find('li a').each(
function () {
$(this).attr('href', '#' + prefix + '-' + counter)
$(this).attr('aria-controls', prefix + '-' + counter)
@@ -84,7 +124,7 @@ function reOrder() {
)
counterCont = 0
- $('.allContent').find('.tab-pane').each(
+ form.find('.allContent').find('.tab-pane').each(
function () {
if ($(this).attr('id') != 'templateContent') {
$(this).attr('id', prefix + '-' + counterCont)
@@ -99,14 +139,18 @@ function reOrder() {
)
}
+form.find('.allTabs').find('li:first').addClass('active').find('a').attr('aria-expanded', true)
+
+form.find('tab-content').find('.tab-pane').removeClass('active')
+form.find('tab-content').find('.tab-pane:first').addClass('active')
-function removeActive() {
- $('.allTabs').find('li').each(
+function removeActive(form) {
+ form.find('.allTabs').find('li').each(
function () {
$(this).removeClass('active')
$(this).find('a').attr('aria-expanded', false)
})
- $('.allContent').find('.tab-pane').each(
+ form.find('.allContent').find('.tab-pane').each(
function () {
$(this).removeClass('active')
@@ -114,7 +158,7 @@ function removeActive() {
}
-function hideDeleteCheckbox() {
- allforms.find('#DELETE').hide()
- allforms.find('#DELETE').prev().hide()
+function hideDeleteCheckbox(form) {
+ form.find('.allContent').find('#DELETE').hide()
+ form.find('.allContent').find('#DELETE').prev().hide()
}