~launchpad-pqm/launchpad/devel

8687.15.18 by Karl Fogel
Add the copyright header block to files under lib/canonical/.
1
# Copyright 2009 Canonical Ltd.  This software is licensed under the
2
# GNU Affero General Public License version 3 (see the file LICENSE).
3844.1.1 by Francis J. Lacoste
Add ProjectScopeWidget that can select between "All projects" and "One project:" scope.
3
10326.1.1 by Henning Eggers
Mechanically renamed IProject* to IProjectGroup*.
4
"""Widgets related to IProjectGroup."""
3844.1.1 by Francis J. Lacoste
Add ProjectScopeWidget that can select between "All projects" and "One project:" scope.
5
6
__metaclass__ = type
7
8
from textwrap import dedent
9
10
from zope.app.form import InputWidget
12442.2.9 by j.c.sackett
Ran import reformatter per review.
11
from zope.app.form.browser.widget import (
12
    BrowserWidget,
13
    renderElement,
14
    )
3844.1.1 by Francis J. Lacoste
Add ProjectScopeWidget that can select between "All projects" and "One project:" scope.
15
from zope.app.form.interfaces import (
12442.2.9 by j.c.sackett
Ran import reformatter per review.
16
    ConversionError,
17
    IInputWidget,
18
    InputErrors,
19
    )
3844.1.1 by Francis J. Lacoste
Add ProjectScopeWidget that can select between "All projects" and "One project:" scope.
20
from zope.app.form.utility import setUpWidget
21
from zope.interface import implements
22
from zope.schema import Choice
23
11270.1.4 by Tim Penhey
Update UnexpectedFormData imports.
24
from lp.app.errors import UnexpectedFormData
12442.2.2 by j.c.sackett
Moved validators to app, which makes more sense.
25
from lp.app.validators import LaunchpadValidationError
14612.2.1 by William Grant
format-imports on lib/. So many imports.
26
from lp.services.webapp.interfaces import IAlwaysSubmittedWidget
3844.1.1 by Francis J. Lacoste
Add ProjectScopeWidget that can select between "All projects" and "One project:" scope.
27
28
29
class ProjectScopeWidget(BrowserWidget, InputWidget):
30
    """Widget for selecting a scope. Either 'All projects' or only one."""
31
32
    implements(IAlwaysSubmittedWidget, IInputWidget)
33
34
    default_option = "all"
3811.2.12 by Bjorn Tillenius
Some fixes to ProjectScopeWidget to make it usable in malone-index.pt
35
    _error = None
3844.1.1 by Francis J. Lacoste
Add ProjectScopeWidget that can select between "All projects" and "One project:" scope.
36
3811.2.12 by Bjorn Tillenius
Some fixes to ProjectScopeWidget to make it usable in malone-index.pt
37
    def __init__(self, field, vocabulary, request):
3844.1.1 by Francis J. Lacoste
Add ProjectScopeWidget that can select between "All projects" and "One project:" scope.
38
        super(ProjectScopeWidget, self).__init__(field, request)
39
40
        # We copy the title, description and vocabulary from the main
41
        # field since it determines the valid target types.
4664.1.1 by Curtis Hovey
Normalized comments for bug 3732.
42
        # XXX flacoste 2007-02-21 bug=86861: We must
3811.2.15 by Bjorn Tillenius
merge r3848 from flacoste/ui-one-zero-fixes
43
        # use field.vocabularyName instead of the vocabulary parameter
8879.5.1 by Edwin Grubbs
Fixed SourcePackageNameVocabulary.
44
        # otherwise VocabularyPickerWidget will fail.
3844.1.1 by Francis J. Lacoste
Add ProjectScopeWidget that can select between "All projects" and "One project:" scope.
45
        target_field = Choice(
46
            __name__='target', title=field.title,
3811.2.15 by Bjorn Tillenius
merge r3848 from flacoste/ui-one-zero-fixes
47
            description=field.description, vocabulary=field.vocabularyName,
3844.1.1 by Francis J. Lacoste
Add ProjectScopeWidget that can select between "All projects" and "One project:" scope.
48
            required=True)
49
        setUpWidget(
50
            self, target_field.__name__, target_field, IInputWidget,
51
            prefix=self.name)
3811.2.12 by Bjorn Tillenius
Some fixes to ProjectScopeWidget to make it usable in malone-index.pt
52
        self.setUpOptions()
3844.1.1 by Francis J. Lacoste
Add ProjectScopeWidget that can select between "All projects" and "One project:" scope.
53
54
    def setUpOptions(self):
55
        """Set up options to be rendered."""
56
        self.options = {}
57
        for option in ['all', 'project']:
58
            attributes = dict(
59
                type='radio', name=self.name, value=option,
60
                id='%s.option.%s' % (self.name, option))
4173.1.5 by Francis J. Lacoste
Upgrade canonical widgets to use IBrowserFormNG.
61
            if self.request.form_ng.getOne(
62
                     self.name, self.default_option) == option:
3844.1.1 by Francis J. Lacoste
Add ProjectScopeWidget that can select between "All projects" and "One project:" scope.
63
                attributes['checked'] = 'checked'
64
            if option == 'project':
65
                attributes['onclick'] = (
66
                    "document.getElementById('field.scope.target').focus();")
