def renderValue(self, value):
     # Render the items with subordinate fields and support markup.
     self.bug_trackers = dict(self.renderItems(value))
     self.product = self.context.context
     # The view must also use GhostWidget for the 'remote_product' field.
     self.remote_product = copy_field(IProduct['remote_product'])
     self.remote_product_widget = CustomWidgetFactory(TextWidget)
     setUpWidget(self,
                 'remote_product',
                 self.remote_product,
                 IInputWidget,
                 prefix='field',
                 value=self.product.remote_product,
                 context=self.product)
     # The view must also use GhostWidget for the 'enable_bug_expiration'
     # field.
     self.enable_bug_expiration = copy_field(
         IProduct['enable_bug_expiration'])
     self.enable_bug_expiration_widget = CustomWidgetFactory(CheckBoxWidget)
     setUpWidget(self,
                 'enable_bug_expiration',
                 self.enable_bug_expiration,
                 IInputWidget,
                 prefix='field',
                 value=self.product.enable_bug_expiration,
                 context=self.product)
     return self.template()
Exemple #2
0
class BrandingChangeView(LaunchpadEditFormView):
    """This is a base class that MUST be subclassed for each object, because
    each object will have a different description for its branding that is
    part of its own interface.

    For each subclass, specify the schema ("IPerson") and the field_names
    (some subset of icon, logo, mugshot).
    """
    @property
    def label(self):
        return ('Change the images used to represent %s in Launchpad' %
                self.context.displayname)

    page_title = "Change branding"

    custom_widget_icon = CustomWidgetFactory(ImageChangeWidget,
                                             ImageChangeWidget.EDIT_STYLE)
    custom_widget_logo = CustomWidgetFactory(ImageChangeWidget,
                                             ImageChangeWidget.EDIT_STYLE)
    custom_widget_mugshot = CustomWidgetFactory(ImageChangeWidget,
                                                ImageChangeWidget.EDIT_STYLE)

    @action("Change Branding", name='change')
    def change_action(self, action, data):
        self.updateContextFromData(data)

    @property
    def next_url(self):
        return canonical_url(self.context)

    cancel_url = next_url
 def __init__(self, context, request):
     SimpleInputWidget.__init__(self, context, request)
     fields = form.Fields(
         Choice(__name__='action',
                source=self._getActionsVocabulary(),
                title=_('Action')),
         Datetime(__name__='announcement_date',
                  title=_('Date'),
                  required=False,
                  default=None))
     fields['action'].custom_widget = CustomWidgetFactory(
         LaunchpadRadioWidget)
     fields['announcement_date'].custom_widget = CustomWidgetFactory(
         DateTimeWidget)
     if IAnnouncement.providedBy(self.context.context):
         # we are editing an existing announcement
         data = {}
         date_announced = self.context.context.date_announced
         data['announcement_date'] = date_announced
         if date_announced is None:
             data['action'] = 'sometime'
         else:
             data['action'] = 'specific'
     else:
         data = {'action': 'immediately'}
     widgets = form.setUpWidgets(fields,
                                 self.name,
                                 context,
                                 request,
                                 ignore_request=False,
                                 data=data)
     self.action_widget = widgets['action']
     self.announcement_date_widget = widgets['announcement_date']
class ProductReleaseEditView(LaunchpadEditFormView):
    """Edit view for ProductRelease objects"""

    schema = IProductRelease
    field_names = [
        "datereleased",
        "release_notes",
        "changelog",
        ]

    custom_widget_datereleased = DateTimeWidget
    custom_widget_release_notes = CustomWidgetFactory(
        TextAreaWidget, height=7, width=62)
    custom_widget_changelog = CustomWidgetFactory(
        TextAreaWidget, height=7, width=62)

    @property
    def label(self):
        """The form label."""
        return smartquote('Edit %s release details' % self.context.title)

    page_title = label

    @action('Change', name='change')
    def change_action(self, action, data):
        self.updateContextFromData(data)
        self.next_url = canonical_url(self.context)

    @property
    def cancel_url(self):
        return canonical_url(self.context)
