Beispiel #1
0
 def test_changing_type_restore_correct_fields(self):
     """Tests that changing a ticket type restores the correct fields for
     that type"""
     t = AgiloTicket(self.env, t_type=Type.TASK)
     self.assert_true(self._matching_properties(t))
     # Now change that to a story
     t[Key.TYPE] = Type.USER_STORY
     self.assert_true(self._matching_properties(t))
     # Now reload config and change to bug
     ac = AgiloConfig(self.env)
     ac.reload()
     t[Key.TYPE] = Type.BUG
     self.assert_true(self._matching_properties(t))
     # Now add a field on the fly and see if it is adapting to it
     agilo_types = ac.get_section(ac.AGILO_TYPES)
     ticket_custom = ac.get_section(ac.TICKET_CUSTOM)
     ticket_custom.change_option('customer', 'text')
     ticket_custom.change_option('customer.label', 'Customer')
     fields = agilo_types.get_list(Type.BUG)
     fields.append('customer')
     # notice the save to force the reload of the config
     agilo_types.change_option('story', ','.join(fields), save=True)
     t[Key.TYPE] = Type.USER_STORY
     self.assert_true('customer' in t.fields_for_type, \
                     "No 'customer' in %s" % t.fields_for_type)
     t['customer'] = 'My Own Customer'
     self.assert_true(self._matching_properties(t))
     t.insert()
     self.assert_true(self._matching_properties(t))
     self.assert_equals('My Own Customer', t['customer'])
Beispiel #2
0
 def test_changing_type_restore_correct_fields(self):
     """Tests that changing a ticket type restores the correct fields for
     that type"""
     t = AgiloTicket(self.env, t_type=Type.TASK)
     self.assert_true(self._matching_properties(t))
     # Now change that to a story
     t[Key.TYPE] = Type.USER_STORY
     self.assert_true(self._matching_properties(t))
     # Now reload config and change to bug
     ac = AgiloConfig(self.env)
     ac.reload()
     t[Key.TYPE] = Type.BUG
     self.assert_true(self._matching_properties(t))
     # Now add a field on the fly and see if it is adapting to it
     agilo_types = ac.get_section(ac.AGILO_TYPES)
     ticket_custom = ac.get_section(ac.TICKET_CUSTOM)
     ticket_custom.change_option('customer', 'text')
     ticket_custom.change_option('customer.label', 'Customer')
     fields = agilo_types.get_list(Type.BUG)
     fields.append('customer')
     # notice the save to force the reload of the config
     agilo_types.change_option('story', ','.join(fields), save=True)
     t[Key.TYPE] = Type.USER_STORY
     self.assert_true('customer' in t.fields_for_type, \
                     "No 'customer' in %s" % t.fields_for_type)
     t['customer'] = 'My Own Customer'
     self.assert_true(self._matching_properties(t))
     t.insert()
     self.assert_true(self._matching_properties(t))
     self.assert_equals('My Own Customer', t['customer'])
Beispiel #3
0
 def test_do_not_sets_default_logo_if_changed(self):
     test_src = 'my_logo'
     agilo_config = AgiloConfig(self.env)
     header_logo = agilo_config.get_section('header_logo')
     header_logo.change_option('src', test_src)
     self.assert_equals(test_src, header_logo.get('src'))
     set_default_agilo_logo(agilo_config)
     self.assert_equals(test_src, header_logo.get('src'))
Beispiel #4
0
 def test_do_not_sets_default_logo_if_changed(self):
     test_src = 'my_logo'
     agilo_config = AgiloConfig(self.env)
     header_logo = agilo_config.get_section('header_logo')
     header_logo.change_option('src', test_src)
     self.assert_equals(test_src, header_logo.get('src'))
     set_default_agilo_logo(agilo_config)
     self.assert_equals(test_src, header_logo.get('src'))
Beispiel #5
0
def _reset_properly_query_and_report_modules(env):
    # Reset the properties of query module and report in the trac.ini, in old
    # agilo was required to remove the original from trac, now we have to make
    # sure that they are reset again, cause the patching is done in AgiloConfig.
    ac = AgiloConfig(env)
    components = ac.get_section('components')
    # even if they would be set to enabled, removing them wouldn't change the
    # behavior
    components.remove_option('trac.ticket.query.querymodule')
    components.remove_option('trac.ticket.report.reportmodule')
    components.save()
