diff --git a/projectroles/forms.py b/projectroles/forms.py index deecc474..47dd0531 100644 --- a/projectroles/forms.py +++ b/projectroles/forms.py @@ -397,11 +397,8 @@ def _set_app_setting_field(self, plugin_name, s_field, s_key, s_val): :param s_val: Setting value """ s_widget_attrs = s_val.get('widget_attrs') or {} - - # Set project type s_project_types = s_val.get('project_types') or [PROJECT_TYPE_PROJECT] s_widget_attrs['data-project-types'] = ','.join(s_project_types).lower() - if 'placeholder' in s_val: s_widget_attrs['placeholder'] = s_val.get('placeholder') setting_kwargs = { @@ -409,7 +406,67 @@ def _set_app_setting_field(self, plugin_name, s_field, s_key, s_val): 'label': s_val.get('label') or '{}.{}'.format(plugin_name, s_key), 'help_text': s_val['description'], } - if s_val['type'] == 'JSON': + + # Option + if ( + s_val.get('options') + and callable(s_val['options']) + and self.instance.pk + ): + values = s_val['options'](project=self.instance) + self.fields[s_field] = forms.ChoiceField( + choices=[ + ( + (str(value[0]), str(value[1])) + if isinstance(value, tuple) + else (str(value), str(value)) + ) + for value in values + ], + **setting_kwargs + ) + elif ( + s_val.get('options') + and callable(s_val['options']) + and not self.instance.pk + ): + values = s_val['options'](project=None) + self.fields[s_field] = forms.ChoiceField( + choices=[ + ( + (str(value[0]), str(value[1])) + if isinstance(value, tuple) + else (str(value), str(value)) + ) + for value in values + ], + **setting_kwargs + ) + elif s_val.get('options'): + self.fields[s_field] = forms.ChoiceField( + choices=[ + ( + (int(option), int(option)) + if s_val['type'] == 'INTEGER' + else (option, option) + ) + for option in s_val['options'] + ], + **setting_kwargs + ) + # Other types + elif s_val['type'] == 'STRING': + self.fields[s_field] = forms.CharField( + widget=forms.TextInput(attrs=s_widget_attrs), **setting_kwargs + ) + elif s_val['type'] == 'INTEGER': + self.fields[s_field] = forms.IntegerField( + widget=forms.NumberInput(attrs=s_widget_attrs), **setting_kwargs + ) + elif s_val['type'] == 'BOOLEAN': + self.fields[s_field] = forms.BooleanField(**setting_kwargs) + # JSON + elif s_val['type'] == 'JSON': # NOTE: Attrs MUST be supplied here (#404) if 'class' in s_widget_attrs: s_widget_attrs['class'] += ' sodar-json-input' @@ -418,89 +475,19 @@ def _set_app_setting_field(self, plugin_name, s_field, s_key, s_val): self.fields[s_field] = forms.CharField( widget=forms.Textarea(attrs=s_widget_attrs), **setting_kwargs ) - if self.instance.pk: - json_data = self.app_settings.get( - plugin_name=plugin_name, - setting_name=s_key, - project=self.instance, - ) - else: - json_data = self.app_settings.get_default( - plugin_name=plugin_name, - setting_name=s_key, - project=None, - ) - self.initial[s_field] = json.dumps(json_data) - else: - if s_val.get('options'): - if callable(s_val['options']) and self.instance.pk: - values = s_val['options'](project=self.instance) - self.fields[s_field] = forms.ChoiceField( - choices=[ - ( - (str(value[0]), str(value[1])) - if isinstance(value, tuple) - else (str(value), str(value)) - ) - for value in values - ], - **setting_kwargs - ) - elif callable(s_val['options']) and not self.instance.pk: - values = s_val['options'](project=None) - self.fields[s_field] = forms.ChoiceField( - choices=[ - ( - (str(value[0]), str(value[1])) - if isinstance(value, tuple) - else (str(value), str(value)) - ) - for value in values - ], - **setting_kwargs - ) - else: - self.fields[s_field] = forms.ChoiceField( - choices=[ - ( - (int(option), int(option)) - if s_val['type'] == 'INTEGER' - else (option, option) - ) - for option in s_val['options'] - ], - **setting_kwargs - ) - elif s_val['type'] == 'STRING': - self.fields[s_field] = forms.CharField( - widget=forms.TextInput(attrs=s_widget_attrs), - **setting_kwargs - ) - elif s_val['type'] == 'INTEGER': - self.fields[s_field] = forms.IntegerField( - widget=forms.NumberInput(attrs=s_widget_attrs), - **setting_kwargs - ) - elif s_val['type'] == 'BOOLEAN': - self.fields[s_field] = forms.BooleanField(**setting_kwargs) - - # Add optional attributes from plugin (#404) - # NOTE: Experimental! Use at your own risk! - self.fields[s_field].widget.attrs.update(s_widget_attrs) - # Set initial value - if self.instance.pk: - self.initial[s_field] = self.app_settings.get( - plugin_name=plugin_name, - setting_name=s_key, - project=self.instance, - ) - else: - self.initial[s_field] = self.app_settings.get_default( - plugin_name=plugin_name, - setting_name=s_key, - project=None, - ) + # Add optional attributes from plugin (#404) + # NOTE: Experimental! Use at your own risk! + self.fields[s_field].widget.attrs.update(s_widget_attrs) + # Set initial value + value = self.app_settings.get( + plugin_name=plugin_name, + setting_name=s_key, + project=self.instance if self.instance.pk else None, + ) + if s_val['type'] == 'JSON': + value = json.dumps(value) + self.initial[s_field] = value def _set_app_setting_notes(self, s_field, s_val, plugin): """ diff --git a/projectroles/views.py b/projectroles/views.py index 8253b9cb..94ba7db8 100644 --- a/projectroles/views.py +++ b/projectroles/views.py @@ -780,6 +780,14 @@ class ProjectSearchResultsView( template_name = 'projectroles/search_results.html' + def _handle_context(self, request, *args, **kwargs): + """Handle context and render to response in GET/POST requests""" + context = self.get_context_data(*args, **kwargs) + if not context['search_terms']: + messages.error(request, 'No search terms provided.') + return redirect(reverse('home')) + return super().render_to_response(context) + def get_context_data(self, *args, **kwargs): context = super().get_context_data(**kwargs) search_input = '' @@ -808,7 +816,6 @@ def get_context_data(self, *args, **kwargs): search_term += ' ' + s.lower() if search_term: search_terms = [search_term] - search_terms = list(dict.fromkeys(search_terms)) # Remove dupes for s in keyword_input: @@ -852,18 +859,10 @@ def get_context_data(self, *args, **kwargs): return context def get(self, request, *args, **kwargs): - context = self.get_context_data(*args, **kwargs) - if not context['search_terms']: - messages.error(request, 'No search terms provided.') - return redirect(reverse('home')) - return super().render_to_response(context) + return self._handle_context(request, *args, *kwargs) def post(self, request, *args, **kwargs): - context = self.get_context_data(*args, **kwargs) - if not context['search_terms']: - messages.error(request, 'No search terms provided.') - return redirect(reverse('home')) - return super().render_to_response(context) + return self._handle_context(request, *args, *kwargs) class ProjectAdvancedSearchView( diff --git a/userprofile/forms.py b/userprofile/forms.py index 845fbf3c..6b3be21a 100644 --- a/userprofile/forms.py +++ b/userprofile/forms.py @@ -33,6 +33,88 @@ class UserSettingsForm(SODARForm): """Form for configuring user settings""" + def _set_app_setting_field(self, plugin_name, s_field, s_key, s_val): + """ + Set user app setting field, widget and value. + + :param plugin_name: App plugin name + :param s_field: Form field name + :param s_key: Setting key + :param s_val: Setting value + """ + s_widget_attrs = s_val.get('widget_attrs') or {} + if 'placeholder' in s_val: + s_widget_attrs['placeholder'] = s_val.get('placeholder') + setting_kwargs = { + 'required': False, + 'label': s_val.get('label') or '{}.{}'.format(plugin_name, s_key), + 'help_text': s_val.get('description'), + } + # Disable global user settings if on target site + if ( + app_settings.get_global_value(s_val) + and settings.PROJECTROLES_SITE_MODE == SITE_MODE_TARGET + ): + setting_kwargs['label'] += ' ' + SETTING_DISABLE_LABEL + setting_kwargs['help_text'] += ' ' + SETTING_SOURCE_ONLY_MSG + setting_kwargs['disabled'] = True + + if s_val.get('options') and callable(s_val['options']): + self.fields[s_field] = forms.ChoiceField( + choices=[ + ( + (str(value[0]), str(value[1])) + if isinstance(value, tuple) + else (str(value), str(value)) + ) + for value in s_val['options'](user=self.user) + ], + **setting_kwargs, + ) + elif s_val.get('options'): + self.fields[s_field] = forms.ChoiceField( + choices=[ + ( + (int(option), int(option)) + if s_val['type'] == 'INTEGER' + else (option, option) + ) + for option in s_val['options'] + ], + **setting_kwargs, + ) + elif s_val['type'] == 'STRING': + self.fields[s_field] = forms.CharField( + widget=forms.TextInput(attrs=s_widget_attrs), + **setting_kwargs, + ) + elif s_val['type'] == 'INTEGER': + self.fields[s_field] = forms.IntegerField( + widget=forms.NumberInput(attrs=s_widget_attrs), + **setting_kwargs, + ) + elif s_val['type'] == 'BOOLEAN': + self.fields[s_field] = forms.BooleanField(**setting_kwargs) + elif s_val['type'] == 'JSON': + # NOTE: Attrs MUST be supplied here (#404) + if 'class' in s_widget_attrs: + s_widget_attrs['class'] += ' sodar-json-input' + else: + s_widget_attrs['class'] = 'sodar-json-input' + self.fields[s_field] = forms.CharField( + widget=forms.Textarea(attrs=s_widget_attrs), + **setting_kwargs, + ) + + # Modify initial value and attributes + self.fields[s_field].widget.attrs.update(s_widget_attrs) + value = app_settings.get( + plugin_name=plugin_name, setting_name=s_key, user=self.user + ) + if s_val['type'] == 'JSON': + value = json.dumps(value) + self.initial[s_field] = value + def __init__(self, *args, **kwargs): self.user = kwargs.pop('current_user') super().__init__(*args, **kwargs) @@ -54,95 +136,9 @@ def __init__(self, *args, **kwargs): plugin_name=name, user_modifiable=True, ) - for s_key, s_val in p_defs.items(): s_field = 'settings.{}.{}'.format(name, s_key) - s_widget_attrs = s_val.get('widget_attrs') or {} - if 'placeholder' in s_val: - s_widget_attrs['placeholder'] = s_val.get('placeholder') - setting_kwargs = { - 'required': False, - 'label': s_val.get('label') or '{}.{}'.format(name, s_key), - 'help_text': s_val.get('description'), - } - # Disable global user settings if on target site - if ( - app_settings.get_global_value(s_val) - and settings.PROJECTROLES_SITE_MODE == SITE_MODE_TARGET - ): - setting_kwargs['label'] += ' ' + SETTING_DISABLE_LABEL - setting_kwargs['help_text'] += ' ' + SETTING_SOURCE_ONLY_MSG - setting_kwargs['disabled'] = True - - if s_val['type'] == 'STRING': - if 'options' in s_val and callable(s_val['options']): - self.fields[s_field] = forms.ChoiceField( - choices=[ - ( - (str(value[0]), str(value[1])) - if isinstance(value, tuple) - else (str(value), str(value)) - ) - for value in s_val['options'](user=self.user) - ], - **setting_kwargs, - ) - elif 'options' in s_val: - self.fields[s_field] = forms.ChoiceField( - choices=[ - (option, option) for option in s_val['options'] - ], - **setting_kwargs, - ) - else: - self.fields[s_field] = forms.CharField( - widget=forms.TextInput(attrs=s_widget_attrs), - **setting_kwargs, - ) - elif s_val['type'] == 'INTEGER': - if 'options' in s_val: - self.fields[s_field] = forms.ChoiceField( - choices=[ - (int(option), int(option)) - for option in s_val['options'] - ], - **setting_kwargs, - ) - else: - self.fields[s_field] = forms.IntegerField( - widget=forms.NumberInput(attrs=s_widget_attrs), - **setting_kwargs, - ) - elif s_val['type'] == 'BOOLEAN': - self.fields[s_field] = forms.BooleanField(**setting_kwargs) - elif s_val['type'] == 'JSON': - # NOTE: Attrs MUST be supplied here (#404) - if 'class' in s_widget_attrs: - s_widget_attrs['class'] += ' sodar-json-input' - else: - s_widget_attrs['class'] = 'sodar-json-input' - self.fields[s_field] = forms.CharField( - widget=forms.Textarea(attrs=s_widget_attrs), - **setting_kwargs, - ) - - # Modify initial value and attributes - if s_val['type'] != 'JSON': - # Add optional attributes from plugin (#404) - # NOTE: Experimental! Use at your own risk! - self.fields[s_field].widget.attrs.update(s_widget_attrs) - - self.initial[s_field] = app_settings.get( - plugin_name=name, setting_name=s_key, user=self.user - ) - else: - self.initial[s_field] = json.dumps( - app_settings.get( - plugin_name=name, - setting_name=s_key, - user=self.user, - ) - ) + self._set_app_setting_field(name, s_field, s_key, s_val) self.fields[s_field].label = self.get_app_setting_label( plugin, self.fields[s_field].label )