Exemple #5
0
 def setUpSubWidgets(self):
     if self._widgets_set_up:
         return
     fields = [
         Choice(__name__="person",
                title=u"Person",
                required=False,
                vocabulary="ValidPersonOrTeam"),
     ]
     if self._read_only:
         self.person_widget = CustomWidgetFactory(
             GitGranteePersonDisplayWidget)
     else:
         self.person_widget = CustomWidgetFactory(
             PersonPickerWidget,
             # XXX cjwatson 2018-10-18: This is a little unfortunate, but
             # otherwise there's no spacing at all between the
             # (deliberately unlabelled) radio button and the text box.
             style="margin-left: 4px;")
     for field in fields:
         setUpWidget(self,
                     field.__name__,
                     field,
                     self._sub_widget_interface,
                     prefix=self.name)
     self._widgets_set_up = True
Exemple #6
0
class BugSubscriptionFilterEditViewBase(LaunchpadEditFormView,
                                        AdvancedSubscriptionMixin):
    """Base class for edit or create views of `IBugSubscriptionFilter`."""

    schema = IBugSubscriptionFilter
    field_names = (
        "description",
        "statuses",
        "importances",
        "information_types",
        "tags",
        "find_all_tags",
        )

    custom_widget_description = CustomWidgetFactory(
        TextWidget, displayWidth=50)
    custom_widget_statuses = LabeledMultiCheckBoxWidget
    custom_widget_importances = LabeledMultiCheckBoxWidget
    custom_widget_information_types = LabeledMultiCheckBoxWidget
    custom_widget_tags = CustomWidgetFactory(
        BugTagsFrozenSetWidget, displayWidth=35)

    # Define in concrete subclass to be the target of the
    # structural subscription that we are modifying.
    target = None

    # This is used by the AdvancedSubscriptionMixin.
    current_user_subscription = None

    @cachedproperty
    def _bug_notification_level_descriptions(self):
        return bug_notification_level_description_mapping(
            'a bug in %s' % self.target.displayname)

    def setUpFields(self):
        """Set up fields for form.

        Overrides the usual implementation to also set up bug notification."""
        super(BugSubscriptionFilterEditViewBase, self).setUpFields()
        self._setUpBugNotificationLevelField()

    @property
    def next_url(self):
        """Return to the user's structural subscriptions page."""
        return canonical_url(
            self.user, view_name="+structural-subscriptions")

    cancel_url = next_url
class ProductReleaseAddViewBase(LaunchpadFormView):
    """Base class for creating a release from an existing or new milestone.

    Subclasses need to define the field_names a form action.
    """
    schema = IProductRelease

    custom_widget_datereleased = DateTimeWidget
    custom_widget_release_notes = CustomWidgetFactory(
        TextAreaWidget, height=7, width=62)
    custom_widget_changelog = CustomWidgetFactory(
        TextAreaWidget, height=7, width=62)

    def _prependKeepMilestoneActiveField(self):
        keep_milestone_active_checkbox = FormFields(
            Bool(
                __name__='keep_milestone_active',
                title=_("Keep the %s milestone active." % self.context.name),
                description=_(
                    "Only select this if bugs or blueprints still need "
                    "to be targeted to this project release's milestone.")),
            render_context=self.render_context)
        self.form_fields = keep_milestone_active_checkbox + self.form_fields

    def _createRelease(self, milestone, data):
        """Create product release for this milestone."""
        newrelease = milestone.createProductRelease(
            self.user, changelog=data['changelog'],
            release_notes=data['release_notes'],
            datereleased=data['datereleased'])
        # Set Milestone.active to false, since bugs & blueprints
        # should not be targeted to a milestone in the past.
        if data.get('keep_milestone_active') is False:
            milestone.active = False
        self.next_url = canonical_url(newrelease.milestone)
        notify(ObjectCreatedEvent(newrelease))

    @property
    def label(self):
        """The form label."""
        return smartquote('Create a new release for %s' %
                          self.context.product.displayname)

    page_title = label

    @property
    def cancel_url(self):
        return canonical_url(self.context)