Beispiel #6
0
def _reset_properly_query_and_report_modules(env):
    # Reset the properties of query module and report in the trac.ini, in old
    # agilo was required to remove the original from trac, now we have to make
    # sure that they are reset again, cause the patching is done in AgiloConfig.
    ac = AgiloConfig(env)
    components = ac.get_section("components")
    # even if they would be set to enabled, removing them wouldn't change the
    # behavior
    components.remove_option("trac.ticket.query.querymodule")
    components.remove_option("trac.ticket.report.reportmodule")
    components.save()
    def test_handles_types_with_dashes(self):
        from_type = 'with-dashes'
        to_type = 'bug'
        custom_type = TicketType(self.env)
        custom_type.name = from_type
        custom_type.insert()

        config = AgiloConfig(self.env)
        config.change_option(from_type, "", section=AgiloConfig.AGILO_TYPES)
        config.reload()
        self.assert_true(from_type in config.get_available_types())

        section = config.get_section(AgiloConfig.AGILO_LINKS)
        allowed_links = section.get_list('allow')
        allowed_links.append('%s-%s' % (from_type, to_type))
        section.change_option('allow', ', '.join(allowed_links), save=True)
        self.links_configuration = LinksConfiguration(self.env)
        self.assert_equals(self.links_configuration.get_alloweds(from_type)[0].dest_type, to_type)
