Changeset 16940


Ignore:
Timestamp:
Oct 31, 2017, 8:39:38 PM (7 years ago)
Author:
Ryan J Ollos
Message:

TracContacts 0.3dev: Make compatible with Trac 1.2+

Location:
contactsplugin/1.2
Files:
9 edited
1 copied

Legend:

Unmodified
Added
Removed
  • contactsplugin/1.2/contacts/__init__.py

    r7488 r16940  
     1import pkg_resources
     2pkg_resources.require('Trac > 1.2')
  • contactsplugin/1.2/contacts/db.py

    r16364 r16940  
    1 from trac.core import *
    2 from trac.db.schema import Table, Column, Index
     1# -*- coding: utf-8 -*-
     2
     3from trac.core import Component, implements
     4from trac.db.api import DatabaseManager
     5from trac.db.schema import Table, Column
    36from trac.env import IEnvironmentSetupParticipant
    47
    58
    69class ContactsEnvironment(Component):
     10
    711    implements(IEnvironmentSetupParticipant)
    812
    9     def __init__(self):
    10         self.db_version_key = 'contacts_version'
    11         #   Increment this whenever there are DB changes
    12         self.db_version = 1
    13         self.db_installed_version = None
     13    db_version_key = 'contacts_version'
     14    db_version = 1
    1415
    15         #   Check DB for to see if we need to add new tables, etc.
    16         db = self.env.get_db_cnx()
    17         cursor = db.cursor()
    18         cursor.execute("SELECT value FROM system WHERE name=%s", (self.db_version_key,))
    19         try:
    20             self.db_installed_version = int(cursor.fetchone()[0])
    21         except: #   Version did not exists, so the plugin was just installed
    22             self.db_installed_version = 0
    23             cursor.execute("INSERT INTO system (name, value) VALUES (%s, %s)", (self.db_version_key,
    24                 self.db_installed_version))
    25             db.commit()
    26             db.close()
     16    contacts_table = [
     17        Table('contact', key=('id',))[
     18            Column('id', auto_increment=True),
     19            Column('first'),
     20            Column('last'),
     21            Column('position'),
     22            Column('email'),
     23            Column('phone')
     24        ]
     25    ]
    2726
    28     def system_needs_upgrade(self):
    29         return self.db_installed_version < self.db_version
     27    # IEnvironmentSetupParticipant methods
    3028
    31     def do_db_upgrade(self):
    32         db = self.env.get_db_cnx()
    33         cursor = db.cursor()
     29    def environment_created(self):
     30        self.upgrade_environment()
    3431
    35         try:
    36             if self.db_installed_version < 1:
    37                 contacts_table = Table('contact', key=('id',))[
    38                     Column('id', type='int', auto_increment=True),
    39                     Column('first'),
    40                     Column('last'),
    41                     Column('position'),
    42                     Column('email'),
    43                     Column('phone')
    44                 ]
    45                 for stmt in to_sql(self.env, contacts_table):
    46                     cursor.execute(stmt)
    47             cursor.execute("UPDATE system SET value = %s WHERE name = %s", (self.db_version, self.db_version_key))
     32    def environment_needs_upgrade(self):
     33        dbm = DatabaseManager(self.env)
     34        return dbm.needs_upgrade(self.db_version, self.db_version_key)
    4835
    49         except Exception, e:
    50             import traceback
    51             print traceback.format_exc(e)
    52             db.rollback()
    53 
    54     #   IEnvironmentSetupParticipant methods
    55     def environment_created(self):
    56         """Called when a new Trac environment is created."""
    57         if self.environment_needs_upgrade(None):
    58             self.upgrade_environment(None)
    59 
    60     def environment_needs_upgrade(self, db):
    61         """Called when Trac checks whether the environment needs to be upgraded.
    62 
    63         Should return `True` if this participant needs an upgrade to be
    64         performed, `False` otherwise.
    65 
    66         """
    67         return self.system_needs_upgrade()
    68 
    69     def upgrade_environment(self, db):
    70         """Actually perform an environment upgrade.
    71 
    72         Implementations of this method should not commit any database
    73         transactions. This is done implicitly after all participants have
    74         performed the upgrades they need without an error being raised.
    75         """
    76         print 'Contacts needs an upgrade'
    77         self.do_db_upgrade()
    78 
    79 
    80 #   Taken from the fullblogplugin source
    81 def to_sql(env, table):
    82     """ Convenience function to get the to_sql for the active connector."""
    83     from trac.db.api import DatabaseManager
    84     dc = DatabaseManager(env)._get_connector()[0]
    85     return dc.to_sql(table)
     36    def upgrade_environment(self):
     37        dbm = DatabaseManager(self.env)
     38        dbm.create_tables(self.contacts_table)
     39        dbm.set_database_version(self.db_version, self.db_version_key)
  • contactsplugin/1.2/contacts/htdocs/edit_contact.css

    r7488 r16940  
    1 .field input.edit {
    2     display: none;
    3 }
     1.field input.edit { display: none; }
  • contactsplugin/1.2/contacts/htdocs/edit_contact.js

    r16364 r16940  
    1 jQuery(document).ready(function($) {
     1jQuery(function($) {
    22    $('.static, .field label').click(function() {
    33        p = $(this).parent()
  • contactsplugin/1.2/contacts/model.py

    r16364 r16940  
    1 from trac.core import *
     1# -*- coding: utf-8 -*-
     2
     3import re
     4
     5from trac.core import TracError
    26
    37
     
    1115
    1216    def load_by_id(self, id):
    13         id = int(id)
    14         db = self.env.get_db_cnx()
    15         cursor = db.cursor()
    16         cursor.execute("SELECT first, last, position, email, phone FROM contact WHERE id = %s", (id,))
    17         row = cursor.fetchone()
    18         if not row:
     17        for row in self.env.db_query("""
     18                SELECT first, last, position, email, phone
     19                FROM contact WHERE id = %s
     20                """, (int(id),)):
     21            self.id = id
     22            self.first = row[0]
     23            self.last = row[1]
     24            self.position = row[2]
     25            self.email = row[3]
     26            self.phone = row[4]
     27            break
     28        else:
    1929            raise TracError('Contact with id %s does not exist.' % id)
    20         self.id = id
    21         self.first = row[0]
    22         self.last = row[1]
    23         self.position = row[2]
    24         self.email = row[3]
    25         self.phone = row[4]
    2630
    2731    def clear(self):
     
    4145
    4246    def clean(self):
    43         import re
    4447        p = re.compile(r'<.*?>')
    4548        self.first = p.sub('', self.first)
     
    5255        if not self.id:
    5356            raise TracError('Trying to update when there is no id!')
    54         db = self.env.get_db_cnx()
    55         cursor = db.cursor()
    56         cursor.execute("UPDATE contact SET first=%s, last=%s, position=%s, email=%s, phone=%s WHERE id=%s",
    57             (self.first, self.last, self.position, self.email, self.phone, self.id))
    58         db.commit()
     57        self.env.db_transaction("""
     58            UPDATE contact
     59             SET first=%s, last=%s, position=%s, email=%s, phone=%s
     60             WHERE id=%s
     61             """, (self.first, self.last, self.position, self.email,
     62                   self.phone, self.id))
    5963
    6064    def insert(self):
    61         db = self.env.get_db_cnx()
    62         cursor = db.cursor()
    63         cursor.execute("INSERT INTO contact (first, last, position, email, phone) VALUES (%s,%s,%s,%s,%s)",
    64             (self.first, self.last, self.position, self.email, self.phone))
    65         self.id = db.get_last_id(cursor, 'contact')
    66         db.commit()
     65        with self.env.db_transaction as db:
     66            cursor = db.cursor()
     67            cursor.execute("""
     68                INSERT INTO contact (first, last, position, email, phone)
     69                VALUES (%s,%s,%s,%s,%s)
     70                """, (self.first, self.last, self.position,
     71                      self.email, self.phone))
     72            self.id = db.get_last_id(cursor, 'contact')
    6773
    6874    def last_first(self):
     
    8086
    8187
    82 def ContactIterator(env, order_by = None):
     88def ContactIterator(env, order_by=None):
    8389    if not order_by:
    8490        order_by = ('last', 'first')
     
    8793            raise ValueError("Must be one of %r: %r" % (_COLS, name))
    8894
    89     db = env.get_db_cnx()
    90     if hasattr(db, 'quote'):
    91         quote = db.quote
    92     else:
    93         quote = lambda name: name
    94     cursor = db.cursor()
    95 
    96     cursor.execute("""
    97         SELECT id, first, last, position, email, phone
    98         FROM contact ORDER BY %s
    99         """ % ','.join(quote(v) for v in order_by))
    100 
    101     for id, first, last, position, email, phone in cursor:
    102         contact = Contact(env)
    103         contact.id = id
    104         contact.first = first
    105         contact.last = last
    106         contact.position = position
    107         contact.email = email
    108         contact.phone = phone
    109         yield contact
     95    with env.db_query as db:
     96        for id, first, last, position, email, phone in db("""
     97                SELECT id, first, last, position, email, phone
     98                FROM contact ORDER BY %s
     99                """ % ','.join(db.quote(v) for v in order_by)):
     100            contact = Contact(env)
     101            contact.id = id
     102            contact.first = first
     103            contact.last = last
     104            contact.position = position
     105            contact.email = email
     106            contact.phone = phone
     107            yield contact
  • contactsplugin/1.2/contacts/templates/contact.html

    r7488 r16940  
    66      xmlns:xi="http://www.w3.org/2001/XInclude">
    77  <xi:include href="layout.html" />
    8   <xi:include href="macros.html" />
    98  <head>
    109    <title>$title</title>
  • contactsplugin/1.2/contacts/templates/contacts.html

    r7488 r16940  
    66      xmlns:xi="http://www.w3.org/2001/XInclude">
    77  <xi:include href="layout.html" />
    8   <xi:include href="macros.html" />
    98  <head>
    109    <title>Contacts</title>
  • contactsplugin/1.2/contacts/web_ui.py

    r16364 r16940  
     1# -*- coding: utf-8 -*-
     2
    13import re
    24from pkg_resources import resource_filename
    35
    4 from trac.core import *
     6from trac.core import Component, implements
    57from trac.perm import IPermissionRequestor
    68from trac.util.html import tag
    79from trac.util.translation import _
    810from trac.web.api import IRequestHandler
    9 from trac.web.chrome import add_script, add_stylesheet, INavigationContributor, ITemplateProvider
     11from trac.web.chrome import (
     12    INavigationContributor, ITemplateProvider, add_script, add_stylesheet)
    1013
    1114from model import Contact, ContactIterator
     
    1316
    1417class ContactsAdminPanel(Component):
    15     """ Pages for adding/editing contacts. """
    16     implements(INavigationContributor, ITemplateProvider, IRequestHandler, IPermissionRequestor)
     18    """Pages for adding/editing contacts."""
     19
     20    implements(INavigationContributor, IPermissionRequestor, IRequestHandler,
     21               ITemplateProvider)
    1722
    1823    # INavigationContributor methods
    1924
    2025    def get_active_navigation_item(self, req):
    21         """This method is only called for the `IRequestHandler` processing the
    22         request.
    23 
    24         It should return the name of the navigation item that should be
    25         highlighted as active/current.
    26         """
    2726        return 'contacts'
    2827
    2928    def get_navigation_items(self, req):
    30         """Should return an iterable object over the list of navigation items to
    31         add, each being a tuple in the form (category, name, text).
    32         """
    3329        if 'CONTACTS_VIEW' in req.perm('contacts'):
    34             yield('mainnav', 'contacts', tag.a(_('Contacts'), href=req.href.contacts()))
     30            yield ('mainnav', 'contacts', tag.a(_('Contacts'),
     31                   href=req.href.contacts()))
    3532
    3633    # ITemplateProvider methods
     
    4037
    4138    def get_templates_dirs(self):
    42         """Return a list of directories containing the provided template
    43         files.
    44         """
    4539        return [resource_filename('contacts', 'templates')]
    4640
     
    5347
    5448    def process_request(self, req):
    55         """Process the request. For ClearSilver, return a (template_name,
    56         content_type) tuple, where `template` is the ClearSilver template to use
    57         (either a `neo_cs.CS` object, or the file name of the template), and
    58         `content_type` is the MIME type of the content. For Genshi, return a
    59         (template_name, data, content_type) tuple, where `data` is a dictionary
    60         of substitutions for the template.
    61 
    62         For both templating systems, "text/html" is assumed if `content_type` is
    63         `None`.
    64 
    65         Note that if template processing should not occur, this method can
    66         simply send the response itself and not return anything.
    67         """
    68         req.perm('contacts').assert_permission('CONTACTS_VIEW')
     49        req.perm('contacts').require('CONTACTS_VIEW')
    6950
    7051        add_stylesheet(req, 'common/css/admin.css')
     
    7556            }, None)
    7657
    77         req.perm('contacts').assert_permission('CONTACTS_ADMIN')
     58        req.perm('contacts').require('CONTACTS_ADMIN')
    7859
    79         #   We will be using the contact.html file, so include it's JS
    80         #   Get Contact ID
    8160        params = req.path_info.split('/')
    8261        contact_id = None
     
    8564        contact = Contact(self.env, contact_id)
    8665
    87         #   Check if saving
    88         if req.method == 'POST' and req.args.get('addcontact'):
     66        if req.method == 'POST' and 'addcontact' in req.args:
    8967            contact.update_from_req(req)
    9068            contact.save()
    91             if (req.args.get('redirect')):
    92                 req.redirect(req.args.get('redirect') + '?contact_id=%d' % contact.id)
     69            if 'redirect' in req.args:
     70                req.redirect(req.href.contacts(contact.id))
    9371            else:
    9472                req.redirect(req.href.contacts())
    95             #   redirecting, so the rest of this function does not get ran
    9673
    9774        template = {'contact': contact}
    98         if (len(params) > 2 and params[2].isdigit()):
     75        if len(params) > 2 and params[2].isdigit():
    9976            add_script(req, 'contacts/edit_contact.js')
    10077            add_stylesheet(req, 'contacts/edit_contact.css')
     
    10481            template['title'] = 'Add Contact'
    10582            template['edit'] = False
    106         if (req.args.get('redirect')):
     83        if 'redirect' in req.args:
    10784            template['redirect'] = req.args.get('redirect')
    10885        else:
    10986            template['redirect'] = None
    11087
    111         return ('contact.html', template, None)
     88        return 'contact.html', template, None
    11289
    11390    # IPermissionRequest methods
    11491
    11592    def get_permission_actions(self):
    116         """Return a list of actions defined by this component.
    117 
    118         The items in the list may either be simple strings, or
    119         `(string, sequence)` tuples. The latter are considered to be "meta
    120         permissions" that group several simple actions under one name for
    121         convenience.
    122         """
    12393        return ['CONTACTS_VIEW', ('CONTACTS_ADMIN', ['CONTACTS_VIEW'])]
  • contactsplugin/1.2/setup.py

    r16364 r16940  
    11#!/usr/bin/env python
     2# -*- coding: utf-8 -*-
    23
    34from setuptools import setup
    45
    5 PACKAGE = 'contacts'
    6 
    76setup(
    8     name=PACKAGE,
    9     description='Plugin which keeps trac of Contact data',
     7    name='TracContacts',
     8    description='Add contact data to Trac',
    109    keywords='trac plugin contact person address addressbook address-book',
    11     version='0.2',
     10    version='0.3',
    1211    url='https://trac-hacks.org/wiki/ContactsPlugin',
    1312    license='http://www.opensource.org/licenses/mit-license.php',
     
    1514    author_email='clubinski@networkninja.com',
    1615    long_description="""
    17     Adds a new menu item for contacts. Stores this contacts in the db with their first name, last name, position,
    18     email, and phone.
     16    Adds a new menu item for contacts. Stores the contacts with their
     17    first name, last name, position, email, and phone.
    1918    """,
    20     packages=[PACKAGE],
    21     package_data={PACKAGE : ['templates/*.html', 'htdocs/*']},
    22     entry_points = {
     19    packages=['contacts'],
     20    package_data={
     21        'contacts': [
     22            'templates/*.html',
     23            'htdocs/*'
     24        ]
     25    },
     26    entry_points={
    2327        'trac.plugins': [
    2428            'contacts.db = contacts.db',
    2529            'contacts.web_ui = contacts.web_ui',
    2630        ]
    27     })
     31    }
     32)
Note: See TracChangeset for help on using the changeset viewer.