class ProductSeriesReviewView(LaunchpadEditFormView):
    """A view to review and change the series `IProduct` and name."""
    schema = IProductSeries
    field_names = ['product', 'name']
    custom_widget_name = CustomWidgetFactory(TextWidget, displayWidth=20)

    @property
    def label(self):
        """The form label."""
        return 'Administer %s %s series' % (self.context.product.displayname,
                                            self.context.name)

    page_title = label

    @property
    def cancel_url(self):
        """See `LaunchpadFormView`."""
        return canonical_url(self.context)

    @action(_('Change'), name='change')
    def change_action(self, action, data):
        """Update the series."""
        self.updateContextFromData(data)
        self.request.response.addInfoNotification(
            _('This Series has been changed'))
        self.next_url = canonical_url(self.context)
 def __init__(self, field, vocabulary, request):
     super(LicenseWidget, self).__init__(field, vocabulary, request)
     # We want to put the license_info widget inside the licences widget's
     # HTML, for better alignment and JavaScript dynamism.  This is
     # accomplished by ghosting the form's license_info widget (see
     # lp/registry/browser/product.py and the GhostWidget implementation
     # below) and creating a custom widget here.  It's a pretty simple text
     # widget so create that now.  The fun part is that it's all within the
     # same form, so posts work correctly.
     self.license_info = Text(__name__='license_info')
     self.license_info_widget = CustomWidgetFactory(DescriptionWidget)
     # The initial value of the license_info widget will be taken from the
     # field's context when available.  This will be the IProduct when
     # we're editing an existing project, but when we're creating a new
     # one, it'll be an IProductSet, which does not have license_info.
     initial_value = getattr(field.context, 'license_info', None)
     setUpWidget(self,
                 'license_info',
                 self.license_info,
                 IInputWidget,
                 prefix='field',
                 value=initial_value,
                 context=field.context)
     self.source_package_release = None
     # These will get filled in by _categorize().  They are the number of
     # selected licences in the category.  The actual count doesn't matter,
     # since if it's greater than 0 it will start opened.  Note that we
     # always want the recommended licences to be opened, so we initialize
     # its value to 1.
     self.recommended_count = 1
     self.more_count = 0
     self.deprecated_count = 0
     self.special_count = 0
 def _setUpBugNotificationLevelField(self):
     """Set up the bug_notification_level field."""
     self.form_fields = self.form_fields.omit('bug_notification_level')
     self.form_fields += formlib.form.Fields(
         self._bug_notification_level_field)
     self.form_fields['bug_notification_level'].custom_widget = (
         CustomWidgetFactory(RadioWidget))
 def setUpSubWidgets(self):
     if self._widgets_set_up:
         return
     fields = [
         Choice(__name__='product',
                title=u'Project',
                required=True,
                vocabulary=self.getProductVocabulary()),
         Choice(__name__='distribution',
                title=u"Distribution",
                required=True,
                vocabulary=self.getDistributionVocabulary(),
                default=getUtility(ILaunchpadCelebrities).ubuntu),
         Choice(__name__='package',
                title=u"Package",
                required=False,
                vocabulary='BinaryAndSourcePackageName'),
     ]
     self.distribution_widget = CustomWidgetFactory(LaunchpadDropdownWidget)
     for field in fields:
         setUpWidget(self,
                     field.__name__,
                     field,
                     IInputWidget,
                     prefix=self.name)
     self._widgets_set_up = True
 def setUpSubWidgets(self):
     if self._widgets_set_up:
         return
     if bool(getFeatureFlag('disclosure.dsp_picker.enabled')):
         # Replace the default field with a field that uses the better
         # vocabulary.
         package_vocab = 'DistributionSourcePackage'
     else:
         package_vocab = 'BinaryAndSourcePackageName'
     fields = [
         Choice(__name__='product',
                title=u'Project',
                required=True,
                vocabulary=self.getProductVocabulary()),
         Choice(__name__='distribution',
                title=u"Distribution",
                required=True,
                vocabulary=self.getDistributionVocabulary(),
                default=getUtility(ILaunchpadCelebrities).ubuntu),
         Choice(__name__='package',
                title=u"Package",
                required=False,
                vocabulary=package_vocab),
     ]
     self.distribution_widget = CustomWidgetFactory(LaunchpadDropdownWidget)
     for field in fields:
         setUpWidget(self,
                     field.__name__,
                     field,
                     IInputWidget,
                     prefix=self.name)
     self._widgets_set_up = True
