summaryrefslogtreecommitdiffstats
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/__init__.py8
-rw-r--r--app/models.py33
-rw-r--r--app/views.py110
3 files changed, 151 insertions, 0 deletions
diff --git a/app/__init__.py b/app/__init__.py
new file mode 100644
index 0000000..f441218
--- /dev/null
+++ b/app/__init__.py
@@ -0,0 +1,8 @@
+from flask import Flask
+from flask.ext.sqlalchemy import SQLAlchemy
+
+app = Flask(__name__)
+app.config.from_object('config')
+db = SQLAlchemy(app)
+
+from app import views, models
diff --git a/app/models.py b/app/models.py
new file mode 100644
index 0000000..4df6689
--- /dev/null
+++ b/app/models.py
@@ -0,0 +1,33 @@
+from app import db
+import datetime
+
+class User(db.Model):
+ id = db.Column(db.Integer, primary_key=True)
+ nickname = db.Column(db.String(64), index=True, unique=True)
+ email = db.Column(db.String(120), index=True, unique=True)
+ opened = db.relationship('Ticket', backref='opened_by', lazy='dynamic', primaryjoin = 'Ticket.opened_by_user_id == User.id')
+ assigned = db.relationship('Ticket', backref='assigned_to', lazy='dynamic', primaryjoin = 'Ticket.assigned_to_user_id == User.id')
+
+
+ def __repr__(self):
+ return '<User %r>' % (self.nickname)
+
+class Ticket(db.Model):
+ id = db.Column(db.Integer, primary_key=True)
+
+ summary = db.Column(db.String(140), nullable=False)
+ body = db.Column(db.Text, nullable=False)
+
+ opened_at = db.Column(db.DateTime, nullable=False)
+ updated_at = db.Column(db.DateTime)
+
+ status = db.Column(db.String(64), nullable=False, default='open')
+ resolution = db.Column(db.String(64))
+ reason = db.Column(db.String(140))
+ deleted = db.Column(db.Boolean, default=False)
+
+ opened_by_user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
+ assigned_to_user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
+
+ def __repr__(self):
+ return '<Ticket %r>' % (self.id)
diff --git a/app/views.py b/app/views.py
new file mode 100644
index 0000000..2e6ba6f
--- /dev/null
+++ b/app/views.py
@@ -0,0 +1,110 @@
+from flask import jsonify, abort, make_response, request, url_for
+from datetime import datetime
+from app import app, db, models
+
+def make_public_ticket(ticket):
+ new_ticket = ticket.copy()
+ new_ticket['uri'] = url_for('get_ticket', ticket_id=ticket['id'], _external=True)
+ return new_ticket
+
+def ticket_to_dict(ticket):
+ nt = {}
+ nt['id'] = ticket.id
+
+ nt['deleted'] = ticket.deleted
+
+ nt['summary'] = ticket.summary
+ nt['body'] = ticket.body
+
+ nt['opened_at'] = ticket.opened_at.strftime('%Y-%m-%dT%H:%M:%S')
+
+ if ticket.updated_at:
+ nt['updated_at'] = ticket.updated_at.strftime('%Y-%m-%dT%H:%M:%S')
+ else:
+ nt['updated_at'] = None
+
+ nt['status'] = ticket.status
+
+ nt['resolution'] = ticket.resolution
+ nt['reason'] = ticket.reason
+
+ if ticket.opened_by:
+ nt['opened_by'] = {
+ 'id': ticket.opened_by.id,
+ 'nickname': ticket.opened_by.nickname,
+ 'email': ticket.opened_by.email,
+ }
+ else:
+ nt['opened_by'] = {'id': None, 'nickname': None, 'email': None}
+
+ if ticket.assigned_to:
+ nt['assigned_to'] = {
+ 'id': ticket.assigned_to.id,
+ 'nickname': ticket.assigned_to.nickname,
+ 'email': ticket.assigned_to.email,
+ }
+ else:
+ nt['assigned_to'] = None
+
+ return nt
+
+@app.route('/tbt/api/1.0/tickets', methods=['GET'])
+def get_tickets():
+ ts = models.Ticket.query.filter(models.Ticket.deleted != True).all()
+ tickets = map(ticket_to_dict, ts)
+ return jsonify({'tickets': list(map(make_public_ticket, tickets))})
+
+@app.route('/tbt/api/1.0/ticket', methods=['POST'])
+def create_ticket():
+ if not request.json or not ('summary' and 'body' and 'user_nickname') in request.json:
+ abort(400)
+
+ user = models.User.query.filter(models.User.nickname == request.json['user_nickname']).first()
+
+ ticket = models.Ticket(summary=request.json['summary'],
+ body=request.json['body'],
+ opened_by=user,
+ opened_at=datetime.utcnow())
+ db.session.add(ticket)
+ db.session.commit()
+
+ td = ticket_to_dict(ticket)
+
+ return jsonify({'ticket': make_public_ticket(td)}), 201
+
+@app.route('/tbt/api/1.0/ticket/<int:ticket_id>', methods=['GET'])
+def get_ticket(ticket_id):
+ ticket = models.Ticket.query.get(ticket_id)
+ if not ticket:
+ abort(404)
+
+ return jsonify({'ticket': make_public_ticket(ticket_to_dict(ticket))})
+
+@app.route('/tbt/api/1.0/ticket/<int:ticket_id>', methods=['PUT'])
+def update_ticket(ticket_id):
+ ticket = next((t for t in tickets if t['id'] == ticket_id), None)
+ if not ticket:
+ abort(404)
+ if not request.json:
+ abort(400)
+ ticket['summary'] = request.json.get('summary', ticket['summary'])
+ ticket['body'] = request.json.get('body', ticket['body'])
+ ticket['status'] = request.json.get('status', ticket['status'])
+ ticket['resolution'] = request.json.get('resolution', ticket['resolution'])
+ ticket['reason'] = request.json.get('reason', ticket['reason'])
+ ticket['assigned-to'] = request.json.get('assigned-to', ticket['assigned-to'])
+ return jsonify({'ticket': make_public_ticket(ticket)})
+
+@app.route('/tbt/api/1.0/ticket/<int:ticket_id>', methods=['DELETE'])
+def delete_ticket(ticket_id):
+ ticket = next((t for t in tickets if t['id'] == ticket_id), None)
+ if not ticket:
+ abort(404)
+ #tickets.remove(ticket)
+ ticket['deleted'] = True
+ return jsonify({'result': True})
+
+@app.errorhandler(404)
+def not_found(error):
+ return make_response(jsonify({'error': 'Not found'}), 404)
+