From 87dcb51600720ce621043b453cbaa4a451fc87d7 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Tue, 12 Sep 2023 18:20:15 -0500 Subject: [PATCH] Initial version, to expose NationBuilder cache tables --- .gitignore | 1 + CHANGELOG.md | 10 ++ MANIFEST.in | 3 + README.md | 11 ++ setup.cfg | 37 +++++ setup.py | 29 ++++ tailbone_nationbuilder/__init__.py | 27 ++++ tailbone_nationbuilder/_version.py | 3 + tailbone_nationbuilder/menus.py | 56 ++++++++ tailbone_nationbuilder/provider.py | 38 ++++++ tailbone_nationbuilder/templates/.keepme | 0 tailbone_nationbuilder/views/__init__.py | 0 .../views/nationbuilder/__init__.py | 37 +++++ .../views/nationbuilder/master.py | 33 +++++ .../views/nationbuilder/people.py | 127 ++++++++++++++++++ tasks.py | 51 +++++++ 16 files changed, 463 insertions(+) create mode 100644 .gitignore create mode 100644 CHANGELOG.md create mode 100644 MANIFEST.in create mode 100644 README.md create mode 100644 setup.cfg create mode 100644 setup.py create mode 100644 tailbone_nationbuilder/__init__.py create mode 100644 tailbone_nationbuilder/_version.py create mode 100644 tailbone_nationbuilder/menus.py create mode 100644 tailbone_nationbuilder/provider.py create mode 100644 tailbone_nationbuilder/templates/.keepme create mode 100644 tailbone_nationbuilder/views/__init__.py create mode 100644 tailbone_nationbuilder/views/nationbuilder/__init__.py create mode 100644 tailbone_nationbuilder/views/nationbuilder/master.py create mode 100644 tailbone_nationbuilder/views/nationbuilder/people.py create mode 100644 tasks.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f0b65c5 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +tailbone_nationbuilder.egg-info/ diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..d02d657 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,10 @@ + +# Changelog +All notable changes to tailbone-nationbuilder will be documented in this file. + +The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) +and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). + +## [0.1.0] - ?? +### Added +- Initial version. diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..dd613e3 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,3 @@ +include *.md +include *.rst +recursive-include tailbone_nationbuilder/templates *.mako diff --git a/README.md b/README.md new file mode 100644 index 0000000..84caa1d --- /dev/null +++ b/README.md @@ -0,0 +1,11 @@ + +# tailbone-nationbuilder + +Rattail is a retail software framework, released under the GNU General +Public License. + +This package contains software interfaces for +[NationBuilder](https://nationbuilder.com/). + +Please see the [Rattail Project](https://rattailproject.org/) +for more information. diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..163e971 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,37 @@ +# -*- coding: utf-8; -*- + +[metadata] +name = tailbone-nationbuilder +version = attr: tailbone_nationbuilder.__version__ +author = Lance Edgar +author_email = lance@edbob.org +url = https://rattailproject.org/ +license = GNU GPL v3 +description = Tailbone integration package for NationBuilder +long_description = file: README.md +classifiers = + Development Status :: 4 - Beta + Environment :: Web Environment + Framework :: Pyramid + Intended Audience :: Developers + License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+) + Natural Language :: English + Operating System :: OS Independent + Programming Language :: Python + Programming Language :: Python :: 3 + Topic :: Office/Business + Topic :: Software Development :: Libraries :: Python Modules + + +[options] +install_requires = + Tailbone + +packages = find: +include_package_data = True + + +[options.entry_points] + +tailbone.providers = + tailbone_nationbuilder = tailbone_nationbuilder.provider:TailboneNationBuilderProvider diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..cd3f6a5 --- /dev/null +++ b/setup.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8; -*- +################################################################################ +# +# Rattail -- Retail Software Framework +# Copyright © 2010-2023 Lance Edgar +# +# This file is part of Rattail. +# +# Rattail is free software: you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation, either version 3 of the License, or (at your option) any later +# version. +# +# Rattail is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# Rattail. If not, see . +# +################################################################################ +""" +tailbone-nationbuilder setup script +""" + +from setuptools import setup + +setup() diff --git a/tailbone_nationbuilder/__init__.py b/tailbone_nationbuilder/__init__.py new file mode 100644 index 0000000..9aa20aa --- /dev/null +++ b/tailbone_nationbuilder/__init__.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8; -*- +################################################################################ +# +# Rattail -- Retail Software Framework +# Copyright © 2010-2023 Lance Edgar +# +# This file is part of Rattail. +# +# Rattail is free software: you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation, either version 3 of the License, or (at your option) any later +# version. +# +# Rattail is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# Rattail. If not, see . +# +################################################################################ +""" +tailbone-nationbuilder package root +""" + +from ._version import __version__ diff --git a/tailbone_nationbuilder/_version.py b/tailbone_nationbuilder/_version.py new file mode 100644 index 0000000..e41b669 --- /dev/null +++ b/tailbone_nationbuilder/_version.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8; -*- + +__version__ = '0.1.0' diff --git a/tailbone_nationbuilder/menus.py b/tailbone_nationbuilder/menus.py new file mode 100644 index 0000000..69f48db --- /dev/null +++ b/tailbone_nationbuilder/menus.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8; -*- +################################################################################ +# +# Rattail -- Retail Software Framework +# Copyright © 2010-2023 Lance Edgar +# +# This file is part of Rattail. +# +# Rattail is free software: you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation, either version 3 of the License, or (at your option) any later +# version. +# +# Rattail is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# Rattail. If not, see . +# +################################################################################ +""" +Common menus for NationBuilder +""" + +from rattail_nationbuilder.nationbuilder.util import get_nationbuilder_url + + +def make_nationbuilder_menu(request): + url = request.route_url + + nationbuilder_menu = { + 'title': "NationBuilder", + 'type': 'menu', + 'items': [ + { + 'title': "People", + 'route': 'nationbuilder.cache.people', + 'perm': 'nationbuilder.cache.people.list', + }, + ], + } + + url = get_nationbuilder_url(request.rattail_config) + if url: + nationbuilder_menu['items'].insert( + 0, { + 'title': "Go to NationBuilder", + 'url': f'{url}/admin/', + 'target': '_blank', + }) + nationbuilder_menu['items'].insert( + 1, {'type': 'sep'}) + + return nationbuilder_menu diff --git a/tailbone_nationbuilder/provider.py b/tailbone_nationbuilder/provider.py new file mode 100644 index 0000000..3014e68 --- /dev/null +++ b/tailbone_nationbuilder/provider.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8; -*- +################################################################################ +# +# Rattail -- Retail Software Framework +# Copyright © 2010-2023 Lance Edgar +# +# This file is part of Rattail. +# +# Rattail is free software: you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation, either version 3 of the License, or (at your option) any later +# version. +# +# Rattail is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# Rattail. If not, see . +# +################################################################################ +""" +Tailbone Provider for NationBuilder Integration +""" + +from tailbone.providers import TailboneProvider + + +class TailboneNationBuilderProvider(TailboneProvider): + """ + View provider for tailbone-nationbuilder + """ + key = 'tailbone_nationbuilder' + + def make_integration_menu(self, request, **kwargs): + from tailbone_nationbuilder.menus import make_nationbuilder_menu + return make_nationbuilder_menu(request) diff --git a/tailbone_nationbuilder/templates/.keepme b/tailbone_nationbuilder/templates/.keepme new file mode 100644 index 0000000..e69de29 diff --git a/tailbone_nationbuilder/views/__init__.py b/tailbone_nationbuilder/views/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tailbone_nationbuilder/views/nationbuilder/__init__.py b/tailbone_nationbuilder/views/nationbuilder/__init__.py new file mode 100644 index 0000000..2a17fc1 --- /dev/null +++ b/tailbone_nationbuilder/views/nationbuilder/__init__.py @@ -0,0 +1,37 @@ +# -*- coding: utf-8; -*- +################################################################################ +# +# Rattail -- Retail Software Framework +# Copyright © 2010-2023 Lance Edgar +# +# This file is part of Rattail. +# +# Rattail is free software: you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation, either version 3 of the License, or (at your option) any later +# version. +# +# Rattail is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# Rattail. If not, see . +# +################################################################################ +""" +NationBuilder Views +""" + +from .master import NationBuilderMasterView + + +def defaults(config, **kwargs): + mod = lambda spec: kwargs.get(spec, spec) + + config.include(mod('tailbone_nationbuilder.views.nationbuilder.people')) + + +def includeme(config): + defaults(config) diff --git a/tailbone_nationbuilder/views/nationbuilder/master.py b/tailbone_nationbuilder/views/nationbuilder/master.py new file mode 100644 index 0000000..cfb74b8 --- /dev/null +++ b/tailbone_nationbuilder/views/nationbuilder/master.py @@ -0,0 +1,33 @@ +# -*- coding: utf-8; -*- +################################################################################ +# +# Rattail -- Retail Software Framework +# Copyright © 2010-2023 Lance Edgar +# +# This file is part of Rattail. +# +# Rattail is free software: you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation, either version 3 of the License, or (at your option) any later +# version. +# +# Rattail is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# Rattail. If not, see . +# +################################################################################ +""" +NationBuilder cache master view +""" + +from tailbone.views import MasterView + + +class NationBuilderMasterView(MasterView): + """ + Base class for NationBuilder cache master views + """ diff --git a/tailbone_nationbuilder/views/nationbuilder/people.py b/tailbone_nationbuilder/views/nationbuilder/people.py new file mode 100644 index 0000000..a14a371 --- /dev/null +++ b/tailbone_nationbuilder/views/nationbuilder/people.py @@ -0,0 +1,127 @@ +# -*- coding: utf-8; -*- +################################################################################ +# +# Rattail -- Retail Software Framework +# Copyright © 2010-2023 Lance Edgar +# +# This file is part of Rattail. +# +# Rattail is free software: you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation, either version 3 of the License, or (at your option) any later +# version. +# +# Rattail is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# Rattail. If not, see . +# +################################################################################ +""" +NationBuilder Cache Person views +""" + +from rattail_nationbuilder.db.model import NationBuilderCachePerson + +from webhelpers2.html import HTML + +from .master import NationBuilderMasterView + + +class NationBuilderCachePersonView(NationBuilderMasterView): + """ + Master view for NationBuilder Users + """ + model_class = NationBuilderCachePerson + url_prefix = '/nationbuilder/cache/people' + route_prefix = 'nationbuilder.cache.people' + has_versions = True + + labels = { + 'id': "ID", + 'external_id': "External ID", + 'primary_image_url_ssl': "Primary Image URL", + 'primary_address_address1': "Address 1", + 'primary_address_address2': "Address 2", + 'primary_address_city': "City", + 'primary_address_state': "State", + 'primary_address_zip': "Zip", + } + + grid_columns = [ + 'id', + 'external_id', + 'first_name', + 'last_name', + 'email', + 'mobile', + 'updated_at', + ] + + form_fields = [ + 'id', + 'signup_type', + 'external_id', + 'first_name', + 'middle_name', + 'last_name', + 'email', + 'email_opt_in', + 'mobile', + 'mobile_opt_in', + 'phone', + 'primary_address_address1', + 'primary_address_address2', + 'primary_address_city', + 'primary_address_state', + 'primary_address_zip', + 'primary_image_url_ssl', + 'tags', + 'note', + 'created_at', + 'updated_at', + ] + + def configure_grid(self, g): + super().configure_grid(g) + + g.set_link('external_id') + if 'external_id' in g.filters: + g.filters['external_id'].default_active = True + g.filters['external_id'].default_verb = 'contains' + + g.set_link('id') + g.set_link('first_name') + g.set_link('last_name') + g.set_link('email') + + g.set_sort_defaults('updated_at', 'desc') + + def render_tags(self, person, field): + tags = getattr(person, field) + if not tags: + return + + items = [] + for tag in self.rattail_config.parse_list(tags): + items.append(HTML.tag('li', c=[tag])) + return HTML.tag('ul', c=items) + + def configure_form(self, f): + super().configure_form(f) + + f.set_renderer('tags', self.render_tags) + + +def defaults(config, **kwargs): + base = globals() + + NationBuilderCachePersonView = kwargs.get('NationBuilderCachePersonView', base['NationBuilderCachePersonView']) + NationBuilderCachePersonView.defaults(config) + + +def includeme(config): + defaults(config) diff --git a/tasks.py b/tasks.py new file mode 100644 index 0000000..168ca4a --- /dev/null +++ b/tasks.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8; -*- +################################################################################ +# +# Rattail -- Retail Software Framework +# Copyright © 2010-2023 Lance Edgar +# +# This file is part of Rattail. +# +# Rattail is free software: you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation, either version 3 of the License, or (at your option) any later +# version. +# +# Rattail is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# Rattail. If not, see . +# +################################################################################ +""" +Tasks for tailbone-nationbuilder +""" + +import os +import shutil + +from invoke import task + + +here = os.path.abspath(os.path.dirname(__file__)) +exec(open(os.path.join(here, 'tailbone_nationbuilder', '_version.py')).read()) + + +@task +def release(c): + """ + Release a new version of tailbone-nationbuilder + """ + # rebuild local tar.gz file for distribution + if os.path.exists('tailbone_nationbuilder.egg-info'): + shutil.rmtree('tailbone_nationbuilder.egg-info') + c.run('python -m build --sdist') + + # filename of built package + filename = f'tailbone-nationbuilder-{__version__}.tar.gz' + + # upload to PyPI + c.run(f'twine upload dist/{filename}')