Rename journal to pages to be consistent with new terminology.
Simplify pip requirements into a single file.
This commit is contained in:
parent
38749c7abc
commit
accb9536c9
|
@ -5,7 +5,7 @@ RUN wget https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.
|
||||||
&& dpkg -i dumb-init_*.deb
|
&& dpkg -i dumb-init_*.deb
|
||||||
COPY requirements* /app/rookeries/
|
COPY requirements* /app/rookeries/
|
||||||
RUN apt-get install libpq-dev
|
RUN apt-get install libpq-dev
|
||||||
RUN pip install --requirement /app/rookeries/requirements-dev.txt --quiet \
|
RUN pip install --requirement /app/rookeries/requirements.txt --quiet \
|
||||||
&& pip install --quiet uwsgi
|
&& pip install --quiet uwsgi
|
||||||
|
|
||||||
COPY . /app/rookeries/
|
COPY . /app/rookeries/
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
# Requirements for development.
|
|
||||||
|
|
||||||
-r requirements.txt
|
|
||||||
|
|
||||||
# Documentation
|
|
||||||
Sphinx>=1.4.8
|
|
||||||
releases>=1.2.1
|
|
||||||
recommonmark>=0.4.0
|
|
||||||
|
|
||||||
# Testing
|
|
||||||
coverage>=4.2
|
|
||||||
flake8>=3.0.4
|
|
||||||
|
|
||||||
pytest>=3.0.3
|
|
||||||
pytest-cov>=2.4.0
|
|
||||||
pytest-mock>=1.2
|
|
||||||
pytest-bdd>=2.18.0
|
|
||||||
|
|
||||||
# Deployment and Automation
|
|
||||||
invoke==0.13.0
|
|
|
@ -15,3 +15,20 @@ psycopg2==2.6.2
|
||||||
# Utilities
|
# Utilities
|
||||||
arrow==0.8.0
|
arrow==0.8.0
|
||||||
requests==2.12.1
|
requests==2.12.1
|
||||||
|
|
||||||
|
# Documentation
|
||||||
|
Sphinx>=1.4.8
|
||||||
|
releases>=1.2.1
|
||||||
|
recommonmark>=0.4.0
|
||||||
|
|
||||||
|
# Testing
|
||||||
|
coverage>=4.2
|
||||||
|
flake8>=3.0.4
|
||||||
|
|
||||||
|
pytest>=3.0.3
|
||||||
|
pytest-cov>=2.4.0
|
||||||
|
pytest-mock>=1.2
|
||||||
|
pytest-bdd>=2.18.0
|
||||||
|
|
||||||
|
# Deployment and Automation
|
||||||
|
invoke==0.13.0
|
||||||
|
|
|
@ -17,7 +17,7 @@ def register_views():
|
||||||
"""Import the various views in the app."""
|
"""Import the various views in the app."""
|
||||||
rookeries_views = [
|
rookeries_views = [
|
||||||
'rookeries.views',
|
'rookeries.views',
|
||||||
'rookeries.journal.views',
|
'rookeries.pages.views',
|
||||||
'rookeries.security',
|
'rookeries.security',
|
||||||
]
|
]
|
||||||
for views_modules in rookeries_views:
|
for views_modules in rookeries_views:
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
"""
|
"""
|
||||||
Models for the journal or CMS component.
|
Models for pages.
|
||||||
|
|
||||||
:copyright: Copyright 2013-2016, Dorian Pula <dorian.pula@amber-penguin-software.ca>
|
:copyright: Copyright 2013-2016, Dorian Pula <dorian.pula@amber-penguin-software.ca>
|
||||||
:license: AGPL v3+
|
:license: AGPL v3+
|
||||||
|
@ -10,9 +10,9 @@ import sqlalchemy
|
||||||
from rookeries import database
|
from rookeries import database
|
||||||
|
|
||||||
|
|
||||||
class Journal(database.ModelBase):
|
class Page(database.ModelBase):
|
||||||
|
|
||||||
__tablename__ = 'journal'
|
__tablename__ = 'pages'
|
||||||
|
|
||||||
id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True)
|
id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True)
|
||||||
# TODO: Move out into the definition of app / container blocks.
|
# TODO: Move out into the definition of app / container blocks.
|
|
@ -13,73 +13,67 @@ import flask_jwt
|
||||||
from sqlalchemy.orm import exc as sql_error
|
from sqlalchemy.orm import exc as sql_error
|
||||||
|
|
||||||
from rookeries import database
|
from rookeries import database
|
||||||
from rookeries.journal import models
|
from rookeries.pages import models
|
||||||
|
|
||||||
from rookeries.main import rookeries_app
|
from rookeries.main import rookeries_app
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
@rookeries_app.route("/api/pages/", methods=['GET'])
|
@rookeries_app.route("/api/pages", methods=['GET'])
|
||||||
def serve_markdown_landing_page():
|
def serve_landing_page():
|
||||||
"""
|
"""
|
||||||
Serving up a landing page with Markdown content.
|
Serving up a landing page with Markdown content.
|
||||||
|
|
||||||
:request page: The name of the page to display.
|
:request page: The name of the page to display.
|
||||||
"""
|
"""
|
||||||
# TODO: Remove hardcoding of landing url
|
# TODO: Remove hardcoding of landing url
|
||||||
return serve_markdown_page("about")
|
return serve_page("about")
|
||||||
|
|
||||||
|
|
||||||
@rookeries_app.route("/api/pages/<string:page>", methods=['GET'])
|
@rookeries_app.route("/api/pages/<slug>", methods=['GET'])
|
||||||
def serve_markdown_page(page='landing'):
|
def serve_page(slug):
|
||||||
"""
|
"""
|
||||||
Serving up a page with Markdown content.
|
Serving up a page with Markdown content.
|
||||||
|
|
||||||
:request page: The name of the page to display.
|
:request page: The name of the page to display.
|
||||||
"""
|
"""
|
||||||
|
logger.info('Retrieving page "%s"', slug)
|
||||||
# TODO: Remove hardcoding of landing url
|
|
||||||
page = "about" if page == "landing" else page
|
|
||||||
logger.info('Retrieving page "%s"', page)
|
|
||||||
|
|
||||||
journal_entry = None
|
journal_entry = None
|
||||||
db_session = database.SQLAlchemy.session
|
db_session = database.SQLAlchemy.session
|
||||||
try:
|
try:
|
||||||
journal_entry = db_session.query(models.Journal).filter_by(slug=page).first()
|
journal_entry = db_session.query(models.Page).filter_by(slug=slug).first()
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
logger.error("Error retrieving '%s' page because of: %s", page, err)
|
logger.error("Error retrieving '%s' page because of: %s", slug, err)
|
||||||
flask.abort(http.HTTPStatus.INTERNAL_SERVER_ERROR)
|
flask.abort(http.HTTPStatus.INTERNAL_SERVER_ERROR)
|
||||||
|
|
||||||
if journal_entry is None:
|
if journal_entry is None:
|
||||||
logger.warn("Unable to find retrieve page: %s", page)
|
logger.warn("Unable to find retrieve page: %s", slug)
|
||||||
flask.abort(http.HTTPStatus.NOT_FOUND)
|
flask.abort(http.HTTPStatus.NOT_FOUND)
|
||||||
|
|
||||||
return flask.jsonify(journal_entry.to_json())
|
return flask.jsonify(journal_entry.to_json())
|
||||||
|
|
||||||
|
|
||||||
@flask_jwt.jwt_required
|
@flask_jwt.jwt_required
|
||||||
@rookeries_app.route("/api/pages/<string:page>", methods=['POST', 'PUT'])
|
@rookeries_app.route("/api/pages/<slug>", methods=['POST', 'PUT'])
|
||||||
def save_markdown_page(page='landing'):
|
def save_page(slug):
|
||||||
# TODO: Remove hardcoding of landing url
|
|
||||||
page = "about" if page == "landing" else page
|
|
||||||
|
|
||||||
updated_journal_entry = flask.request.json
|
updated_journal_entry = flask.request.json
|
||||||
db_session = database.SQLAlchemy.session
|
db_session = database.SQLAlchemy.session
|
||||||
journal_entry = None
|
journal_entry = None
|
||||||
try:
|
try:
|
||||||
journal_entry = db_session.query(models.Journal).filter_by(slug=page).first()
|
journal_entry = db_session.query(models.Page).filter_by(slug=slug).first()
|
||||||
except sql_error.NoResultFound:
|
except sql_error.NoResultFound:
|
||||||
journal_entry = models.Journal(
|
journal_entry = models.Page(
|
||||||
slug=page,
|
slug=slug,
|
||||||
title=updated_journal_entry['title'],
|
title=updated_journal_entry['title'],
|
||||||
content=updated_journal_entry['content'])
|
content=updated_journal_entry['content'])
|
||||||
db_session.add(journal_entry)
|
db_session.add(journal_entry)
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
logger.error("Error retrieving '%s' page because of: %s", page, err)
|
logger.error("Error retrieving '%s' page because of: %s", slug, err)
|
||||||
flask.abort(http.HTTPStatus.INTERNAL_SERVER_ERROR)
|
flask.abort(http.HTTPStatus.INTERNAL_SERVER_ERROR)
|
||||||
else:
|
else:
|
||||||
journal_entry.slug = page
|
journal_entry.slug = slug
|
||||||
journal_entry.title = updated_journal_entry['title']
|
journal_entry.title = updated_journal_entry['title']
|
||||||
journal_entry.content = updated_journal_entry['content']
|
journal_entry.content = updated_journal_entry['content']
|
||||||
|
|
|
@ -9,7 +9,7 @@ import pathlib
|
||||||
|
|
||||||
from sqlalchemy import orm
|
from sqlalchemy import orm
|
||||||
|
|
||||||
from rookeries.journal import models as journal_models
|
from rookeries.pages import models as journal_models
|
||||||
|
|
||||||
|
|
||||||
def create_sample_page(page_id, title, content_file):
|
def create_sample_page(page_id, title, content_file):
|
||||||
|
@ -28,7 +28,7 @@ def sample_page_collection():
|
||||||
|
|
||||||
|
|
||||||
def populate_database(db_engine):
|
def populate_database(db_engine):
|
||||||
docs = [journal_models.Journal(**doc) for doc in sample_page_collection()]
|
docs = [journal_models.Page(**doc) for doc in sample_page_collection()]
|
||||||
session = orm.sessionmaker(bind=db_engine)()
|
session = orm.sessionmaker(bind=db_engine)()
|
||||||
session.add_all(docs)
|
session.add_all(docs)
|
||||||
session.commit()
|
session.commit()
|
||||||
|
|
|
@ -26,7 +26,7 @@ def expected_json_content():
|
||||||
return content
|
return content
|
||||||
|
|
||||||
|
|
||||||
def test_serve_journal_entry_view_returns_journal_entry_as_json(flask_test_app, expected_json_content):
|
def test_serve_page_returns_journal_entry_as_json(flask_test_app, expected_json_content):
|
||||||
expected_info = {
|
expected_info = {
|
||||||
'slug': 'about',
|
'slug': 'about',
|
||||||
'title': 'About Rookeries',
|
'title': 'About Rookeries',
|
||||||
|
@ -39,20 +39,20 @@ def test_serve_journal_entry_view_returns_journal_entry_as_json(flask_test_app,
|
||||||
assert utils.convert_response_into_json(actual) == expected_info
|
assert utils.convert_response_into_json(actual) == expected_info
|
||||||
|
|
||||||
|
|
||||||
def test_serve_journal_entry_view_serving_landing_doc_returns_about_page(flask_test_app, expected_json_content):
|
def test_serve_landing_page_view_returns_about_page(flask_test_app, expected_json_content):
|
||||||
expected_info = {
|
expected_info = {
|
||||||
'slug': 'about',
|
'slug': 'about',
|
||||||
'title': 'About Rookeries',
|
'title': 'About Rookeries',
|
||||||
'content': expected_json_content,
|
'content': expected_json_content,
|
||||||
}
|
}
|
||||||
|
|
||||||
actual = flask_test_app.get('/api/pages/landing')
|
actual = flask_test_app.get('/api/pages')
|
||||||
|
|
||||||
assert actual.status_code == http.HTTPStatus.OK
|
assert actual.status_code == http.HTTPStatus.OK
|
||||||
assert utils.convert_response_into_json(actual) == expected_info
|
assert utils.convert_response_into_json(actual) == expected_info
|
||||||
|
|
||||||
|
|
||||||
def test_serve_journal_entry_view_returns_404_when_no_content_found(flask_test_app):
|
def test_serve_page_view_returns_404_when_no_content_found(flask_test_app):
|
||||||
expect_json = {
|
expect_json = {
|
||||||
'error': {
|
'error': {
|
||||||
'code': 404,
|
'code': 404,
|
|
@ -57,8 +57,8 @@ export class JournalMarkdownView extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
displayContent: this.props.article || "Please wait while we load this journal entry.",
|
displayContent: this.props.article || "Please wait while we load this pages entry.",
|
||||||
originalContent: this.props.article || "Please wait while we load this journal entry.",
|
originalContent: this.props.article || "Please wait while we load this pages entry.",
|
||||||
editorPaneState: EditorPaneState.hidden
|
editorPaneState: EditorPaneState.hidden
|
||||||
};
|
};
|
||||||
this.handleSaveContent = this.handleSaveContent.bind(this);
|
this.handleSaveContent = this.handleSaveContent.bind(this);
|
||||||
|
|
Loading…
Reference in New Issue