|
|
|
@ -9,11 +9,10 @@ from sqlalchemy.sql.expression import func |
|
|
|
|
|
|
|
|
|
from asl_articles import app, db |
|
|
|
|
from asl_articles.models import Article, Author, ArticleAuthor, Scenario, ArticleScenario, ArticleImage |
|
|
|
|
from asl_articles.models import Publication |
|
|
|
|
from asl_articles.authors import do_get_authors |
|
|
|
|
from asl_articles.scenarios import do_get_scenarios |
|
|
|
|
from asl_articles.tags import do_get_tags |
|
|
|
|
from asl_articles.authors import get_author_vals |
|
|
|
|
from asl_articles.scenarios import get_scenario_vals |
|
|
|
|
import asl_articles.publications |
|
|
|
|
import asl_articles.publishers |
|
|
|
|
from asl_articles import search |
|
|
|
|
from asl_articles.utils import get_request_args, clean_request_args, clean_tags, encode_tags, decode_tags, \ |
|
|
|
|
apply_attrs, make_ok_response |
|
|
|
@ -34,9 +33,10 @@ def get_article( article_id ): |
|
|
|
|
if not article: |
|
|
|
|
abort( 404 ) |
|
|
|
|
_logger.debug( "- %s", article ) |
|
|
|
|
return jsonify( get_article_vals( article ) ) |
|
|
|
|
deep = request.args.get( "deep" ) |
|
|
|
|
return jsonify( get_article_vals( article, deep ) ) |
|
|
|
|
|
|
|
|
|
def get_article_vals( article, add_type=False ): |
|
|
|
|
def get_article_vals( article, deep ): |
|
|
|
|
"""Extract public fields from an Article record.""" |
|
|
|
|
authors = sorted( article.article_authors, |
|
|
|
|
key = lambda a: a.seq_no |
|
|
|
@ -45,22 +45,28 @@ def get_article_vals( article, add_type=False ): |
|
|
|
|
key = lambda a: a.seq_no |
|
|
|
|
) |
|
|
|
|
vals = { |
|
|
|
|
"_type": "article", |
|
|
|
|
"article_id": article.article_id, |
|
|
|
|
"article_title": article.article_title, |
|
|
|
|
"article_subtitle": article.article_subtitle, |
|
|
|
|
"article_image_id": article.article_id if article.article_image else None, |
|
|
|
|
"article_authors": [ a.author_id for a in authors ], |
|
|
|
|
"article_authors": [ get_author_vals( a.parent_author ) for a in authors ], |
|
|
|
|
"article_snippet": article.article_snippet, |
|
|
|
|
"article_pageno": article.article_pageno, |
|
|
|
|
"article_url": article.article_url, |
|
|
|
|
"article_scenarios": [ s.scenario_id for s in scenarios ], |
|
|
|
|
"article_scenarios": [ get_scenario_vals( s.parent_scenario ) for s in scenarios ], |
|
|
|
|
"article_tags": decode_tags( article.article_tags ), |
|
|
|
|
"article_rating": article.article_rating, |
|
|
|
|
"pub_id": article.pub_id, |
|
|
|
|
"publ_id": article.publ_id, |
|
|
|
|
} |
|
|
|
|
if add_type: |
|
|
|
|
vals[ "type" ] = "article" |
|
|
|
|
if deep: |
|
|
|
|
vals["_parent_pub"] = asl_articles.publications.get_publication_vals( |
|
|
|
|
article.parent_pub, False, False |
|
|
|
|
) if article.parent_pub else None |
|
|
|
|
vals["_parent_publ"] = asl_articles.publishers.get_publisher_vals( |
|
|
|
|
article.parent_publ, False, False |
|
|
|
|
) if article.parent_publ else None |
|
|
|
|
return vals |
|
|
|
|
|
|
|
|
|
def get_article_sort_key( article ): |
|
|
|
@ -80,13 +86,11 @@ def create_article(): |
|
|
|
|
log = ( _logger, "Create article:" ) |
|
|
|
|
) |
|
|
|
|
warnings = [] |
|
|
|
|
updated = clean_request_args( vals, _FIELD_NAMES, warnings, _logger ) |
|
|
|
|
clean_request_args( vals, _FIELD_NAMES, warnings, _logger ) |
|
|
|
|
|
|
|
|
|
# NOTE: Tags are stored in the database using \n as a separator, so we need to encode *after* cleaning them. |
|
|
|
|
cleaned_tags = clean_tags( vals.get("article_tags"), warnings ) |
|
|
|
|
vals[ "article_tags" ] = encode_tags( cleaned_tags ) |
|
|
|
|
if cleaned_tags != vals.get( "article_tags" ): |
|
|
|
|
updated[ "article_tags" ] = decode_tags( vals["article_tags"] ) |
|
|
|
|
|
|
|
|
|
# create the new article |
|
|
|
|
vals[ "time_created" ] = datetime.datetime.now() |
|
|
|
@ -95,23 +99,16 @@ def create_article(): |
|
|
|
|
db.session.flush() |
|
|
|
|
new_article_id = article.article_id |
|
|
|
|
_set_seqno( article, article.pub_id ) |
|
|
|
|
_save_authors( article, updated ) |
|
|
|
|
_save_scenarios( article, updated ) |
|
|
|
|
_save_image( article, updated ) |
|
|
|
|
_save_authors( article ) |
|
|
|
|
_save_scenarios( article ) |
|
|
|
|
_save_image( article ) |
|
|
|
|
db.session.commit() |
|
|
|
|
_logger.debug( "- New ID: %d", new_article_id ) |
|
|
|
|
search.add_or_update_article( None, article, None ) |
|
|
|
|
|
|
|
|
|
# generate the response |
|
|
|
|
extras = { "article_id": new_article_id } |
|
|
|
|
if request.args.get( "list" ): |
|
|
|
|
extras[ "authors" ] = do_get_authors() |
|
|
|
|
extras[ "scenarios" ] = do_get_scenarios() |
|
|
|
|
extras[ "tags" ] = do_get_tags() |
|
|
|
|
if article.pub_id: |
|
|
|
|
pub = Publication.query.get( article.pub_id ) |
|
|
|
|
extras[ "_publication" ] = asl_articles.publications.get_publication_vals( pub, True ) |
|
|
|
|
return make_ok_response( updated=updated, extras=extras, warnings=warnings ) |
|
|
|
|
vals = get_article_vals( article, True ) |
|
|
|
|
return make_ok_response( record=vals, warnings=warnings ) |
|
|
|
|
|
|
|
|
|
def _set_seqno( article, pub_id ): |
|
|
|
|
"""Set an article's seq#.""" |
|
|
|
@ -123,7 +120,7 @@ def _set_seqno( article, pub_id ): |
|
|
|
|
else: |
|
|
|
|
article.article_seqno = None |
|
|
|
|
|
|
|
|
|
def _save_authors( article, updated_fields ): |
|
|
|
|
def _save_authors( article ): |
|
|
|
|
"""Save the article's authors.""" |
|
|
|
|
|
|
|
|
|
# delete the existing article-author rows |
|
|
|
@ -133,8 +130,6 @@ def _save_authors( article, updated_fields ): |
|
|
|
|
|
|
|
|
|
# add the article-author rows |
|
|
|
|
authors = request.json.get( "article_authors", [] ) |
|
|
|
|
author_ids = [] |
|
|
|
|
new_authors = False |
|
|
|
|
for seq_no,author in enumerate( authors ): |
|
|
|
|
if isinstance( author, int ): |
|
|
|
|
# this is an existing author |
|
|
|
@ -147,19 +142,12 @@ def _save_authors( article, updated_fields ): |
|
|
|
|
db.session.add( author ) |
|
|
|
|
db.session.flush() |
|
|
|
|
author_id = author.author_id |
|
|
|
|
new_authors = True |
|
|
|
|
_logger.debug( "Created new author \"%s\": id=%d", author, author_id ) |
|
|
|
|
db.session.add( |
|
|
|
|
ArticleAuthor( seq_no=seq_no, article_id=article.article_id, author_id=author_id ) |
|
|
|
|
) |
|
|
|
|
author_ids.append( author_id ) |
|
|
|
|
|
|
|
|
|
# check if we created any new authors |
|
|
|
|
if new_authors: |
|
|
|
|
# yup - let the caller know about them |
|
|
|
|
updated_fields[ "article_authors"] = author_ids |
|
|
|
|
|
|
|
|
|
def _save_scenarios( article, updated_fields ): |
|
|
|
|
def _save_scenarios( article ): |
|
|
|
|
"""Save the article's scenarios.""" |
|
|
|
|
|
|
|
|
|
# delete the existing article-scenario rows |
|
|
|
@ -169,8 +157,6 @@ def _save_scenarios( article, updated_fields ): |
|
|
|
|
|
|
|
|
|
# add the article-scenario rows |
|
|
|
|
scenarios = request.json.get( "article_scenarios", [] ) |
|
|
|
|
scenario_ids = [] |
|
|
|
|
new_scenarios = False |
|
|
|
|
for seq_no,scenario in enumerate( scenarios ): |
|
|
|
|
if isinstance( scenario, int ): |
|
|
|
|
# this is an existing scenario |
|
|
|
@ -183,19 +169,12 @@ def _save_scenarios( article, updated_fields ): |
|
|
|
|
db.session.add( new_scenario ) |
|
|
|
|
db.session.flush() |
|
|
|
|
scenario_id = new_scenario.scenario_id |
|
|
|
|
new_scenarios = True |
|
|
|
|
_logger.debug( "Created new scenario \"%s [%s]\": id=%d", scenario[1], scenario[0], scenario_id ) |
|
|
|
|
db.session.add( |
|
|
|
|
ArticleScenario( seq_no=seq_no, article_id=article.article_id, scenario_id=scenario_id ) |
|
|
|
|
) |
|
|
|
|
scenario_ids.append( scenario_id ) |
|
|
|
|
|
|
|
|
|
# check if we created any new scenarios |
|
|
|
|
if new_scenarios: |
|
|
|
|
# yup - let the caller know about them |
|
|
|
|
updated_fields[ "article_scenarios"] = scenario_ids |
|
|
|
|
|
|
|
|
|
def _save_image( article, updated ): |
|
|
|
|
def _save_image( article ): |
|
|
|
|
"""Save the article's image.""" |
|
|
|
|
|
|
|
|
|
# check if a new image was provided |
|
|
|
@ -207,7 +186,7 @@ def _save_image( article, updated ): |
|
|
|
|
ArticleImage.query.filter( ArticleImage.article_id == article.article_id ).delete() |
|
|
|
|
if image_data == "{remove}": |
|
|
|
|
# NOTE: The front-end sends this if it wants the article to have no image. |
|
|
|
|
updated[ "article_image_id" ] = None |
|
|
|
|
article.article_image_id = None |
|
|
|
|
return |
|
|
|
|
|
|
|
|
|
# add the new image to the database |
|
|
|
@ -217,7 +196,6 @@ def _save_image( article, updated ): |
|
|
|
|
db.session.add( img ) |
|
|
|
|
db.session.flush() |
|
|
|
|
_logger.debug( "Created new image: %s, #bytes=%d", fname, len(image_data) ) |
|
|
|
|
updated[ "article_image_id" ] = article.article_id |
|
|
|
|
|
|
|
|
|
# --------------------------------------------------------------------- |
|
|
|
|
|
|
|
|
@ -231,44 +209,29 @@ def update_article(): |
|
|
|
|
log = ( _logger, "Update article: id={}".format( article_id ) ) |
|
|
|
|
) |
|
|
|
|
warnings = [] |
|
|
|
|
updated = clean_request_args( vals, _FIELD_NAMES, warnings, _logger ) |
|
|
|
|
clean_request_args( vals, _FIELD_NAMES, warnings, _logger ) |
|
|
|
|
|
|
|
|
|
# NOTE: Tags are stored in the database using \n as a separator, so we need to encode *after* cleaning them. |
|
|
|
|
cleaned_tags = clean_tags( vals.get("article_tags"), warnings ) |
|
|
|
|
vals[ "article_tags" ] = encode_tags( cleaned_tags ) |
|
|
|
|
if cleaned_tags != vals.get( "article_tags" ): |
|
|
|
|
updated[ "article_tags" ] = decode_tags( vals["article_tags"] ) |
|
|
|
|
|
|
|
|
|
# update the article |
|
|
|
|
article = Article.query.get( article_id ) |
|
|
|
|
if not article: |
|
|
|
|
abort( 404 ) |
|
|
|
|
orig_pub = Publication.query.get( article.pub_id ) if article.pub_id else None |
|
|
|
|
if vals["pub_id"] != article.pub_id: |
|
|
|
|
_set_seqno( article, vals["pub_id"] ) |
|
|
|
|
vals[ "time_updated" ] = datetime.datetime.now() |
|
|
|
|
apply_attrs( article, vals ) |
|
|
|
|
_save_authors( article, updated ) |
|
|
|
|
_save_scenarios( article, updated ) |
|
|
|
|
_save_image( article, updated ) |
|
|
|
|
_save_authors( article ) |
|
|
|
|
_save_scenarios( article ) |
|
|
|
|
_save_image( article ) |
|
|
|
|
db.session.commit() |
|
|
|
|
search.add_or_update_article( None, article, None ) |
|
|
|
|
|
|
|
|
|
# generate the response |
|
|
|
|
extras = {} |
|
|
|
|
if request.args.get( "list" ): |
|
|
|
|
extras[ "authors" ] = do_get_authors() |
|
|
|
|
extras[ "scenarios" ] = do_get_scenarios() |
|
|
|
|
extras[ "tags" ] = do_get_tags() |
|
|
|
|
pubs = [] |
|
|
|
|
if orig_pub and orig_pub.pub_id != article.pub_id: |
|
|
|
|
pubs.append( asl_articles.publications.get_publication_vals( orig_pub, True ) ) |
|
|
|
|
if article.pub_id: |
|
|
|
|
pub = Publication.query.get( article.pub_id ) |
|
|
|
|
pubs.append( asl_articles.publications.get_publication_vals( pub, True ) ) |
|
|
|
|
if pubs: |
|
|
|
|
extras[ "_publications" ] = pubs |
|
|
|
|
return make_ok_response( updated=updated, extras=extras, warnings=warnings ) |
|
|
|
|
vals = get_article_vals( article, True ) |
|
|
|
|
return make_ok_response( record=vals, warnings=warnings ) |
|
|
|
|
|
|
|
|
|
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
|
|
|
|
|
|
|
|
@ -311,11 +274,4 @@ def delete_article( article_id ): |
|
|
|
|
search.delete_articles( [ article ] ) |
|
|
|
|
|
|
|
|
|
# generate the response |
|
|
|
|
extras = {} |
|
|
|
|
if request.args.get( "list" ): |
|
|
|
|
extras[ "authors" ] = do_get_authors() |
|
|
|
|
extras[ "tags" ] = do_get_tags() |
|
|
|
|
if article.pub_id: |
|
|
|
|
pub = Publication.query.get( article.pub_id ) |
|
|
|
|
extras[ "_publication" ] = asl_articles.publications.get_publication_vals( pub, True ) |
|
|
|
|
return make_ok_response( extras=extras ) |
|
|
|
|
return make_ok_response() |
|
|
|
|