Changeset 16940
- Timestamp:
- Oct 31, 2017, 8:39:38 PM (7 years ago)
- Location:
- contactsplugin/1.2
- Files:
-
- 9 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
contactsplugin/1.2/contacts/__init__.py
r7488 r16940 1 import pkg_resources 2 pkg_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 3 from trac.core import Component, implements 4 from trac.db.api import DatabaseManager 5 from trac.db.schema import Table, Column 3 6 from trac.env import IEnvironmentSetupParticipant 4 7 5 8 6 9 class ContactsEnvironment(Component): 10 7 11 implements(IEnvironmentSetupParticipant) 8 12 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 14 15 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 ] 27 26 28 def system_needs_upgrade(self): 29 return self.db_installed_version < self.db_version 27 # IEnvironmentSetupParticipant methods 30 28 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() 34 31 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) 48 35 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($) {1 jQuery(function($) { 2 2 $('.static, .field label').click(function() { 3 3 p = $(this).parent() -
contactsplugin/1.2/contacts/model.py
r16364 r16940 1 from trac.core import * 1 # -*- coding: utf-8 -*- 2 3 import re 4 5 from trac.core import TracError 2 6 3 7 … … 11 15 12 16 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: 19 29 raise TracError('Contact with id %s does not exist.' % id) 20 self.id = id21 self.first = row[0]22 self.last = row[1]23 self.position = row[2]24 self.email = row[3]25 self.phone = row[4]26 30 27 31 def clear(self): … … 41 45 42 46 def clean(self): 43 import re44 47 p = re.compile(r'<.*?>') 45 48 self.first = p.sub('', self.first) … … 52 55 if not self.id: 53 56 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)) 59 63 60 64 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') 67 73 68 74 def last_first(self): … … 80 86 81 87 82 def ContactIterator(env, order_by =None):88 def ContactIterator(env, order_by=None): 83 89 if not order_by: 84 90 order_by = ('last', 'first') … … 87 93 raise ValueError("Must be one of %r: %r" % (_COLS, name)) 88 94 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 6 6 xmlns:xi="http://www.w3.org/2001/XInclude"> 7 7 <xi:include href="layout.html" /> 8 <xi:include href="macros.html" />9 8 <head> 10 9 <title>$title</title> -
contactsplugin/1.2/contacts/templates/contacts.html
r7488 r16940 6 6 xmlns:xi="http://www.w3.org/2001/XInclude"> 7 7 <xi:include href="layout.html" /> 8 <xi:include href="macros.html" />9 8 <head> 10 9 <title>Contacts</title> -
contactsplugin/1.2/contacts/web_ui.py
r16364 r16940 1 # -*- coding: utf-8 -*- 2 1 3 import re 2 4 from pkg_resources import resource_filename 3 5 4 from trac.core import *6 from trac.core import Component, implements 5 7 from trac.perm import IPermissionRequestor 6 8 from trac.util.html import tag 7 9 from trac.util.translation import _ 8 10 from trac.web.api import IRequestHandler 9 from trac.web.chrome import add_script, add_stylesheet, INavigationContributor, ITemplateProvider 11 from trac.web.chrome import ( 12 INavigationContributor, ITemplateProvider, add_script, add_stylesheet) 10 13 11 14 from model import Contact, ContactIterator … … 13 16 14 17 class 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) 17 22 18 23 # INavigationContributor methods 19 24 20 25 def get_active_navigation_item(self, req): 21 """This method is only called for the `IRequestHandler` processing the22 request.23 24 It should return the name of the navigation item that should be25 highlighted as active/current.26 """27 26 return 'contacts' 28 27 29 28 def get_navigation_items(self, req): 30 """Should return an iterable object over the list of navigation items to31 add, each being a tuple in the form (category, name, text).32 """33 29 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())) 35 32 36 33 # ITemplateProvider methods … … 40 37 41 38 def get_templates_dirs(self): 42 """Return a list of directories containing the provided template43 files.44 """45 39 return [resource_filename('contacts', 'templates')] 46 40 … … 53 47 54 48 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') 69 50 70 51 add_stylesheet(req, 'common/css/admin.css') … … 75 56 }, None) 76 57 77 req.perm('contacts'). assert_permission('CONTACTS_ADMIN')58 req.perm('contacts').require('CONTACTS_ADMIN') 78 59 79 # We will be using the contact.html file, so include it's JS80 # Get Contact ID81 60 params = req.path_info.split('/') 82 61 contact_id = None … … 85 64 contact = Contact(self.env, contact_id) 86 65 87 # Check if saving 88 if req.method == 'POST' and req.args.get('addcontact'): 66 if req.method == 'POST' and 'addcontact' in req.args: 89 67 contact.update_from_req(req) 90 68 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)) 93 71 else: 94 72 req.redirect(req.href.contacts()) 95 # redirecting, so the rest of this function does not get ran96 73 97 74 template = {'contact': contact} 98 if (len(params) > 2 and params[2].isdigit()):75 if len(params) > 2 and params[2].isdigit(): 99 76 add_script(req, 'contacts/edit_contact.js') 100 77 add_stylesheet(req, 'contacts/edit_contact.css') … … 104 81 template['title'] = 'Add Contact' 105 82 template['edit'] = False 106 if (req.args.get('redirect')):83 if 'redirect' in req.args: 107 84 template['redirect'] = req.args.get('redirect') 108 85 else: 109 86 template['redirect'] = None 110 87 111 return ('contact.html', template, None)88 return 'contact.html', template, None 112 89 113 90 # IPermissionRequest methods 114 91 115 92 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, or119 `(string, sequence)` tuples. The latter are considered to be "meta120 permissions" that group several simple actions under one name for121 convenience.122 """123 93 return ['CONTACTS_VIEW', ('CONTACTS_ADMIN', ['CONTACTS_VIEW'])] -
contactsplugin/1.2/setup.py
r16364 r16940 1 1 #!/usr/bin/env python 2 # -*- coding: utf-8 -*- 2 3 3 4 from setuptools import setup 4 5 5 PACKAGE = 'contacts'6 7 6 setup( 8 name= PACKAGE,9 description=' Plugin which keeps trac of Contact data',7 name='TracContacts', 8 description='Add contact data to Trac', 10 9 keywords='trac plugin contact person address addressbook address-book', 11 version='0. 2',10 version='0.3', 12 11 url='https://trac-hacks.org/wiki/ContactsPlugin', 13 12 license='http://www.opensource.org/licenses/mit-license.php', … … 15 14 author_email='clubinski@networkninja.com', 16 15 long_description=""" 17 Adds a new menu item for contacts. Stores th is 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. 19 18 """, 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={ 23 27 'trac.plugins': [ 24 28 'contacts.db = contacts.db', 25 29 'contacts.web_ui = contacts.web_ui', 26 30 ] 27 }) 31 } 32 )
Note: See TracChangeset
for help on using the changeset viewer.