Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Second funnel app #254

Merged
merged 30 commits into from
Sep 20, 2018
Merged

Second funnel app #254

merged 30 commits into from
Sep 20, 2018

Conversation

iambibhas
Copy link
Contributor

@iambibhas iambibhas commented Jul 11, 2018

First part of completing #230.

@iambibhas iambibhas changed the title Second funnel app [WIP] Second funnel app Jul 31, 2018
@iambibhas iambibhas requested a review from jace July 31, 2018 08:42
mail.init_app(app)

lastuser.init_app(funnelapp)
lastuser.init_app(app)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jace these lines above seems wrong. specially the db.app = <> part. How to handle these?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

db.app assignment is only required if there's a database operation outside a request context, to let the db object know which app to operate on. This can happen during init, if we're loading from db, or doing a background job. Workaround: enclose the database operation in with app.app_context(): (we've previously used with app.test_request_context():, a somewhat heavier operation since it also constructs a dummy request).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok. And what about the others? Double assigning migrate and calling init_app() multiple times on db, mail and lastuser doesn't seem right.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mail and Lastuser are fine. Migrate doesn't need to be on Funnelapp.

@iambibhas iambibhas changed the base branch from master to hasgeekapp August 14, 2018 07:36
@@ -12,6 +12,7 @@
from ._version import __version__


funnelapp = Flask(__name__, instance_relative_config=True)
app = Flask(__name__, instance_relative_config=True)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Always put app first and funnelapp second, since funnelapp will be removed eventually.

db.init_app(app)

db.app = funnelapp
db.app = app
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove both these lines.

db.app = app

migrate = Migrate(funnelapp, db)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this. Migrate only needs to be on the main app.

mail.init_app(app)

lastuser.init_app(funnelapp)
lastuser.init_app(app)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mail and Lastuser are fine. Migrate doesn't need to be on Funnelapp.

funnel/util.py Outdated
@@ -4,8 +4,8 @@
from urlparse import urlparse
import qrcode
import qrcode.image.svg
from flask import current_app
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Place this import above qrcode since it's a more foundational library.

@@ -379,7 +388,8 @@ def proposal_prev(profile, space, proposal):
return redirect(space.url_for())


@app.route('/<space>/<proposal>/move', methods=['POST',], subdomain='<profile>')
@app.route('/<profile>/<space>/<proposal>/move', methods=['POST',])
@funnelapp.route('/<space>/<proposal>/move', methods=['POST',], subdomain='<profile>')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

methods=['POST'] in both lines (for style consistency).

@funnelapp.route('/<space>/users/new', defaults={'group': None}, endpoint='usergroup_new',
methods=['GET', 'POST'], subdomain='<profile>')
@app.route('/<profile>/<space>/users/<group>/edit', methods=['GET', 'POST'])
@funnelapp.route('/<space>/users/<group>/edit', methods=['GET', 'POST'], subdomain='<profile>')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Order them app, app, funnelapp, funnelapp.

manage.py Outdated
@@ -2,7 +2,7 @@

from coaster.manage import init_manager

from funnel import app, models
from funnel import funnelapp, app, models
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

funnelapp is not required here.

rqfunnelinit.py Outdated
@@ -0,0 +1,14 @@
from urlparse import urlparse
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file is not required. The same RQ backend will power both apps.

runserver.py Outdated
@@ -6,5 +6,5 @@
try:
port = int(sys.argv[1])
except (IndexError, ValueError):
port = 3000
port = 3001
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Keep the port here, change it for Funnel.

Copy link
Member

@jace jace left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Partial review, will continue later today.



def import_tickets(ticket_client_id):
with app.test_request_context():
with current_app.test_request_context():
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change this back to app. If you need a test_request_context, then current_app will be None, so this construct will fail. Do this everywhere that test_request_context or app_context is used.

spaces_all = ProposalSpace.fetch_sorted().filter(
ProposalSpace.profile == self, ProposalSpace.parent_space == None
).all()
return spaces_all
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be a relationship. Why is it a property?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure why it was defined as a property, I just organized it. Anyway, now when I try to define it as a relationship, there is a circular import issue. ProposalSpace model requires Profile for a relationship and vice versa.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can put the name in quotes. SQLAlchemy will do an eval using the model namespace to pick the correct model. That means any valid Python expression will work inside the quotes.

Copy link
Member

@jace jace left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few more cosmetic changes.

from ..models import Profile, ProposalSpace, Proposal
from .space import space_data


def index_jsonify(data):
spaces_data = list()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's wrong with spaces_data = []?

space_dict = dict(space.current_access())
if space_dict:
spaces_data.append(space_dict)
return jsonify(spaces=spaces_data)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This whole thing could be:

    return jsonify(spaces=[d for d in [dict(s.current_access()) for s in data['spaces']] if d])

def index():
g.profile = None
g.permissions = []
spaces = ProposalSpace.fetch_sorted().filter(ProposalSpace.profile != None).all()
return render_template('index.html.jinja2', spaces=spaces)
return dict(spaces=spaces)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return {'spaces': spaces}

g.profile = None
g.permissions = []
spaces = ProposalSpace.fetch_sorted().filter(ProposalSpace.profile != None).all()
return dict(spaces=spaces)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As above.

@render_with({'text/html': 'funnelindex.html.jinja2', 'application/json': index_jsonify})
def funnelindex():
g.profile = None
g.permissions = []
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has to be current_auth.permissions now. See Coaster's load_models for how to set it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

g.permissions is used in a lot of places on this repo. I'm not completely sure about the effects of change to current_auth.permissions. can we do this part of another PR? or maybe the next PR.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

current_auth.permissions is guaranteed to be an InspectableSet. g.permissions only promises to support the in operator. It could be a list, tuple or set. This difference is crucial for the transition.

spaces_data.append(space_dict)
return jsonify(
profile=dict(data['profile'].current_access()),
spaces=spaces_data)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Simplify this as above.

@@ -38,7 +38,8 @@ def space_data(space):


# Test endpoint
@app.route('/form', methods=['GET', 'POST'], subdomain='<profile>')
@app.route('/<profile>/form', methods=['GET', 'POST'])
@funnelapp.route('/form', methods=['GET', 'POST'], subdomain='<profile>')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this endpoint. We added it to test Baseframe's form generator. It's not required anymore.

g.permissions = []
spaces = ProposalSpace.fetch_sorted().filter(ProposalSpace.profile != None).all()
# XXX: Can we just return index() ?
return {'spaces': [d for d in [dict(s.current_access()) for s in spaces] if d]}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jace ^

parent_spaces_test = db.relationship('ProposalSpace',
lazy='dynamic',
primaryjoin="and_(ProposalSpace.profile_id == Profile.id, ProposalSpace.parent_space_id == None)"
)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jace need some help with this one, parent_spaces below is returned by the fetch_sorted() classmethod which, along with sorting the results, does a state filter, which I can't do where without importing ProposalSpace, which I can do as I removed the circular import issue from space.py, but want to check if it's possible without importing ProposalSpace

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That entire function could be a SQL expression, which means it could be a relationship.

Copy link
Contributor Author

@iambibhas iambibhas Sep 18, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's complicated in the SQL expression is the custom sorting that fetch_sorted() does. Closest event is first, then second third are future events and then forth and so on are older events etc like that. can be done using sqlalchemy's hybrid_property I think.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Leave this aside for now. I'll look at rewriting it as a relationship later.

@render_with({'text/html': 'funnelindex.html.jinja2'}, json=True)
def funnelindex():
g.profile = None
g.permissions = []
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jace g.permissions is widely used in this repo. I'm not too sure about the changes required to change them back to current_auth.permissions. Can we handle this in a separate PR?

g.permissions = []
spaces = ProposalSpace.fetch_sorted().filter(ProposalSpace.profile != None).all()
# XXX: Can we just return index() ?
return {'spaces': spaces}
Copy link
Contributor Author

@iambibhas iambibhas Sep 17, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jace can we just return index()?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You'll get the output of render_with, unless you pass it _render=False. https://coaster.readthedocs.io/en/latest/views/decorators.html#coaster.views.decorators.render_with

@iambibhas iambibhas merged commit 8ffd7f4 into hasgeekapp Sep 20, 2018
@iambibhas iambibhas deleted the url-rewrite branch September 20, 2018 02:11
iambibhas pushed a commit that referenced this pull request Sep 20, 2018
* replaced app with funnelapp and created new app instance

* added route for new app to all views

* replaced runtime use of app iwth current_app

* renamed runfunnelserver.py to runfunnel.py

* separated rqinit file for both applications

* added app specific configuration

* added comment for app specific config

* fixed app order, removed unnecessary views from funnelapp and more fixes

* renamed jsonify function name

* moved model import inside function to avoid circular import

* misc fixes

* moving lastuser confix to app specific config files

* added LASTUSER_COOKIE_DOMAIN to app specific config

* fixed mui css issue with funnelapp

* funnelindex page update with new UI

* downloading CSV file instead of showing on tab

* using content type text/csv

* fixed placement of few hr tags

* Call embedIframe only when preview video link is present.

* misc fixes

* reverted to index_jsonify function

* removed unused function

* using parent_spaces_test relationship to test

* removed parent_spaces_test

* Sync funnelindex with index. Change heading to bold on proposal page.

* removed doubt
iambibhas pushed a commit that referenced this pull request Sep 29, 2018
* Add static pages.

* Second funnel app (#254)

* replaced app with funnelapp and created new app instance

* added route for new app to all views

* replaced runtime use of app iwth current_app

* renamed runfunnelserver.py to runfunnel.py

* separated rqinit file for both applications

* added app specific configuration

* added comment for app specific config

* fixed app order, removed unnecessary views from funnelapp and more fixes

* renamed jsonify function name

* moved model import inside function to avoid circular import

* misc fixes

* moving lastuser confix to app specific config files

* added LASTUSER_COOKIE_DOMAIN to app specific config

* fixed mui css issue with funnelapp

* funnelindex page update with new UI

* downloading CSV file instead of showing on tab

* using content type text/csv

* fixed placement of few hr tags

* Call embedIframe only when preview video link is present.

* misc fixes

* reverted to index_jsonify function

* removed unused function

* using parent_spaces_test relationship to test

* removed parent_spaces_test

* Sync funnelindex with index. Change heading to bold on proposal page.

* removed doubt

* Update footer with hasgeek info.

* Update hasgeek index page.

* Update navbar in about page.

* Update Flask Flat Pages in requirements.txt.

* Fix columns of footer.

* Minor css changes.

* Add divider btw headings.

* Add analytics and social media widgets. Add previous events section.

* added flatpages config to app settings
vidya-ram pushed a commit that referenced this pull request Nov 23, 2021
* replaced app with funnelapp and created new app instance

* added route for new app to all views

* replaced runtime use of app iwth current_app

* renamed runfunnelserver.py to runfunnel.py

* separated rqinit file for both applications

* added app specific configuration

* added comment for app specific config

* fixed app order, removed unnecessary views from funnelapp and more fixes

* renamed jsonify function name

* moved model import inside function to avoid circular import

* misc fixes

* moving lastuser confix to app specific config files

* added LASTUSER_COOKIE_DOMAIN to app specific config

* fixed mui css issue with funnelapp

* funnelindex page update with new UI

* downloading CSV file instead of showing on tab

* using content type text/csv

* fixed placement of few hr tags

* Call embedIframe only when preview video link is present.

* misc fixes

* reverted to index_jsonify function

* removed unused function

* using parent_spaces_test relationship to test

* removed parent_spaces_test

* Sync funnelindex with index. Change heading to bold on proposal page.

* removed doubt
vidya-ram added a commit that referenced this pull request Nov 23, 2021
* Add static pages.

* Second funnel app (#254)

* replaced app with funnelapp and created new app instance

* added route for new app to all views

* replaced runtime use of app iwth current_app

* renamed runfunnelserver.py to runfunnel.py

* separated rqinit file for both applications

* added app specific configuration

* added comment for app specific config

* fixed app order, removed unnecessary views from funnelapp and more fixes

* renamed jsonify function name

* moved model import inside function to avoid circular import

* misc fixes

* moving lastuser confix to app specific config files

* added LASTUSER_COOKIE_DOMAIN to app specific config

* fixed mui css issue with funnelapp

* funnelindex page update with new UI

* downloading CSV file instead of showing on tab

* using content type text/csv

* fixed placement of few hr tags

* Call embedIframe only when preview video link is present.

* misc fixes

* reverted to index_jsonify function

* removed unused function

* using parent_spaces_test relationship to test

* removed parent_spaces_test

* Sync funnelindex with index. Change heading to bold on proposal page.

* removed doubt

* Update footer with hasgeek info.

* Update hasgeek index page.

* Update navbar in about page.

* Update Flask Flat Pages in requirements.txt.

* Fix columns of footer.

* Minor css changes.

* Add divider btw headings.

* Add analytics and social media widgets. Add previous events section.

* added flatpages config to app settings
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants