diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 29ef050..4a9fbf3 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -3,8 +3,6 @@ - - @@ -90,7 +88,7 @@ - + @@ -101,8 +99,8 @@ - - + + @@ -111,11 +109,34 @@ + + + + + + + + + + + + + + + + + + + + + + + - + @@ -141,8 +162,18 @@ - - + + + + + + + + + + + + @@ -152,7 +183,7 @@ - + @@ -162,27 +193,7 @@ - - - - - - - - - - - - - - - - - - - - - + @@ -1014,8 +1025,8 @@ - - + + @@ -1155,8 +1166,8 @@ - - + + @@ -1257,16 +1268,6 @@ - - - - - - - - - - @@ -1318,6 +1319,7 @@ + @@ -1337,24 +1339,6 @@ - - - - - - - - - - - - - - - - - - @@ -1370,7 +1354,7 @@ - + @@ -1378,7 +1362,7 @@ - + @@ -1391,28 +1375,10 @@ - - - - - - - - - - - - - - - - - - - + @@ -1424,10 +1390,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + diff --git a/www/pocwww/.coveragerc b/www/pocwww/.coveragerc new file mode 100644 index 0000000..d292a1e --- /dev/null +++ b/www/pocwww/.coveragerc @@ -0,0 +1,3 @@ +[run] +source = pocwww +omit = pocwww/test* diff --git a/www/pocwww/CHANGES.txt b/www/pocwww/CHANGES.txt new file mode 100644 index 0000000..14b902f --- /dev/null +++ b/www/pocwww/CHANGES.txt @@ -0,0 +1,4 @@ +0.0 +--- + +- Initial version. diff --git a/www/pocwww/MANIFEST.in b/www/pocwww/MANIFEST.in new file mode 100644 index 0000000..608cd89 --- /dev/null +++ b/www/pocwww/MANIFEST.in @@ -0,0 +1,2 @@ +include *.txt *.ini *.cfg *.rst +recursive-include pocwww *.ico *.png *.css *.gif *.jpg *.pt *.txt *.mak *.mako *.js *.html *.xml *.jinja2 diff --git a/www/pocwww/README.txt b/www/pocwww/README.txt new file mode 100644 index 0000000..ff46e9e --- /dev/null +++ b/www/pocwww/README.txt @@ -0,0 +1,29 @@ +POC Web Interface +=============================== + +Getting Started +--------------- + +- Change directory into your newly created project. + + cd POC Web Interface + +- Create a Python virtual environment. + + python3 -m venv env + +- Upgrade packaging tools. + + env/bin/pip install --upgrade pip setuptools + +- Install the project in editable mode with its testing requirements. + + env/bin/pip install -e ".[testing]" + +- Run your project's tests. + + env/bin/pytest + +- Run your project. + + env/bin/pserve development.ini diff --git a/www/pocwww/development.ini b/www/pocwww/development.ini new file mode 100644 index 0000000..6b27287 --- /dev/null +++ b/www/pocwww/development.ini @@ -0,0 +1,62 @@ +### +# app configuration +# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html +### + +[app:main] +use = egg:pocwww + +pyramid.reload_templates = true +pyramid.debug_authorization = false +pyramid.debug_notfound = false +pyramid.debug_routematch = false +pyramid.default_locale_name = en +pyramid.includes = + pyramid_debugtoolbar + +# By default, the toolbar only appears for clients from IP addresses +# '127.0.0.1' and '::1'. +# debugtoolbar.hosts = 127.0.0.1 ::1 + +mongo_uri = mongodb://localhost:27017/poc + + +### +# wsgi server configuration +### + +[server:main] +use = egg:waitress#main +listen = *:6543 + +### +# logging configuration +# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html +### + +[loggers] +keys = root, pocwww + +[handlers] +keys = console + +[formatters] +keys = generic + +[logger_root] +level = INFO +handlers = console + +[logger_pocwww] +level = DEBUG +handlers = +qualname = pocwww + +[handler_console] +class = StreamHandler +args = (sys.stderr,) +level = NOTSET +formatter = generic + +[formatter_generic] +format = %(asctime)s %(levelname)-5.5s [%(name)s:%(lineno)s][%(threadName)s] %(message)s diff --git a/www/pocwww/pocwww/__init__.py b/www/pocwww/pocwww/__init__.py new file mode 100644 index 0000000..1ca1f98 --- /dev/null +++ b/www/pocwww/pocwww/__init__.py @@ -0,0 +1,38 @@ +from pyramid.config import Configurator + +try: + # for python 2 + from urlparse import urlparse +except ImportError: + # for python 3 + from urllib.parse import urlparse + +from pymongo import MongoClient + + +def main(global_config, **settings): + """ This function returns a Pyramid WSGI application. + """ + config = Configurator(settings=settings) + config.include('pyramid_jinja2') + + db_url = urlparse(settings['mongo_uri']) + config.registry.db = MongoClient( + host=db_url.hostname, + port=db_url.port, + ) + + def add_db(request): + db = config.registry.db[db_url.path[1:]] + if db_url.username and db_url.password: + db.authenticate(db_url.username, db_url.password) + return db + + config.add_request_method(add_db, 'db', reify=True) + config.add_static_view('static', 'static', cache_max_age=3600) + config.add_route('home', '/') + config.add_route('cards_page', '/cards/{page_num}') + config.add_route('cards', '/cards') + config.add_route('card_single', "/card/view/{stroke_number}") + config.scan() + return config.make_wsgi_app() diff --git a/www/pocwww/pocwww/static/pyramid-16x16.png b/www/pocwww/pocwww/static/pyramid-16x16.png new file mode 100644 index 0000000..9792031 Binary files /dev/null and b/www/pocwww/pocwww/static/pyramid-16x16.png differ diff --git a/www/pocwww/pocwww/static/pyramid.png b/www/pocwww/pocwww/static/pyramid.png new file mode 100644 index 0000000..4ab837b Binary files /dev/null and b/www/pocwww/pocwww/static/pyramid.png differ diff --git a/www/pocwww/pocwww/static/theme.css b/www/pocwww/pocwww/static/theme.css new file mode 100644 index 0000000..8e97fc7 --- /dev/null +++ b/www/pocwww/pocwww/static/theme.css @@ -0,0 +1,121 @@ +/*@import url(//fonts.googleapis.com/css?family=Open+Sans:300,400,600,700); +body { + font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; + font-weight: 300; + color: #ffffff; + background: #bc2131; +} +h1, +h2, +h3, +h4, +h5, +h6 { + font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; + font-weight: 300; +}*/ +/* + * Base structure + */ + +/* Move down content because we have a fixed navbar that is 50px tall */ +body { + padding-top: 50px; +} + + +/* + * Global add-ons + */ + +.sub-header { + padding-bottom: 10px; + border-bottom: 1px solid #eee; +} + +/* + * Top navigation + * Hide default border to remove 1px line. + */ +.navbar-fixed-top { + border: 0; +} + +/* + * Sidebar + */ + +/* Hide for mobile, show later */ +.sidebar { + display: none; +} +@media (min-width: 768px) { + .sidebar { + position: fixed; + top: 51px; + bottom: 0; + left: 0; + z-index: 1000; + display: block; + padding: 20px; + overflow-x: hidden; + overflow-y: auto; /* Scrollable contents if viewport is shorter than content. */ + background-color: #f5f5f5; + border-right: 1px solid #eee; + } +} + +/* Sidebar navigation */ +.nav-sidebar { + margin-right: -21px; /* 20px padding + 1px border */ + margin-bottom: 20px; + margin-left: -20px; +} +.nav-sidebar > li > a { + padding-right: 20px; + padding-left: 20px; +} +.nav-sidebar > .active > a, +.nav-sidebar > .active > a:hover, +.nav-sidebar > .active > a:focus { + color: #fff; + background-color: #428bca; +} + + +/* + * Main content + */ + +.main { + padding: 20px; +} +@media (min-width: 768px) { + .main { + padding-right: 40px; + padding-left: 40px; + } +} +.main .page-header { + margin-top: 0; +} + + +/* + * Placeholder dashboard ideas + */ + +.placeholders { + margin-bottom: 30px; + text-align: center; +} +.placeholders h4 { + margin-bottom: 0; +} +.placeholder { + margin-bottom: 20px; +} +.placeholder img { + display: inline-block; + border-radius: 50%; +} diff --git a/www/pocwww/pocwww/templates/cardlist.jinja2 b/www/pocwww/pocwww/templates/cardlist.jinja2 new file mode 100644 index 0000000..ca11d1b --- /dev/null +++ b/www/pocwww/pocwww/templates/cardlist.jinja2 @@ -0,0 +1,10 @@ +{% extends "layout.jinja2" %} + +{% block content %} +
+

