Skip to content

Commit

Permalink
Merge pull request #196 from RaghavPro/import_settings
Browse files Browse the repository at this point in the history
ability to import/export admin settings
  • Loading branch information
anandology authored Jul 26, 2016
2 parents 73cc763 + e6989de commit c39d1e1
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 20 deletions.
52 changes: 52 additions & 0 deletions cleansweep/plugins/committees/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ def dict(self):
"slug": self.slug,
"description": self.description,
"place_key": self.place.key,
"place_type_key": self.place_type.short_name,
"roles": [role.dict() for role in self.roles]
}

Expand Down Expand Up @@ -188,6 +189,57 @@ def get_all_members(self, place):
q = self._get_members_query(place)
return db.engine.execute(q).fetchall()

@staticmethod
def export():
"""
Calls dict() on each committee type and stores it in a list.
:return: List of all committee types.
"""
query = CommitteeType.query.all()
committee_types = [committee_type.dict() for committee_type in query]
return committee_types

@staticmethod
def import_committee_types(committee_types):
"""
Imports committee types from export data.
Validates if all required fields are present and slug does not already exist.
:param committee_types: List of dictionary objects containing committee_type data. See dict() of CommitteeType.
:return: List of CommitteeType objects successfully created.
"""
created = []
for c_type in committee_types:
place = Place.find(c_type.get('place_key'))
place_type = PlaceType.get(c_type.get('place_type_key'))
name = c_type.get('name', '').strip()
slug = c_type.get('slug', '').strip()
desc = c_type.get('description', '').strip()

slug_already_exists = CommitteeType.find(place, slug) is not None
if not place or not place_type or not name or slug_already_exists:
continue

committee_type = CommitteeType.new(place=place, place_type=place_type, name=name, slug=slug, desc=desc,
roles=c_type.get('roles', []))
created.append(committee_type)
return created

@staticmethod
def new(place, place_type, name, slug, desc="", roles=None):
"""
Creates a new CommitteeType from data provided and returns the object.
"""
committee_type = CommitteeType(place=place, place_type=place_type, name=name, slug=slug, description=desc)
db.session.add(committee_type)

for role in roles or []:
name = role.get('role', '').strip()
if not name:
continue
committee_type.add_role(role_name=name, multiple=role.get('multiple'), permission=role.get('permission'))
return committee_type


class CommitteeRole(db.Model):
"""Role in a committee.
Expand Down
48 changes: 31 additions & 17 deletions cleansweep/plugins/committees/templates/committee_structures.html
Original file line number Diff line number Diff line change
@@ -1,29 +1,43 @@

{% extends "admin/base.html" %}

{% block content_head %}
<div class="page-content">
<ul class="breadcrumb breadcrumb-collapse">
<li><a href="{{url_for('admin')}}">Admin Center</a></li>
<li></li>
</ul>
<h2>Committee Structures</h2>
</div>
<div class="page-content">
<ul class="breadcrumb breadcrumb-collapse">
<li><a href="{{ url_for('admin') }}">Admin Center</a></li>
<li></li>
</ul>
<h2>Committee Structures</h2>
</div>
{% endblock %}

{% block content_body %}
<div class="list-group">
{% for p in place.type.all() %}
{% set committees_count = place.committee_types.filter_by(place_type_id=p.id).count() %}
<a href="{{ url_for(".committee_structures_by_level", level=p.short_name)}}" class="list-group-item"
{% if committees_count == 0 %}
style="background: #eee;"
title="No committee structures are defined at this level."
{% endif %}
>
{{ p.name }}
<span class="badge">{{ committees_count }}</span>
</a>
<a href="{{ url_for(".committee_structures_by_level", level=p.short_name) }}" class="list-group-item"
{% if committees_count == 0 %}
style="background: #eee;"
title="No committee structures are defined at this level."
{% endif %}
>
{{ p.name }}
<span class="badge">{{ committees_count }}</span>
</a>
{% endfor %}
</div>
<div>
<a class="btn btn-primary" href="{{ url_for('.export_committee_structures') }}">Export</a>
<div class="pull-right">
{% if has_permission("committees.import") %}
<form action="{{ url_for('.import_committee_structures') }}" enctype="multipart/form-data" method="post">
<div class="input-group" style="width: 300px">
<input type="file" name="file" class="form-control">
<span class="input-group-btn">
<button class="btn btn-primary" type="submit">Import</button>
</span>
</div>
</form>
{% endif %}
</div>
</div>
{% endblock %}
30 changes: 29 additions & 1 deletion cleansweep/plugins/committees/views.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import json

from ...plugin import Plugin
from ...core import rbac
from ...models import db, Member, PlaceType, Place
from .models import CommitteeRole, CommitteeType
from flask import (flash, request, Response, make_response, render_template, redirect, url_for, abort)
from flask import (flash, request, Response, make_response, render_template, redirect, url_for, abort, jsonify)
from . import forms
from . import signals, notifications, audits
from ...view_helpers import require_permission
Expand Down Expand Up @@ -233,3 +235,29 @@ def download_members_of_committee_type(slug):
response = Response(dataset.xls, content_type='application/vnd.ms-excel;charset=utf-8')
response.headers['Content-Disposition'] = "attachment; filename='{0}'".format(filename)
return response


@plugin.route("/admin/committee-structures/export", methods=['GET'])
@require_permission("admin.committee-structures.view")
def export_committee_structures():
response = jsonify(committee_types=CommitteeType.export())
response.headers['Content-Type'] = 'application/json'
response.headers['Content-Disposition'] = "attachment;filename=committee_structures.json"
return response


@plugin.route("/admin/committee-structures/import", methods=['POST'])
@require_permission("admin.committee-structures.import")
def import_committee_structures():
json_file = request.files['file']
file_content = json_file.read()
try:
committee_types = json.loads(file_content).get('committee_types') or []
created = CommitteeType.import_committee_types(committee_types)
db.session.commit()
flash("Successfully created {0} of {1} committee structures.".format(len(created), len(committee_types)),
category="success")
except ValueError:
flash("An error occurred. Maybe it was an invalid file. Make sure JSON is correct.", category="error")

return redirect(url_for(".committee_structures"))
3 changes: 1 addition & 2 deletions cleansweep/views/admin.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
"""Views of the admin panel.
"""

from flask import (render_template, abort, url_for, redirect, request,
make_response, session, flash, jsonify)
make_response, session, flash)
from ..models import Member, db, PendingMember, Place
from .. import forms
from ..app import app
Expand Down

0 comments on commit c39d1e1

Please sign in to comment.