67
            self.options[option] = renderElement('input', **attributes)
68
        self.target_widget.onKeyPress = (
69
            "selectWidget('%s.option.project', event)" % self.name)
70
71
    def hasInput(self):
72
        """See zope.app.form.interfaces.IInputWidget."""
73
        return self.name in self.request.form
74
75
    def hasValidInput(self):
76
        """See zope.app.form.interfaces.IInputWidget."""
77
        try:
78
            self.getInputValue()
3900.3.1 by Bjorn Tillenius
fix ProjectScopeWidget.getInputValue() to return None if the widget isn't required, and there is no input.
79
            return self.hasInput()
3844.1.1 by Francis J. Lacoste
Add ProjectScopeWidget that can select between "All projects" and "One project:" scope.
80
        except (InputErrors, UnexpectedFormData, LaunchpadValidationError):
81
            return False
82
83
    def getInputValue(self):
84
        """See zope.app.form.interfaces.IInputWidget."""
4173.1.5 by Francis J. Lacoste
Upgrade canonical widgets to use IBrowserFormNG.
85
        scope = self.request.form_ng.getOne(self.name)
3844.1.1 by Francis J. Lacoste
Add ProjectScopeWidget that can select between "All projects" and "One project:" scope.
86
        if scope == 'all':
87
            return None
88
        elif scope == 'project':
4173.1.5 by Francis J. Lacoste
Upgrade canonical widgets to use IBrowserFormNG.
89
            if not self.request.form_ng.getOne(self.target_widget.name):
3811.2.13 by Bjorn Tillenius
Make ProjectScopeWidget.getInputValue raise an appropriate error also
90
                self._error = LaunchpadValidationError(
91
                    'Please enter a project name')
92
                raise self._error
3844.1.1 by Francis J. Lacoste
Add ProjectScopeWidget that can select between "All projects" and "One project:" scope.
93
            try:
94
                return self.target_widget.getInputValue()
95
            except ConversionError:
4173.1.5 by Francis J. Lacoste
Upgrade canonical widgets to use IBrowserFormNG.
96
                entered_name = self.request.form_ng.getOne(
97
                     "%s.target" % self.name)
3811.2.12 by Bjorn Tillenius
Some fixes to ProjectScopeWidget to make it usable in malone-index.pt
98
                self._error = LaunchpadValidationError(
3844.1.1 by Francis J. Lacoste
Add ProjectScopeWidget that can select between "All projects" and "One project:" scope.
99
                    "There is no project named '%s' registered in"
5985.6.11 by Maris Fogels
Updated many many LVE callsites to the new API.
100
                    " Launchpad" % entered_name)
3811.2.13 by Bjorn Tillenius
Make ProjectScopeWidget.getInputValue raise an appropriate error also
101
                raise self._error
3900.3.1 by Bjorn Tillenius
fix ProjectScopeWidget.getInputValue() to return None if the widget isn't required, and there is no input.
102
        elif self.required:
3844.1.1 by Francis J. Lacoste
Add ProjectScopeWidget that can select between "All projects" and "One project:" scope.
103
            raise UnexpectedFormData("No valid option was selected.")
3900.3.1 by Bjorn Tillenius
fix ProjectScopeWidget.getInputValue() to return None if the widget isn't required, and there is no input.
104
        else:
105
            return None
3844.1.1 by Francis J. Lacoste
Add ProjectScopeWidget that can select between "All projects" and "One project:" scope.
106
4798.1.4 by Tom Berger
use the scope widget to provide the default value, and make the same fix in the answers application
107
    def getScope(self):
4798.1.6 by Tom Berger
post-review changes
108
        """Return the selected scope or None if it isn't selected."""
4798.1.4 by Tom Berger
use the scope widget to provide the default value, and make the same fix in the answers application
109
        return self.request.form_ng.getOne(self.name)
110
3844.1.1 by Francis J. Lacoste
Add ProjectScopeWidget that can select between "All projects" and "One project:" scope.
111
    def setRenderedValue(self, value):
112
        """See IWidget."""
113
        if value is None:
114
            self.default_option = 'all'
115
            self.target_widget.setRenderedValue(None)
116
        else:
117
            self.default_option = 'project'
118
            self.target_widget.setRenderedValue(value)
3811.2.12 by Bjorn Tillenius
Some fixes to ProjectScopeWidget to make it usable in malone-index.pt
119
        self.setUpOptions()
3844.1.1 by Francis J. Lacoste
Add ProjectScopeWidget that can select between "All projects" and "One project:" scope.
120
121
    def __call__(self):
122
        """See zope.app.form.interfaces.IBrowserWidget."""
123
        return "\n".join([
124
            self.renderScopeOptions(),
125
            self.target_widget()])
126
127
    def renderScopeOptions(self):
128
        """Render the HTML for the scope radio widgets."""
129
        return dedent('''\
130
        <label>
131
          %(all)s All projects
132
        </label>
133
        <label>
134
          %(project)s One project:
135
        </label>
136
        ''' % self.options)
3811.2.12 by Bjorn Tillenius
Some fixes to ProjectScopeWidget to make it usable in malone-index.pt
137
138
    def error(self):
139
        """See zope.app.form.browser.interfaces.IBrowserWidget"""
140
        if self._error:
141
            return self._error.doc()
142
        else:
143
            return u""