Card Data Page {{page_num}} / {{total_pages}}

+ {% for card in cards %} +

{{card.timestamp}}

+ {% endfor %} +
+{% endblock content %} diff --git a/www/pocwww/pocwww/templates/cardsingle.jinja2 b/www/pocwww/pocwww/templates/cardsingle.jinja2 new file mode 100644 index 0000000..f0aaf40 --- /dev/null +++ b/www/pocwww/pocwww/templates/cardsingle.jinja2 @@ -0,0 +1,11 @@ +{% extends "layout.jinja2" %} + +{% block content %} +
+
{{card.timestamp}}
+
{{card.surface_position}}
+
{{card.surface_load}}
+
{{card.downhole_position}}
+
{{card.downhole_load}}
+
+{% endblock content %} diff --git a/www/pocwww/pocwww/templates/layout.jinja2 b/www/pocwww/pocwww/templates/layout.jinja2 new file mode 100644 index 0000000..2963f60 --- /dev/null +++ b/www/pocwww/pocwww/templates/layout.jinja2 @@ -0,0 +1,86 @@ + + + + + + + + + + + + Henry POC + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ {% block content %} +

No content

+ {% endblock content %} +
+
+
+ + + + + + + + diff --git a/www/pocwww/pocwww/templates/mytemplate.jinja2 b/www/pocwww/pocwww/templates/mytemplate.jinja2 new file mode 100644 index 0000000..1bd9fd1 --- /dev/null +++ b/www/pocwww/pocwww/templates/mytemplate.jinja2 @@ -0,0 +1,8 @@ +{% extends "layout.jinja2" %} + +{% block content %} +
+