Beispiel #8
0
class AgiloConfigTest(AgiloTestCase):
    
    def setUp(self):
        self.super()
        self.trac_config = self.env.config
        self.config = AgiloConfig(self.env)
    
    # --------------------------------------------------------------------------
    # Agilo-specific configuration
    
    def test_days_are_fetched_correctly_from_config(self):
        """Regression test: Check that AgiloConfig uses the right configuration
        section and that use_days is really a bool, not a string."""
        self.trac_config.set('agilo-general', Key.USE_DAYS, False)
        self.assert_false(self.config.use_days)
        
        self.trac_config.set('agilo-general', Key.USE_DAYS, True)
        self.config.reload()
        self.assert_true(self.config.use_days)
    
    def test_can_enable_agilo_ui(self):
        self.config.enable_agilo_ui(save=True)
        self.assert_true(self.config.is_agilo_ui_enabled)
        self.config.disable_agilo_ui(save=True)
        self.assert_none(self.config.get('templates_dir', 'inherit'))
        self.assert_false(self.config.is_agilo_ui_enabled)
    
    def test_can_enable_agilo(self):
        self.config.enable_agilo()
        self.assert_true(self.config.is_agilo_enabled)
        self.config.disable_agilo()
        self.assert_false(self.config.is_agilo_enabled)
    
    def test_can_disable_agilo_ui(self):
        self.assert_true(self.config.is_agilo_ui_enabled)
        self.config.disable_agilo_ui(save=True)
        self.assert_false(self.config.is_agilo_ui_enabled)
    
    def _set_template_dir(self, config, dirname):
        config.change_option('templates_dir', dirname, 'inherit', save=True)
    
    def test_configuration_detects_outdated_template_path(self):
        self.assert_true(self.config.is_agilo_enabled)
        self.assert_true(self.config.is_agilo_ui_enabled)
        
        current_dir = '/usr/share/agilo-0.42-r12345.egg/templates'
        self._set_template_dir(self.config, '')
        self.assert_false(self.config.is_agilo_ui_enabled)
        self.assert_true(self.config._is_template_dir_outdated(current_dir))
        
        self._set_template_dir(self.config, '/my/user/configured/template')
        self.assert_false(self.config._is_template_dir_outdated(current_dir))
        
        self._set_template_dir(self.config, current_dir.replace('12345', '54321'))
        self.assert_true(self.config._is_template_dir_outdated(current_dir))
    
    def test_knows_when_filtered_burndown_is_enabled(self):
        self.assert_false(self.config.is_filtered_burndown_enabled())
        self.config.change_option('should_reload_burndown_on_filter_change_when_filtering_by_component', True, section=AgiloConfig.AGILO_GENERAL)
        self.assert_false(self.config.is_filtered_burndown_enabled())
        self.config.change_option('backlog_filter_attribute', 'component', section=AgiloConfig.AGILO_GENERAL)
        self.assert_true(self.config.is_filtered_burndown_enabled())
    
    # --------------------------------------------------------------------------
    # modify low-level configuration
    
    def test_can_remove_whole_sections(self):
        section = self.config.get_section('fnord')
        section.change_option('foo', 'bar')
        self.assert_true('fnord' in self.trac_config.sections())
        self.assert_equals('bar', section.get('foo'))
        section.remove()
        self.assert_not_equals('bar', section.get('foo'))
    
    def test_can_remove_sections_without_getting_it_first(self):
        section = self.config.get_section('fnord')
        section.change_option('foo', 'bar')
        self.assert_true('fnord' in self.trac_config.sections())
        self.assert_equals('bar', section.get('foo'))
        self.config.remove(section='fnord')
        self.assert_false(self.config.get_section('fnord').has_option('foo'))
        self.assert_not_equals('bar', section.get('foo'))
    
    def test_config_knows_if_an_option_is_set(self):
        self.assert_false(self.config.has_option('foo', section='fnord'))
        self.config.change_option('foo', 'bar', section='fnord')
        self.assert_true(self.config.has_option('foo', section='fnord'))
    
    def test_config_reloads_on_change(self):
        self.config.change_option('%s.%s' % (Type.BUG, Key.ALIAS),
                                  'Bugone', section=AgiloConfig.AGILO_TYPES,
                                  save=True)
        self.assert_equals('Bugone', self.config.ALIASES.get(Type.BUG))
    
    def test_config_reloads_links_configuration_on_change(self):
        self.assert_contains('story', LinksConfiguration(self.env).get_allowed_destination_types('requirement'))
        self.config.change_option('allow',
                                  '', section=AgiloConfig.AGILO_LINKS,
                                  save=True)
        self.assert_not_contains('story', LinksConfiguration(self.env).get_allowed_destination_types('requirement'))
    
    def test_config_writing_key_with_capitals(self):
        my_section = self.config.get_section('my-section')
        my_section.change_option('TestMe', 'This is a test', save=True)
        # Test that it is stored
        self.assert_equals('This is a test', 
                         self.env.config.get('my-section', 'TestMe'))
        # Test that is case insensitive
        self.assert_equals('This is a test', 
                         self.env.config.get('my-section', 'testme'))
        self.assert_equals('This is a test', 
                         self.env.config.get('my-section', 'TESTME'))
    
    def test_config_is_normalizing(self):
        my_section = self.config.get_section('my-section')
        my_section.change_option('TestMe', 'This is a test', save=True)
        # check that in reality only the lowecased version is saved in the
        # config file trac.ini
        options = self.config.get_options('my-section')
        self.assert_true('testme' in options,
                        "TestMe not found in: %s" % options)
        self.assert_false('TestMe' in options,
                        "TestMe found in: %s" % options)
    
    def test_config_not_updating_case_sensitive(self):
        my_section = self.config.get_section('my-section')
        my_section.change_option('TestMe', 'This is a test', save=True)
        # Test that it is asymmetric
        # Using set will not set the option as it is case insensitive and is
        # not stored because testme already exists in the trac.ini
        my_section.set_option('TESTME', 'This is another test', save=True)
        self.assert_not_equals('This is another test', 
                            self.env.config.get('my-section', 'TESTME'))
        self.assert_equals('This is a test', 
                         self.env.config.get('my-section', 'TESTME'))
        options = self.config.get_options('my-section')
        self.assert_true('testme' in options,
                         'TestMe not found in: %s' % options)
        self.assert_false('TestMe' in options,
                          'TestMe found in: %s' % options)
    
    def test_config_is_case_insensitive_and_overwrites(self):
        my_section = self.config.get_section('my-section')
        my_section.change_option('TestMe', 'This is a test', save=True)
        # Now change the option and check that also the old key, that is the
        # same actually changed
        my_section.change_option('TESTME', 'This is another test', save=True)
        self.assert_equals('This is another test', 
                         self.env.config.get('my-section', 'TESTME'))
        self.assert_not_equals('This is a test', 
                            self.env.config.get('my-section', 'testme'))
        # Now check what it is stored
        options = self.config.get_options('my-section')
        self.assert_true('testme' in options, 'testme not found in: %s' % options)
        self.assert_false('TESTME' in options, 'TESTME found in: %s' % options)
        # Test it is in the AgiloWrapper also after reload
        self.config.reload()
        self.assert_equals('This is another test', 
                         self.config.get('TestMe', 'my-section'))
    
    def test_config_stores_none_as_empty_string(self):
        my_section = self.config.get_section('my-section')
        my_section.set_option('test', 'This is a test', save=True)
        self.assert_equals('This is a test', 
                         self.env.config.get('my-section', 'test'))
        # Now change the option and check that also the old key, that is the
        # same actually changed
        my_section.change_option('test', None, save=True)
        self.assert_not_equals('This is a test', 
                               self.env.config.get('my-section', 'test'))
        self.assert_equals('', self.env.config.get('my-section', 'test'))
        # Check real config
        self.env.config.set('my-section', 'test', None)
        self.env.config.save()
        self.assert_equals('', self.env.config.get('my-section', 'test'))
    
    def test_dont_strip_non_string_values(self):
        self.assert_true(self.config.get('foo', default=True, section='trac'))
    
    def test_sets_default_agilo_logo_on_new_install(self):
        # should be set by the initialization so let's check it
        agilo_logo_src = 'agilo/images/default_logo.png'
        self.assert_equals(agilo_logo_src, self.env.config.get('header_logo', 'src'))
    
    def test_do_not_sets_default_logo_if_changed(self):
        test_src = 'my_logo'
        agilo_config = AgiloConfig(self.env)
        header_logo = agilo_config.get_section('header_logo')
        header_logo.change_option('src', test_src)
        self.assert_equals(test_src, header_logo.get('src'))
        set_default_agilo_logo(agilo_config)
        self.assert_equals(test_src, header_logo.get('src'))
    
    def test_sets_agilo_favicon_on_new_install(self):
        agilo_favicon = 'agilo/images/favicon.ico'
        self.assert_equals(agilo_favicon, self.env.config.get('project', 'icon'))
    
    def test_doesnt_overwrite_custom_favicons(self):
        custom_favicon = 'fnord'
        project_section = AgiloConfig(self.env).get_section('project')
        project_section.change_option('icon', custom_favicon)
        self.assert_equals(custom_favicon, project_section.get('icon'))
        
        initialize_config(self.env, {})
        project_section = AgiloConfig(self.env).get_section('project')
        self.assert_equals(custom_favicon, project_section.get('icon'))
Beispiel #9
0
class AgiloConfigTest(AgiloTestCase):
    def setUp(self):
        self.super()
        self.trac_config = self.env.config
        self.config = AgiloConfig(self.env)

    # --------------------------------------------------------------------------
    # Agilo-specific configuration

    def test_days_are_fetched_correctly_from_config(self):
        """Regression test: Check that AgiloConfig uses the right configuration
        section and that use_days is really a bool, not a string."""
        self.trac_config.set('agilo-general', Key.USE_DAYS, False)
        self.assert_false(self.config.use_days)

        self.trac_config.set('agilo-general', Key.USE_DAYS, True)
        self.config.reload()
        self.assert_true(self.config.use_days)

    def test_can_enable_agilo_ui(self):
        self.config.enable_agilo_ui(save=True)
        self.assert_true(self.config.is_agilo_ui_enabled)
        self.config.disable_agilo_ui(save=True)
        self.assert_none(self.config.get('templates_dir', 'inherit'))
        self.assert_false(self.config.is_agilo_ui_enabled)

    def test_can_enable_agilo(self):
        self.config.enable_agilo()
        self.assert_true(self.config.is_agilo_enabled)
        self.config.disable_agilo()
        self.assert_false(self.config.is_agilo_enabled)

    def test_can_disable_agilo_ui(self):
        self.assert_true(self.config.is_agilo_ui_enabled)
        self.config.disable_agilo_ui(save=True)
        self.assert_false(self.config.is_agilo_ui_enabled)

    def _set_template_dir(self, config, dirname):
        config.change_option('templates_dir', dirname, 'inherit', save=True)

    def test_configuration_detects_outdated_template_path(self):
        self.assert_true(self.config.is_agilo_enabled)
        self.assert_true(self.config.is_agilo_ui_enabled)

        current_dir = '/usr/share/agilo-0.42-r12345.egg/templates'
        self._set_template_dir(self.config, '')
        self.assert_false(self.config.is_agilo_ui_enabled)
        self.assert_true(self.config._is_template_dir_outdated(current_dir))

        self._set_template_dir(self.config, '/my/user/configured/template')
        self.assert_false(self.config._is_template_dir_outdated(current_dir))

        self._set_template_dir(self.config,
                               current_dir.replace('12345', '54321'))
        self.assert_true(self.config._is_template_dir_outdated(current_dir))

    def test_knows_when_filtered_burndown_is_enabled(self):
        self.assert_false(self.config.is_filtered_burndown_enabled())
        self.config.change_option(
            'should_reload_burndown_on_filter_change_when_filtering_by_component',
            True,
            section=AgiloConfig.AGILO_GENERAL)
        self.assert_false(self.config.is_filtered_burndown_enabled())
        self.config.change_option('backlog_filter_attribute',
                                  'component',
                                  section=AgiloConfig.AGILO_GENERAL)
        self.assert_true(self.config.is_filtered_burndown_enabled())

    # --------------------------------------------------------------------------
    # modify low-level configuration

    def test_can_remove_whole_sections(self):
        section = self.config.get_section('fnord')
        section.change_option('foo', 'bar')
        self.assert_true('fnord' in self.trac_config.sections())
        self.assert_equals('bar', section.get('foo'))
        section.remove()
        self.assert_not_equals('bar', section.get('foo'))

    def test_can_remove_sections_without_getting_it_first(self):
        section = self.config.get_section('fnord')
        section.change_option('foo', 'bar')
        self.assert_true('fnord' in self.trac_config.sections())
        self.assert_equals('bar', section.get('foo'))
        self.config.remove(section='fnord')
        self.assert_false(self.config.get_section('fnord').has_option('foo'))
        self.assert_not_equals('bar', section.get('foo'))

    def test_config_knows_if_an_option_is_set(self):
        self.assert_false(self.config.has_option('foo', section='fnord'))
        self.config.change_option('foo', 'bar', section='fnord')
        self.assert_true(self.config.has_option('foo', section='fnord'))

    def test_config_reloads_on_change(self):
        self.config.change_option('%s.%s' % (Type.BUG, Key.ALIAS),
                                  'Bugone',
                                  section=AgiloConfig.AGILO_TYPES,
                                  save=True)
        self.assert_equals('Bugone', self.config.ALIASES.get(Type.BUG))

    def test_config_reloads_links_configuration_on_change(self):
        self.assert_contains(
            'story',
            LinksConfiguration(
                self.env).get_allowed_destination_types('requirement'))
        self.config.change_option('allow',
                                  '',
                                  section=AgiloConfig.AGILO_LINKS,
                                  save=True)
        self.assert_not_contains(
            'story',
            LinksConfiguration(
                self.env).get_allowed_destination_types('requirement'))

    def test_config_writing_key_with_capitals(self):
        my_section = self.config.get_section('my-section')
        my_section.change_option('TestMe', 'This is a test', save=True)
        # Test that it is stored
        self.assert_equals('This is a test',
                           self.env.config.get('my-section', 'TestMe'))
        # Test that is case insensitive
        self.assert_equals('This is a test',
                           self.env.config.get('my-section', 'testme'))
        self.assert_equals('This is a test',
                           self.env.config.get('my-section', 'TESTME'))

    def test_config_is_normalizing(self):
        my_section = self.config.get_section('my-section')
        my_section.change_option('TestMe', 'This is a test', save=True)
        # check that in reality only the lowecased version is saved in the
        # config file trac.ini
        options = self.config.get_options('my-section')
        self.assert_true('testme' in options,
                         "TestMe not found in: %s" % options)
        self.assert_false('TestMe' in options, "TestMe found in: %s" % options)

    def test_config_not_updating_case_sensitive(self):
        my_section = self.config.get_section('my-section')
        my_section.change_option('TestMe', 'This is a test', save=True)
        # Test that it is asymmetric
        # Using set will not set the option as it is case insensitive and is
        # not stored because testme already exists in the trac.ini
        my_section.set_option('TESTME', 'This is another test', save=True)
        self.assert_not_equals('This is another test',
                               self.env.config.get('my-section', 'TESTME'))
        self.assert_equals('This is a test',
                           self.env.config.get('my-section', 'TESTME'))
        options = self.config.get_options('my-section')
        self.assert_true('testme' in options,
                         'TestMe not found in: %s' % options)
        self.assert_false('TestMe' in options, 'TestMe found in: %s' % options)

    def test_config_is_case_insensitive_and_overwrites(self):
        my_section = self.config.get_section('my-section')
        my_section.change_option('TestMe', 'This is a test', save=True)
        # Now change the option and check that also the old key, that is the
        # same actually changed
        my_section.change_option('TESTME', 'This is another test', save=True)
        self.assert_equals('This is another test',
                           self.env.config.get('my-section', 'TESTME'))
        self.assert_not_equals('This is a test',
                               self.env.config.get('my-section', 'testme'))
        # Now check what it is stored
        options = self.config.get_options('my-section')
        self.assert_true('testme' in options,
                         'testme not found in: %s' % options)
        self.assert_false('TESTME' in options, 'TESTME found in: %s' % options)
        # Test it is in the AgiloWrapper also after reload
        self.config.reload()
        self.assert_equals('This is another test',
                           self.config.get('TestMe', 'my-section'))

    def test_config_stores_none_as_empty_string(self):
        my_section = self.config.get_section('my-section')
        my_section.set_option('test', 'This is a test', save=True)
        self.assert_equals('This is a test',
                           self.env.config.get('my-section', 'test'))
        # Now change the option and check that also the old key, that is the
        # same actually changed
        my_section.change_option('test', None, save=True)
        self.assert_not_equals('This is a test',
                               self.env.config.get('my-section', 'test'))
        self.assert_equals('', self.env.config.get('my-section', 'test'))
        # Check real config
        self.env.config.set('my-section', 'test', None)
        self.env.config.save()
        self.assert_equals('', self.env.config.get('my-section', 'test'))

    def test_dont_strip_non_string_values(self):
        self.assert_true(self.config.get('foo', default=True, section='trac'))

    def test_sets_default_agilo_logo_on_new_install(self):
        # should be set by the initialization so let's check it
        agilo_logo_src = 'agilo/images/default_logo.png'
        self.assert_equals(agilo_logo_src,
                           self.env.config.get('header_logo', 'src'))

    def test_do_not_sets_default_logo_if_changed(self):
        test_src = 'my_logo'
        agilo_config = AgiloConfig(self.env)
        header_logo = agilo_config.get_section('header_logo')
        header_logo.change_option('src', test_src)
        self.assert_equals(test_src, header_logo.get('src'))
        set_default_agilo_logo(agilo_config)
        self.assert_equals(test_src, header_logo.get('src'))

    def test_sets_agilo_favicon_on_new_install(self):
        agilo_favicon = 'agilo/images/favicon.ico'
        self.assert_equals(agilo_favicon,
                           self.env.config.get('project', 'icon'))

    def test_doesnt_overwrite_custom_favicons(self):
        custom_favicon = 'fnord'
        project_section = AgiloConfig(self.env).get_section('project')
        project_section.change_option('icon', custom_favicon)
        self.assert_equals(custom_favicon, project_section.get('icon'))

        initialize_config(self.env, {})
        project_section = AgiloConfig(self.env).get_section('project')
        self.assert_equals(custom_favicon, project_section.get('icon'))