Exemple #13
0
class LanguageAdminView(LaunchpadEditFormView):
    """Handle an admin form submission."""

    rootsite = 'translations'

    schema = ILanguage

    custom_widget_countries = CustomWidgetFactory(LabeledMultiCheckBoxWidget,
                                                  orientation='vertical')

    field_names = [
        'code', 'englishname', 'nativename', 'pluralforms', 'pluralexpression',
        'visible', 'direction', 'countries'
    ]

    page_title = "Change details"

    @property
    def label(self):
        """The form label"""
        return "Edit %s in Launchpad" % describe_language(self.context)

    @property
    def cancel_url(self):
        """See LaunchpadFormView."""
        return canonical_url(self.context, rootsite=self.rootsite)

    @property
    def next_url(self):
        return canonical_url(self.context, rootsite=self.rootsite)

    @action("Admin Language", name="admin")
    def admin_action(self, action, data):
        self.updateContextFromData(data)

    def _validateCode(self, new_code):
        """Validate a change in language code."""
        language_set = getUtility(ILanguageSet)
        if language_set.getLanguageByCode(new_code) is not None:
            self.setFieldError('code',
                               'There is already a language with that code.')

    def _validatePluralData(self, pluralforms, pluralexpression):
        """Validate plural expression and number of plural forms."""
        try:
            make_friendly_plural_forms(pluralexpression, pluralforms)
        except BadPluralExpression as e:
            self.setFieldError('pluralexpression', str(e))

    def validate(self, data):
        new_code = data.get('code')
        if new_code != self.context.code:
            self._validateCode(new_code)

        pluralexpression = data.get('pluralexpression')
        pluralforms = data.get('pluralforms')
        if pluralexpression is not None:
            self._validatePluralData(pluralforms, pluralexpression)
    def setUpFields(self):
        """See `LaunchpadFormView`."""
        super(BugSubscriptionSubscribeSelfView, self).setUpFields()
        if self.user is None:
            return

        self.form_fields += formlib.form.Fields(self._subscription_field)
        self._setUpBugNotificationLevelField()
        self.form_fields['subscription'].custom_widget = CustomWidgetFactory(
            RadioWidget)
Exemple #15
0
    def __init__(self, field, vocabulary, request):
        LaunchpadRadioWidget.__init__(self, field, vocabulary, request)

        # Bug tracker widget.
        self.bugtracker = Choice(vocabulary="WebBugTracker",
                                 __name__='bugtracker')
        self.bugtracker_widget = CustomWidgetFactory(BugTrackerPickerWidget)
        setUpWidget(self,
                    'bugtracker',
                    self.bugtracker,
                    IInputWidget,
                    prefix=self.name,
                    value=field.context.bugtracker,
                    context=field.context)
        self.bugtracker_widget.onKeyPress = ("selectWidget('%s.2', event);" %
                                             self.name)

        # Upstream email address field and widget.
        ## This is to make email address bug trackers appear
        ## separately from the main bug tracker list.
        self.upstream_email_address = StrippedTextLine(
            required=False,
            constraint=email_validator,
            __name__='upstream_email_address')
        self.upstream_email_address_widget = (
            CustomWidgetFactory(StrippedTextWidget))
        setUpWidget(self,
                    'upstream_email_address',
                    self.upstream_email_address,
                    IInputWidget,
                    prefix=self.name,
                    value='',
                    context=self.upstream_email_address.context)
        ## Select the corresponding radio option automatically if
        ## the user starts typing.
        if self.upstream_email_address_widget.extra is None:
            self.upstream_email_address_widget.extra = ''
        self.upstream_email_address_widget.extra += (
            ''' onkeypress="selectWidget('%s.3', event);"\n''' % self.name)
class ProductSeriesEditView(LaunchpadEditFormView):
    """A View to edit the attributes of a series."""
    schema = IProductSeries
    field_names = ['name', 'summary', 'status', 'branch', 'releasefileglob']
    custom_widget_summary = CustomWidgetFactory(TextAreaWidget,
                                                height=7,
                                                width=62)
    custom_widget_releasefileglob = CustomWidgetFactory(StrippedTextWidget,
                                                        displayWidth=40)

    @property
    def label(self):
        """The form label."""
        return 'Edit %s %s series' % (self.context.product.displayname,
                                      self.context.name)

    page_title = label

    def validate(self, data):
        """See `LaunchpadFormView`."""
        branch = data.get('branch')
        if branch is not None:
            message = get_series_branch_error(self.context.product, branch)
            if message:
                self.setFieldError('branch', message)

    @action(_('Change'), name='change')
    def change_action(self, action, data):
        """Update the series."""
        self.updateContextFromData(data)

    @property
    def next_url(self):
        """See `LaunchpadFormView`."""
        return canonical_url(self.context)

    cancel_url = next_url