-
Notifications
You must be signed in to change notification settings - Fork 5
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
Added new and edit for organization #222
base: main
Are you sure you want to change the base?
Changes from 2 commits
edba52b
66653a8
b01d0f8
e4313fa
3cbc222
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
# -*- coding: utf-8 -*- | ||
|
||
from boxoffice.models import db, Organization | ||
from baseframe.forms.sqlalchemy import QuerySelectField | ||
import baseframe.forms as forms | ||
from coaster.utils import buid | ||
from baseframe import __ | ||
from .utils import validate_json, format_json | ||
|
||
__all__ = ['OrgForm', 'NewOrgForm'] | ||
|
||
|
||
DEFAULT_ORG_DETAILS = { | ||
u'access_token': buid(), | ||
u'address': u'', | ||
u'cin': u'', | ||
u'logo': u'', | ||
u'pan': u'', | ||
u'refund_policy': u'', | ||
u'support_email': u'', | ||
u'ticket_faq': u'', | ||
u'website': u'' | ||
} | ||
|
||
|
||
class OrgForm(forms.Form): | ||
contact_email = forms.EmailField(__("Contact email"), | ||
validators=[forms.validators.DataRequired(__("Please enter an email address")), forms.validators.Length(min=5, max=80)]) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use an email validator instead of a length validator. |
||
details = forms.TextAreaField(__("Details"), filters=[format_json], | ||
validators=[validate_json], default=DEFAULT_ORG_DETAILS) | ||
invoicer = QuerySelectField(__("Parent organization"), get_label='title', | ||
validators=[forms.validators.DataRequired(__("Please select a parent organization"))]) | ||
|
||
def set_queries(self): | ||
self.invoicer.query = Organization.query.filter( | ||
Organization.invoicer == None).options(db.load_only('id', 'title')) | ||
|
||
|
||
class NewOrgForm(OrgForm): | ||
organization = forms.RadioField(u"Organization", validators=[forms.validators.DataRequired("Select an organization")], | ||
description=u"Select the organization you’d like to setup Boxoffice for") |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
# -*- coding: utf-8 -*- | ||
|
||
import json | ||
from flask import request | ||
import baseframe.forms as forms | ||
from baseframe import __ | ||
|
||
|
||
def validate_json(form, field): | ||
try: | ||
json.loads(field.data) | ||
except ValueError: | ||
raise forms.validators.StopValidation(__("Invalid JSON")) | ||
|
||
|
||
def format_json(data): | ||
if request.method == 'GET': | ||
return json.dumps(data, indent=4, sort_keys=True) | ||
# `json.loads` doesn't raise an exception for "null" | ||
# so assign a default value of `{}` | ||
if not data or data == 'null': | ||
return json.dumps({}) | ||
return data | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So it doesn't format JSON if the request is not a GET? That doesn't make sense. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The formatting with indents is only to make it easy for the admin to edit it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I mean the "return data" bit. It's returning the Python data object if the request is not a GET? Why? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's because |
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
{"assets":{"main_order":"main_order.be0a8f034a0fd223228e.js","main_invoice":"main_invoice.be0a8f034a0fd223228e.js","main_admin":"main_admin.be0a8f034a0fd223228e.js"}} | ||
{"assets":{"main_order":"main_order.77834e515b9b2330ff9c.js","main_invoice":"main_invoice.77834e515b9b2330ff9c.js","main_admin":"main_admin.77834e515b9b2330ff9c.js"}} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
# -*- coding: utf-8 -*- | ||
|
||
from . import admin, item_collection, order, participant, login, admin_item_collection, admin_order, admin_discount, admin_report, admin_item, admin_category | ||
from . import admin, org, item_collection, order, participant, login, admin_item_collection, admin_order, admin_discount, admin_report, admin_item, admin_category |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
# -*- coding: utf-8 -*- | ||
|
||
from flask import g, Markup, request, flash, url_for, redirect | ||
from coaster.views import load_models | ||
from baseframe import _ | ||
from baseframe.forms import render_message, render_redirect, render_form | ||
from ..models import db, Organization | ||
from ..forms import OrgForm, NewOrgForm | ||
from .. import app, lastuser | ||
|
||
|
||
@lastuser.requires_permission('siteadmin') | ||
@lastuser.requires_login | ||
@app.route('/admin/o/new', methods=['GET', 'POST']) | ||
def new_org(): | ||
# Step 1: Get a list of organizations this user owns | ||
existing = Organization.query.filter(Organization.userid.in_(g.user.organizations_owned_ids())).all() | ||
existing_ids = [e.userid for e in existing] | ||
# Step 2: Prune list to organizations without a profile | ||
new_orgs = [] | ||
for user_org in g.user.organizations_owned(): | ||
if user_org['userid'] not in existing_ids: | ||
new_orgs.append((user_org['userid'], user_org['title'])) | ||
if not new_orgs: | ||
return render_message( | ||
title=_(u"No organizations found"), | ||
message=Markup(_(u"You do not have any organizations that are not setup on Boxoffice. " | ||
u'Would you like to <a href="{link}">create a new organization</a>?').format( | ||
link=lastuser.endpoint_url('/organizations/new')))) | ||
eligible_orgs = [] | ||
for orgid, title in new_orgs: | ||
eligible_orgs.append((orgid, title)) | ||
if not eligible_orgs: | ||
return render_message( | ||
title=_(u"No organizations available"), | ||
message=_(u"To setup Boxoffice for an organization, you must be the owner of the organization.")) | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use the logic used in Funnel's There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's mostly borrowed from there. https://github.com/hasgeek/funnel/blob/master/funnel/views/profile.py#L34 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Damn, then that needs to be tossed as well. We can live with this for now, knowing that both places will need to be changed after hasgeek/lastuser#232. |
||
# Step 3: Ask user to select organization | ||
form = NewOrgForm() | ||
form.organization.choices = eligible_orgs | ||
if request.method == 'GET': | ||
form.organization.data = new_orgs[0][0] | ||
if form.validate_on_submit(): | ||
# Step 4: Make a profile | ||
user_org = [user_org for user_org in g.user.organizations_owned() if user_org['userid'] == form.organization.data][0] | ||
organization = Organization(name=user_org['name'], title=user_org['title'], userid=user_org['userid']) | ||
form.populate_obj(organization) | ||
db.session.add(organization) | ||
db.session.commit() | ||
flash(_(u"Created an organization for {org}").format(org=organization.title), "success") | ||
return redirect(url_for('org', org=organization.name), code=303) | ||
return render_form( | ||
form=form, | ||
title=_(u"Setup Boxoffice for your organization..."), | ||
submit="Next", | ||
formid="org_new", | ||
cancel_url=url_for('index'), | ||
ajax=False) | ||
|
||
|
||
@app.route('/admin/o/<name>/edit', methods=['GET', 'POST']) | ||
@load_models( | ||
(Organization, {'name': 'name'}, 'org'), | ||
permission='org_admin') | ||
def edit_org(org): | ||
form = OrgForm(obj=org) | ||
if form.validate_on_submit(): | ||
form.populate_obj(org) | ||
db.session.commit() | ||
flash(_("Your changes have been saved"), 'info') | ||
return redirect(url_for('org', org=org.name), code=303) | ||
return render_form( | ||
form=form, | ||
title=_("Edit organization settings"), | ||
submit=_("Save changes"), | ||
cancel_url='/admin/o/{{org}}'.format(org=org.name), | ||
ajax=False) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is declaring a fixed access token as a global.