Beispiel #10
0
class LinksAdminPanel(AgiloAdminPanel):
    """Administration panel for links.
    Needs to get imported in agilo/admin/__init__.py in order to appear
    on the web interface."""

    _type = 'links'
    _label = ('Links', _('Links'))

    def __init__(self):
        self.config = AgiloConfig(self.env)
        self.links = self.config.get_section(AgiloConfig.AGILO_LINKS)
        self.allowed_links = self._get_allowed_links()

    def _get_allowed_links(self):
        """Returns the dictionary containing the allowed links pairs"""
        links_configuration = LinksConfiguration(self.env)
        return dict([(l, list(links_configuration.extract_types(l)))
                     for l in self.links.get_list(LinkOption.ALLOW)])

    def _get_delete_pairs(self):
        """Returns the dictionary containing the cascade delete pairs"""
        links_configuration = LinksConfiguration(self.env)
        return dict([(l, list(links_configuration.extract_types(l)))
                     for l in self.links.get_list(LinkOption.DELETE)])

    def detail_view(self, req, cat, page, link):
        links_configuration = LinksConfiguration(self.env)
        (source, target) = links_configuration.extract_types(link)
        copy_fields = [f.strip() for f in self.links.get('%s.%s.%s' % \
                                                         (source, target, LinkOption.COPY),
                                                         default='').split(',')]
        show_fields = [f.strip() for f in self.links.get('%s.%s.%s' % \
                                                         (source, target, LinkOption.SHOW),
                                                         default='').split(',')]
        ticket_system = AgiloTicketSystem(self.env)
        # dict of name->label for all core and custom fields
        labels = dict([(f['name'], f['label'])
                       for f in ticket_system.get_ticket_fields()])
        cascade_delete = source + '-' + target in self._get_delete_pairs()
        data = {
            'view': 'detail',
            'link': link,
            'source': source,
            'target': target,
            'source_fields': self.config.TYPES[source],
            'target_fields': self.config.TYPES[target],
            'labels': labels,
            'copy_fields': copy_fields,
            'show_fields': show_fields,
            'cascade_delete': cascade_delete
        }
        return 'agilo_admin_links.html', data

    def detail_save_view(self, req, cat, page, link):
        links_configuration = LinksConfiguration(self.env)
        (source, target) = links_configuration.extract_types(link)
        fields = req.args.get('copy_fields', [])
        if type(fields) != type([]):
            fields = [fields]
        # set copy options for this link
        self.links.change_option(
            '%s.%s.%s' % (source, target, LinkOption.COPY), ', '.join(fields))

        fields = req.args.get('show_fields', [])
        if type(fields) != type([]):
            fields = [fields]
        # set show options for this link
        self.links.change_option(
            '%s.%s.%s' % (source, target, LinkOption.SHOW), ', '.join(fields))

        cascade_delete = req.args.get('cascade_delete')
        delete_pairs = self._get_delete_pairs()
        if cascade_delete and source + '-' + target not in delete_pairs:
            delete_pairs[source + '-' + target] = (source, target)
            self.links.change_option(LinkOption.DELETE,
                                     ', '.join(delete_pairs.keys()))

        elif not cascade_delete and source + '-' + target in self._get_delete_pairs(
        ):
            del delete_pairs[source + '-' + target]
            self.links.change_option(LinkOption.DELETE,
                                     ', '.join(delete_pairs.keys()))

        # saved it, redirect back to admin view
        self.links.save()
        req.redirect(req.href.admin(cat, page))

    def list_view(self, req, cat, page):
        data = {
            'view': 'list',
            'allowed_links': self._get_allowed_links(),
            'available_types': self.config.get_available_types(strict=True),
        }
        return 'agilo_admin_links.html', data

    def list_save_view(self, req, cat, page):
        source = req.args.get('source')
        target = req.args.get('target')
        if req.args.get('add') and source and target:
            if (source, target) in self.allowed_links:
                # link already exists, redirect to it
                req.redirect(
                    req.href.admin(cat, page, '%s-%s' % (source, target)))
            # Set, save because there is the redirect
            self.links.change_option(LinkOption.ALLOW, '%s, %s-%s' % \
                                     (self.links.get(LinkOption.ALLOW, default=''),
                                      source, target), save=True)
            return req.redirect(
                req.href.admin(cat, page, '%s-%s' % (source, target)))

        # Remove components
        if req.args.get('remove'):
            sel = req.args.get('sel')
            if not sel:
                raise TracError(_('No link selected'))
            if not isinstance(sel, list):
                sel = [sel]

            # delete selection from allowed links
            for s in sel:
                del self.allowed_links[s]

            # write new value back to config, and save
            self.links.change_option(LinkOption.ALLOW,
                                     ', '.join(self.allowed_links.keys()),
                                     save=True)
        return req.redirect(req.href.admin(cat, page))
Beispiel #11
0
class LinksAdminPanel(AgiloAdminPanel):
    """Administration panel for links.
    Needs to get imported in agilo/admin/__init__.py in order to appear
    on the web interface."""
    
    _type = 'links'
    _label = ('Links', _('Links'))

    def __init__(self):
        self.config = AgiloConfig(self.env)
        self.links = self.config.get_section(AgiloConfig.AGILO_LINKS)
        self.allowed_links = self._get_allowed_links()
    
    def _get_allowed_links(self):
        """Returns the dictionary containing the allowed links pairs"""
        links_configuration = LinksConfiguration(self.env)
        return dict([(l, list(links_configuration.extract_types(l))) for l in self.links.get_list(LinkOption.ALLOW)])

    def _get_delete_pairs(self):
        """Returns the dictionary containing the cascade delete pairs"""
        links_configuration = LinksConfiguration(self.env)
        return dict([(l, list(links_configuration.extract_types(l))) for l in self.links.get_list(LinkOption.DELETE)])

    def detail_view(self, req, cat, page, link):
        links_configuration = LinksConfiguration(self.env)
        (source, target) = links_configuration.extract_types(link)
        copy_fields = [f.strip() for f in self.links.get('%s.%s.%s' % \
                                                         (source, target, LinkOption.COPY), 
                                                         default='').split(',')]
        show_fields = [f.strip() for f in self.links.get('%s.%s.%s' % \
                                                         (source, target, LinkOption.SHOW), 
                                                         default='').split(',')]
        ticket_system = AgiloTicketSystem(self.env)
        # dict of name->label for all core and custom fields
        labels = dict([(f['name'], f['label']) for f in ticket_system.get_ticket_fields()])
        cascade_delete = source+'-'+target in self._get_delete_pairs()
        data = {
            'view': 'detail',
            'link': link,
            'source' : source,
            'target' : target,
            'source_fields' : self.config.TYPES[source],
            'target_fields' : self.config.TYPES[target],
            'labels' : labels,
            'copy_fields' : copy_fields,
            'show_fields' : show_fields,
            'cascade_delete': cascade_delete
        }
        return 'agilo_admin_links.html', data
        
    def detail_save_view(self, req, cat, page, link):
        links_configuration = LinksConfiguration(self.env)
        (source, target) = links_configuration.extract_types(link)
        fields = req.args.get('copy_fields', [])
        if type(fields) != type([]):
            fields = [fields]
        # set copy options for this link
        self.links.change_option('%s.%s.%s' % (source, target, LinkOption.COPY),
                                 ', '.join(fields))
        
        fields = req.args.get('show_fields', [])
        if type(fields) != type([]):
            fields = [fields]
        # set show options for this link
        self.links.change_option('%s.%s.%s' % (source, target, LinkOption.SHOW),
                                 ', '.join(fields))
        
        cascade_delete = req.args.get('cascade_delete')
        delete_pairs = self._get_delete_pairs()
        if cascade_delete and source+'-'+target not in delete_pairs:
            delete_pairs[source+'-'+target] = (source, target)
            self.links.change_option(LinkOption.DELETE, 
                                     ', '.join(delete_pairs.keys()))

        elif not cascade_delete and source+'-'+target in self._get_delete_pairs():
            del delete_pairs[source+'-'+target]
            self.links.change_option(LinkOption.DELETE, 
                                     ', '.join(delete_pairs.keys()))
            
        
        # saved it, redirect back to admin view
        self.links.save()
        req.redirect(req.href.admin(cat, page))
   
    def list_view(self, req, cat, page):
        data = {
            'view': 'list',
            'allowed_links': self._get_allowed_links(),
            'available_types' : self.config.get_available_types(strict=True),
        }
        return 'agilo_admin_links.html', data
        
    def list_save_view(self, req, cat, page):
        source = req.args.get('source')
        target = req.args.get('target')
        if req.args.get('add') and source and target:
            if (source, target) in self.allowed_links:
                # link already exists, redirect to it
                req.redirect(req.href.admin(cat, page, '%s-%s' % (source, target)))
            # Set, save because there is the redirect
            self.links.change_option(LinkOption.ALLOW, '%s, %s-%s' % \
                                     (self.links.get(LinkOption.ALLOW, default=''), 
                                      source, target), save=True)
            return req.redirect(req.href.admin(cat, page, '%s-%s' % (source, target)))

        # Remove components
        if req.args.get('remove'):
            sel = req.args.get('sel')
            if not sel:
                raise TracError(_('No link selected'))
            if not isinstance(sel, list):
                sel = [sel]

            # delete selection from allowed links
            for s in sel:
                del self.allowed_links[s]
                
            # write new value back to config, and save
            self.links.change_option(LinkOption.ALLOW, 
                                     ', '.join(self.allowed_links.keys()),
                                     save=True)
        return req.redirect(req.href.admin(cat, page))