Pyramid Starter project

+

Welcome to POC Web Interface, a Pyramid application generated by
Cookiecutter.

+
+{% endblock content %} diff --git a/www/pocwww/pocwww/tests.py b/www/pocwww/pocwww/tests.py new file mode 100644 index 0000000..39c284a --- /dev/null +++ b/www/pocwww/pocwww/tests.py @@ -0,0 +1,29 @@ +import unittest + +from pyramid import testing + + +class ViewTests(unittest.TestCase): + def setUp(self): + self.config = testing.setUp() + + def tearDown(self): + testing.tearDown() + + def test_my_view(self): + from .views import my_view + request = testing.DummyRequest() + info = my_view(request) + self.assertEqual(info['project'], 'POC Web Interface') + + +class FunctionalTests(unittest.TestCase): + def setUp(self): + from pocwww import main + app = main({}) + from webtest import TestApp + self.testapp = TestApp(app) + + def test_root(self): + res = self.testapp.get('/', status=200) + self.assertTrue(b'Pyramid' in res.body) diff --git a/www/pocwww/pocwww/views.py b/www/pocwww/pocwww/views.py new file mode 100644 index 0000000..0952882 --- /dev/null +++ b/www/pocwww/pocwww/views.py @@ -0,0 +1,39 @@ +from pyramid.view import view_config + +from math import ceil + + +@view_config(route_name='home', renderer='templates/mytemplate.jinja2') +def my_view(request): + return {'project': 'POC Web Interface'} + + +def card_page(request): + page_num = 1 + try: + page_num = int(request.matchdict['page_num']) + except KeyError: + pass + + num_per_page = 100 + num_cards = request.db['cards'].count() + pages = ceil(num_cards / num_per_page) + + cards = request.db['cards'].find().sort("timestamp", -1).skip(num_per_page * (page_num - 1)).limit(num_per_page) + return {'cards': list(cards), 'page_num': page_num, 'total_pages': pages} + + +@view_config(route_name='cards', renderer='templates/cardlist.jinja2') +def cards(request): + return card_page(request) + + +@view_config(route_name='cards_page', renderer='templates/cardlist.jinja2') +def cards_page(request): + return card_page(request) + + +@view_config(route_name='card_single', renderer='templates/cardsingle.jinja2') +def card_single(request): + card = list(request.db['cards'].find({"strokeNumber": int(request.matchdict['stroke_number'])})) + return {"card": card[0]} diff --git a/www/pocwww/production.ini b/www/pocwww/production.ini new file mode 100644 index 0000000..ee0a476 --- /dev/null +++ b/www/pocwww/production.ini @@ -0,0 +1,53 @@ +### +# app configuration +# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html +### + +[app:main] +use = egg:pocwww + +pyramid.reload_templates = false +pyramid.debug_authorization = false +pyramid.debug_notfound = false +pyramid.debug_routematch = false +pyramid.default_locale_name = en + +### +# wsgi server configuration +### + +[server:main] +use = egg:waitress#main +listen = *:6543 + +### +# logging configuration +# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html +### + +[loggers] +keys = root, pocwww + +[handlers] +keys = console + +[formatters] +keys = generic + +[logger_root] +level = WARN +handlers = console + +[logger_pocwww] +level = WARN +handlers = +qualname = pocwww + +[handler_console] +class = StreamHandler +args = (sys.stderr,) +level = NOTSET +formatter = generic + +[formatter_generic] +format = %(asctime)s %(levelname)-5.5s [%(name)s:%(lineno)s][%(threadName)s] %(message)s diff --git a/www/pocwww/pytest.ini b/www/pocwww/pytest.ini new file mode 100644 index 0000000..1bdc32f --- /dev/null +++ b/www/pocwww/pytest.ini @@ -0,0 +1,3 @@ +[pytest] +testpaths = pocwww +python_files = *.py diff --git a/www/pocwww/setup.py b/www/pocwww/setup.py new file mode 100644 index 0000000..45f15df --- /dev/null +++ b/www/pocwww/setup.py @@ -0,0 +1,51 @@ +import os + +from setuptools import setup, find_packages + +here = os.path.abspath(os.path.dirname(__file__)) +with open(os.path.join(here, 'README.txt')) as f: + README = f.read() +with open(os.path.join(here, 'CHANGES.txt')) as f: + CHANGES = f.read() + +requires = [ + 'pyramid', + 'pyramid_jinja2', + 'pyramid_debugtoolbar', + 'waitress', +] + +tests_require = [ + 'WebTest >= 1.3.1', # py3 compat + 'pytest', + 'pytest-cov', +] + +setup( + name='pocwww', + version='0.0', + description='POC Web Interface', + long_description=README + '\n\n' + CHANGES, + classifiers=[ + 'Programming Language :: Python', + 'Framework :: Pyramid', + 'Topic :: Internet :: WWW/HTTP', + 'Topic :: Internet :: WWW/HTTP :: WSGI :: Application', + ], + author='', + author_email='', + url='', + keywords='web pyramid pylons', + packages=find_packages(), + include_package_data=True, + zip_safe=False, + extras_require={ + 'testing': tests_require, + }, + install_requires=requires, + entry_points={ + 'paste.app_factory': [ + 'main = pocwww:main', + ], + }, +)