From b4866aad63d9d120b068f43bb552ee713f6fd0e8 Mon Sep 17 00:00:00 2001
From: Benjamin Bertrand <benjamin.bertrand@esss.se>
Date: Fri, 1 Dec 2017 23:09:19 +0100
Subject: [PATCH] Implement UI to register items

---
 app/main/forms.py              | 24 +++++++++++++++++++++++-
 app/main/views.py              | 23 +++++++++++++++++++++--
 app/templates/create_item.html | 19 +++++++++++++++----
 app/utils.py                   |  9 +++++++++
 4 files changed, 68 insertions(+), 7 deletions(-)

diff --git a/app/main/forms.py b/app/main/forms.py
index 8ee9fd4..20549c2 100644
--- a/app/main/forms.py
+++ b/app/main/forms.py
@@ -10,7 +10,7 @@ This module defines the main forms.
 
 """
 from flask_wtf import FlaskForm
-from wtforms import SelectField, StringField, validators
+from wtforms import SelectField, StringField, SelectMultipleField, validators
 from .. import utils, models
 
 
@@ -37,6 +37,28 @@ class QRCodeForm(FlaskForm):
         )
 
 
+class ItemForm(FlaskForm):
+    ics_id = StringField('ICS id',
+                         validators=[validators.InputRequired(),
+                                     validators.Regexp(models.ICS_ID_RE)])
+    serial_number = StringField('Serial number',
+                                validators=[validators.InputRequired()])
+    manufacturer_id = SelectField('Manufacturer')
+    model_id = SelectField('Model')
+    location_id = SelectField('Location')
+    status_id = SelectField('Status')
+    parent_id = SelectField('Parent')
+    # macs = SelectMultipleField('Macs')
+
+    def __init__(self, *args, **kwargs):
+        super().__init__(*args, **kwargs)
+        self.manufacturer_id.choices = utils.get_model_choices(models.Manufacturer, allow_blank=True)
+        self.model_id.choices = utils.get_model_choices(models.Model, allow_blank=True)
+        self.location_id.choices = utils.get_model_choices(models.Location, allow_blank=True)
+        self.status_id.choices = utils.get_model_choices(models.Status, allow_blank=True)
+        self.parent_id.choices = utils.get_model_choices(models.Item, allow_blank=True, attr='ics_id')
+
+
 class HostForm(FlaskForm):
     network_id = SelectField('Network')
     # The list of IPs is dynamically created on the browser side
diff --git a/app/main/views.py b/app/main/views.py
index 6b058fb..b8476d0 100644
--- a/app/main/views.py
+++ b/app/main/views.py
@@ -13,7 +13,7 @@ import sqlalchemy as sa
 from flask import (Blueprint, render_template, jsonify,
                    redirect, url_for, request, flash, current_app)
 from flask_login import login_required
-from .forms import QRCodeForm, HostForm
+from .forms import QRCodeForm, HostForm, ItemForm
 from ..extensions import db
 from ..decorators import login_groups_accepted
 from .. import utils, models
@@ -72,7 +72,26 @@ def list_items():
 @bp.route('/items/create', methods=('GET', 'POST'))
 @login_groups_accepted('admin', 'create')
 def create_item():
-    form = None
+    form = ItemForm()
+    if form.validate_on_submit():
+        item = models.Item(ics_id=form.ics_id.data,
+                           serial_number=form.serial_number.data,
+                           manufacturer_id=form.manufacturer_id.data or None,
+                           model_id=form.model_id.data or None,
+                           location_id=form.location_id.data or None,
+                           status_id=form.status_id.data or None,
+                           parent_id=form.parent_id.data or None)
+        current_app.logger.debug(f'Trying to create: {item!r}')
+        db.session.add(item)
+        try:
+            db.session.commit()
+        except sa.exc.IntegrityError as e:
+            db.session.rollback()
+            current_app.logger.warning(f'{e}')
+            flash(f'{e}', 'error')
+        else:
+            flash(f'Item {item} created!', 'success')
+        return redirect(url_for('main.create_item'))
     return render_template('create_item.html', form=form)
 
 
diff --git a/app/templates/create_item.html b/app/templates/create_item.html
index 56a5f18..d9b2931 100644
--- a/app/templates/create_item.html
+++ b/app/templates/create_item.html
@@ -1,4 +1,5 @@
 {%- extends "base.html" %}
+{% from "_helpers.html" import render_field %}
 
 {% block title %}Items - CSEntry{% endblock %}
 
@@ -14,11 +15,21 @@
 
   <br>
 
-  <div class="card">
-    <h4 class="card-header">Register new item</h4>
-    <div class="card-body">
+  <form id="itemForm" method="POST">
+    {{ form.hidden_tag() }}
+    {{ render_field(form.ics_id) }}
+    {{ render_field(form.serial_number) }}
+    {{ render_field(form.manufacturer_id) }}
+    {{ render_field(form.model_id) }}
+    {{ render_field(form.location_id) }}
+    {{ render_field(form.status_id) }}
+    {{ render_field(form.parent_id) }}
+    <div class="form-group row">
+      <div class="col-sm-10">
+        <button type="submit" class="btn btn-primary">Submit</button>
+      </div>
     </div>
-  </div>
+  </form>
 {%- endblock %}
 
 {% block csentry_scripts %}
diff --git a/app/utils.py b/app/utils.py
index aab9a5a..9dc30ce 100644
--- a/app/utils.py
+++ b/app/utils.py
@@ -107,6 +107,15 @@ def get_choices(iterable, allow_blank=False, allow_null=False):
     return choices
 
 
+def get_model_choices(model, allow_blank=False, attr='name'):
+    """Return a list of (value, label)"""
+    choices = []
+    if allow_blank:
+        choices = [('', '')]
+    choices.extend([(str(instance.id), getattr(instance, attr)) for instance in model.query.all()])
+    return choices
+
+
 def get_query(query, args):
     """Retrieve the query from the arguments
 
-- 
GitLab