diff --git a/api_tests/draft_nodes/views/test_draft_node_detail.py b/api_tests/draft_nodes/views/test_draft_node_detail.py index 5bbbfa5b388..11369073813 100644 --- a/api_tests/draft_nodes/views/test_draft_node_detail.py +++ b/api_tests/draft_nodes/views/test_draft_node_detail.py @@ -55,6 +55,7 @@ def test_detail_response(self, app, user, user_two): assert res.status_code == 404 # cannot access draft node after it's been registered (it's now a node!) + draft_reg.title = 'test user generated title.' draft_reg.register(Auth(user)) url = '/{}draft_nodes/{}/'.format(API_BASE, draft_node._id) res = app.get(url, auth=user_two.auth, expect_errors=True) diff --git a/api_tests/draft_registrations/views/test_draft_registration_detail.py b/api_tests/draft_registrations/views/test_draft_registration_detail.py index d7e7626ac13..54ce2250932 100644 --- a/api_tests/draft_registrations/views/test_draft_registration_detail.py +++ b/api_tests/draft_registrations/views/test_draft_registration_detail.py @@ -95,7 +95,7 @@ def test_detail_view_returns_editable_fields_no_specified_node(self, app, user): res = app.get(url, auth=user.auth, expect_errors=True) attributes = res.json['data']['attributes'] - assert attributes['title'] == 'Untitled' + assert attributes['title'] == '' assert attributes['description'] == '' assert attributes['category'] == '' assert attributes['node_license'] is None diff --git a/api_tests/draft_registrations/views/test_draft_registration_list.py b/api_tests/draft_registrations/views/test_draft_registration_list.py index 3878e9d6001..4c4a7148d55 100644 --- a/api_tests/draft_registrations/views/test_draft_registration_list.py +++ b/api_tests/draft_registrations/views/test_draft_registration_list.py @@ -431,7 +431,7 @@ def test_draft_registration_attributes_not_copied_from_node(self, app, project_p res = app.post_json_api(url_draft_registrations, payload, auth=user.auth) assert res.status_code == 201 attributes = res.json['data']['attributes'] - assert attributes['title'] == 'Untitled' + assert attributes['title'] == '' assert attributes['description'] != project_public.description assert attributes['category'] != project_public.category assert set(attributes['tags']) != set([tag.name for tag in project_public.tags.all()]) diff --git a/api_tests/registrations/views/test_registration_list.py b/api_tests/registrations/views/test_registration_list.py index 601152b550b..bac1cf78e2f 100644 --- a/api_tests/registrations/views/test_registration_list.py +++ b/api_tests/registrations/views/test_registration_list.py @@ -1570,6 +1570,9 @@ def test_need_admin_perms_on_draft( payload_ver['data']['attributes']['draft_registration_id'] = draft_registration._id assert draft_registration.branched_from.is_admin_contributor(user) is False assert draft_registration.has_permission(user, permissions.ADMIN) is True + assert draft_registration.title is '' + draft_registration.title = 'test user generated title required' + draft_registration.save() res = app.post_json_api(url_registrations_ver, payload_ver, auth=user.auth) assert res.status_code == 201 @@ -1578,6 +1581,9 @@ def test_need_admin_perms_on_draft( assert draft_registration.branched_from.is_admin_contributor(user) is True assert draft_registration.has_permission(user, permissions.ADMIN) is True payload_ver['data']['attributes']['draft_registration_id'] = draft_registration._id + assert draft_registration.title is '' + draft_registration.title = 'test user generated title required' + draft_registration.save() res = app.post_json_api(url_registrations_ver, payload_ver, auth=user.auth) assert res.status_code == 201 diff --git a/osf/models/mixins.py b/osf/models/mixins.py index ee980e6d7ee..9960171049e 100644 --- a/osf/models/mixins.py +++ b/osf/models/mixins.py @@ -2261,24 +2261,26 @@ def stage_m2m_values(self, fieldname, resource, alternative_resource=None): else: return [] - def copy_editable_fields( - self, resource, alternative_resource=None, include_contributors=True, save=True, excluded_attributes=None - ): + def copy_editable_fields(self, resource, alternative_resource=None, include_contributors=True, save=True, excluded_attributes=None): """ - Copy editable fields from 'resource' to the current object. DraftRegistrations have different rules for creation - based on whether they are based on OSF Projects or are 'no-project` Registrations that will copu default - metadata information from the user, or some other source other then an OSF Project or Node. + This method copies various editable fields from the 'resource' object to the current object. Includes, title, + description, category, contributors, node_license, tags, subjects, and affiliated_institutions. + The field on the resource will always supersede the field on the alternative_resource. For example, copying + fields from the draft_registration to the registration. resource will be a DraftRegistration object, but the + alternative_resource will be a Node. DraftRegistration fields will trump Node fields. - :param Object resource: Primary resource to copy attributes from + :param Object resource: Primary resource where you want to copy attributes :param Object alternative_resource: Backup resource for copying attributes - :param bool include_contributors: Whether to also copy contributors - :param bool save: Whether to save the changes immediately - :param List excluded_attributes: List of attributes to exclude from copying + :param Boolean include_contributors: represents whether to also copy the resource's contributors + :param Boolean save: represents whether to save the resources changes immediately + :param List: a list of strings representing attributes to exclude from copying """ if not excluded_attributes: excluded_attributes = [] - self._copy_basic_attributes(resource, alternative_resource, excluded_attributes) + for attribute in ['title', 'description', 'category', 'node_license']: + if attribute not in excluded_attributes: + self.set_editable_attribute(attribute, resource, alternative_resource) if include_contributors: # Contributors will always come from "resource", as contributor constraints diff --git a/osf/models/registrations.py b/osf/models/registrations.py index a5ac5b8cfeb..92e1f32bcfb 100644 --- a/osf/models/registrations.py +++ b/osf/models/registrations.py @@ -1265,8 +1265,8 @@ def create_from_node(cls, user, schema, node=None, data=None, provider=None): if node: branched_from = node else: - branched_from = DraftNode.objects.create(creator=user, title='Untitled') - excluded_attributes = ['affiliated_institutions'] + branched_from = DraftNode.objects.create(creator=user, title=settings.DEFAULT_DRAFT_NODE_TITLE) + excluded_attributes.append('title') if not isinstance(branched_from, (Node, DraftNode)): raise DraftRegistrationStateError() diff --git a/osf_tests/test_draft_node.py b/osf_tests/test_draft_node.py index e8d2ef14324..288fb4c4dd9 100644 --- a/osf_tests/test_draft_node.py +++ b/osf_tests/test_draft_node.py @@ -22,6 +22,7 @@ get_default_metaschema, ) from website.project.signals import after_create_registration +from website import settings pytestmark = pytest.mark.django_db @@ -123,8 +124,8 @@ def test_create_draft_registration_without_node(self, user): schema=get_default_metaschema(), data=data, ) - assert draft.title == 'Untitled' - assert draft.branched_from.title == 'Untitled' + assert draft.title == '' + assert draft.branched_from.title == settings.DEFAULT_DRAFT_NODE_TITLE assert draft.branched_from.type == 'osf.draftnode' assert draft.branched_from.creator == user assert len(draft.logs.all()) == 0 diff --git a/osf_tests/test_draft_registration.py b/osf_tests/test_draft_registration.py index b6133c4e32a..2527df493e7 100644 --- a/osf_tests/test_draft_registration.py +++ b/osf_tests/test_draft_registration.py @@ -269,7 +269,7 @@ def test_create_from_node_draft_node(self, user): schema=factories.get_default_metaschema(), ) - assert draft.title == 'Untitled' + assert draft.title == '' assert draft.description == '' assert draft.category == '' assert user in draft.contributors.all() diff --git a/website/settings/defaults.py b/website/settings/defaults.py index 1438e90e07b..7c67bf55e90 100644 --- a/website/settings/defaults.py +++ b/website/settings/defaults.py @@ -2129,3 +2129,4 @@ def from_node_usage(cls, usage_bytes, private_limit=None, public_limit=None): PREPRINT_METRICS_START_DATE = datetime.datetime(2019, 1, 1) WAFFLE_VALUES_YAML = 'osf/features.yaml' +DEFAULT_DRAFT_NODE_TITLE = 'Untitled' diff --git a/website/templates/project/project_header.mako b/website/templates/project/project_header.mako index a5a054ba681..639f92ef1c7 100644 --- a/website/templates/project/project_header.mako +++ b/website/templates/project/project_header.mako @@ -41,7 +41,7 @@