Skip to content

Commit v0.16

kwmccabe edited this page Apr 17, 2018 · 10 revisions

v0.16 - Item fields (active,item_title,item_text,mod_update), Delete Item confirmation


Files changed (14)

File mysql/scripts/seeddata.sql MODIFIED

  • Add item_title and item_text to flaskapp.item seeddata.
 DELETE FROM `item`;
-INSERT INTO `item` (keyname) VALUES ("one");
-INSERT INTO `item` (keyname) VALUES ("two");
-INSERT INTO `item` (keyname) VALUES ("three");
+INSERT INTO `item` (keyname,item_title,item_text) VALUES ("one","One","One here");
+INSERT INTO `item` (keyname,item_title,item_text) VALUES ("two","Two","Two here");
+INSERT INTO `item` (keyname,item_title,item_text) VALUES ("three","Three","Three here");
+INSERT INTO `item` (keyname,item_title,item_text) VALUES ("four","Four","Four here");
+INSERT INTO `item` (keyname,item_title,item_text) VALUES ("five","Five","Five here");
+INSERT INTO `item` (keyname,item_title,item_text) VALUES ("six","Six","Six here");
 OPTIMIZE TABLE `item`;

File mysql/scripts/tables.sql MODIFIED

  • Add active, item_title, item_text and mod_update to CREATE TABLE statement.
 CREATE TABLE `item` (
     `id`            bigint(20)      NOT NULL AUTO_INCREMENT,
     `keyname`       varchar(63)     NOT NULL,
+    `active`        tinyint(1)      NOT NULL DEFAULT '1',
+    `item_title`    varchar(255)    DEFAULT NULL,
+    `item_text`     text,
     `mod_create`    datetime        DEFAULT CURRENT_TIMESTAMP,
+    `mod_update`    datetime        DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
 
     PRIMARY KEY (`id`),
-    UNIQUE KEY `item_keyname` (`keyname`)
+    UNIQUE KEY `item_keyname` (`keyname`),
+    KEY `item_active` (`active`),
+    KEY `item_title` (`item_title`),
+    KEY `item_update` (`mod_update`)
 ) ENGINE=InnoDB AUTO_INCREMENT=1000 DEFAULT CHARSET=utf8;
 DESCRIBE `item`;
 SELECT "table `item` created" AS MSG;

File web/app/item/forms.py MODIFIED

  • Add the required column item_title to CreateItemForm.
  • Add all columns (editable and non-editable) to EditItemForm.
 class CreatItemForm(FlaskForm):
     keyname    = StringField('Keyname', validators=[InputRequired(),Length(2,63),validate_keyname], filters=[filter_keyname])
+    item_title = StringField('Title', validators=[InputRequired(),Length(1,255)])
     submit     = SubmitField('Create Item')
 
...

 class EditItemForm(FlaskForm):
     id         = HiddenField('id')
     keyname    = StringField('Keyname', validators=[InputRequired(),Length(2,63),validate_keyname], filters=[filter_keyname])
+    active     = BooleanField('Active')
+    item_title = StringField('Title', validators=[InputRequired(),Length(1,255)])
+    item_text  = TextAreaField('Text')
     mod_create = DateTimeField('Item Created')
+    mod_update = DateTimeField('Item Updated')
     submit     = SubmitField('Update Item')

File web/app/item/models.py MODIFIED

  • Add active, item_title, item_text and mod_update to class ItemModel.
     __tablename__ = 'item'
     id         = db.Column(db.BigInteger, autoincrement=True, primary_key=True)
     keyname    = db.Column(db.String(63), nullable=False, index=True, unique=True, default='')
+    active     = db.Column(db.Boolean, nullable=False, index=True, default=1)
+    item_title = db.Column(db.String(255))
+    item_text  = db.Column(db.Text)
     mod_create = db.Column(db.DateTime, default=datetime.utcnow)
+    mod_update = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, index=True)
 
     def to_json(self):
         json_item = {
             #'url': url_for('api.get_item', id=self.id),
             'id'        : self.id,
             'keyname'   : self.keyname,
+            'active'    : self.active,
+            'item_title': self.item_title,
+            'item_text' : self.item_text,
             'mod_create': self.mod_create,
+            'mod_update': self.mod_update,
         }
         return json_item

File web/app/item/templates/item_create.html MODIFIED

  • Add input field for the required column item_title.
 <!-- BLOCK: breadcrumb -->
 {% block breadcrumb %}
 {{super()}}
-<li><a href="/admin/">Admin</a></li>
+<li><a href="{{ url_for('main.main_page', page='admin') }}">Admin</a></li>
 <li><a href="{{ url_for('.item_list') }}">Items</a></li>
 <li><a href="{{ url_for('.item_create') }}">Create</a></li>
 {% endblock %}

...

+    <div class="form-group">
+        *{{ form.item_title.label }}
+        {{ form.item_title(class_='form-control',placeholder='Title') }}
+    </div>
     {{ form.submit(class_='btn btn-primary') }}
     <span class="form-submit-buttons">
-        [ <a class="btn btn-default" href="{{ url_for('.item_list') }}">Cancel</a> ]
+        <a class="btn btn-default" href="{{ url_for('.item_list') }}">Cancel</a>
     </span>
 </form> 

File web/app/item/templates/item_edit.html MODIFIED

  • Add input fields for columns item_title, item_text, and active.
  • Add display for column mod_update.
  • Add data-confirm-link="Delete Item? This action cannot be undone." to Delete Item link.
 <!-- BLOCK: breadcrumb -->
 {% block breadcrumb %}
 {{super()}}
-<li><a href="/admin/">Admin</a></li>
+<li><a href="{{ url_for('main.main_page', page='admin') }}">Admin</a></li>
 <li><a href="{{ url_for('.item_list') }}">Items</a></li>
 <li><a href="{{ url_for('.item_edit', id=form.id.data) }}">Edit {{ form.item.keyname }}</a></li>
 {% endblock %}

...

+    <div class="form-group">
+        *{{ form.item_title.label }}
+        {{ form.item_title(class_='form-control',placeholder='Title') }}
+    </div>
+    <div class="form-group">
+        {{ form.item_text.label }}
+        {{ form.item_text(class_='form-control',placeholder='Text') }}
+    </div>
+    <div class="form-group">
+        {{ form.active.label }}
+        {{ form.active(class_='form-control') }}
+    </div>
     {{ form.submit(class_='btn btn-primary') }}
     <span class="form-submit-buttons">
-        [ <a href="{{ url_for('.item_delete', id=form.id.data) }}">Delete Item</a> ]
+        [ <a data-confirm-link="Delete Item? This action cannot be undone." href="{{ url_for('.item_delete', id=form.id.data) }}">Delete Item</a> ]
     </span>
 </form>
 
 {{ form.mod_create.label }} : {{ form.mod_create.data }}<br/>
+{{ form.mod_update.label }} : {{ form.mod_update.data }}<br/>
 
     </div> <!-- end class="panel-body" -->
 </div> <!-- end class="panel" -->

File web/app/item/templates/item_index.html ADDED

  • Create template for route /item/.
+{% extends "base.html" %}
+
+<!-- BLOCK: breadcrumb -->
+{% block breadcrumb %}
+{{super()}}
+<li><a href="{{ url_for('.item_page') }}">Items</a></li>
+{% endblock %}
+
+<!-- BLOCK: content -->
+{% block content %}
+
+<p>This is public landing page for the Item Module.</p>
+
+{% endblock %}
+
+
+<!-- BLOCK: templates -->
+{% block templates %}{{super()}} - item_index.html{% endblock %}
+
+{# end web/app/item/templates/item_index.html #}

File web/app/item/templates/item_list.html MODIFIED

  • Add placeholder navigation links for filtering view by item.active.
  • Add data-confirm-link to Delete Item link.
 <!-- BLOCK: breadcrumb -->
 {% block breadcrumb %}
 {{super()}}
-<li><a href="/admin/">Admin</a></li>
+<li><a href="{{ url_for('main.main_page', page='admin') }}">Admin</a></li>
 <li><a href="{{ url_for('.item_list') }}">Items</a></li>
 {% endblock %}
 
...

 <tr>
 <td>
     Showing {{ rowcnt }} Items
-    <br/><br/>[ <a href="{{ url_for('.item_create') }}">Create Item</a> ]
 </td>
 <td class="text-right">
     <span>Page 1 of 1</span>
 </td>
 </tr>
+<tr>
+<td>
+    [ <a href="{{ url_for('.item_create') }}">Create Item</a> ]
+</td>
+<td class="text-right">
+    [<a href="{{ url_for('.item_list') }}?status=all">All</a>]
+    [<a href="{{ url_for('.item_list') }}?status=active">Active</a>]
+    [<a href="{{ url_for('.item_list') }}?status=inactive">Inactive</a>]
+</td>
+</tr>
 </table>
 
...

     <td>
         [ <a href="{{ url_for('.item_edit', id=row.id) }}">edit</a> ]
-        [ <a href="{{ url_for('.item_delete', id=row.id) }}">delete</a> ]
+        [ <a data-confirm-link="Delete Item? This action cannot be undone." href="{{ url_for('.item_delete', id=row.id) }}">delete</a> ]
     </td>

File web/app/item/templates/item_view.html MODIFIED

 <!-- BLOCK: breadcrumb -->
 {% block breadcrumb %}
 {{super()}}
-<li><a href="/admin/">Admin</a></li>
+<li><a href="{{ url_for('main.main_page', page='admin') }}">Admin</a></li>
 <li><a href="{{ url_for('.item_list') }}">Items</a></li>
 <li><a href="{{ url_for('.item_view', id=item.id) }}">{{ item.keyname }}</a></li>
 {% endblock %}

File web/app/item/views.py MODIFIED

  • Replace hello_item() with new, generic route /item/<page>/.
  • Remove form.mod_update from database update - applies default as defined in CREATE TABLE statement.
+from jinja2 import TemplateNotFound

...

-@item.route('/item/')
-def hello_item():
-    logging.info("hello_item()")
-    return 'Hello FlaskApp : Item Module'
+@item.route('/item/', defaults={'page': 'index'})
+@item.route('/item/<page>/')
+def item_page(page):
+    try:
+        logging.debug( 'item_page( page:%s )' % (page) )
+        return render_template('item_%s.html' % (page))
+    except TemplateNotFound:
+        logging.info('TemplateNotFound: item_%s.html' % (page))
+        abort(404)

...

     item = ItemModel.query.get_or_404(id)
     form = EditItemForm(item)
     if form.validate_on_submit():
-        del form.mod_create
+        del form.mod_create, form.mod_update
         form.populate_obj(item)
         db.session.add(item)
         db.session.commit()

File web/app/main/templates/base.html MODIFIED

 <div id="debuginfo"><pre>
 DEBUG:
 TEMPLATES: {% block templates %}base.html{% endblock %}
+REQUEST.ARGS: {{ request.args }}
 </pre></div>

File web/app/main/templates/navbar_main.html MODIFIED

  • Link to route /item/.
  • Link to route /admin/.
     <div class="collapse navbar-collapse" id="navbar-main-collapse">
       <ul class="nav navbar-nav">
         <!-- li class="active"><a href="#">Link <span class="sr-only">(current)</span></a></li -->
-        <li><a href="#">Items</a></li>
+        <li><a href="{{ url_for('item.item_page') }}">Items</a></li>
         <li><a href="#">Users</a></li>
         <li class="dropdown">
           <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Admin <span class="caret"></span></a>
           <ul class="dropdown-menu">
+            <li><a href="{{ url_for('main.main_page', page='admin') }}">Dashboard</a></li>
+            <li role="separator" class="divider"></li>
             <li><a href="{{ url_for('item.item_list') }}">Items</a></li>
             <li><a href="#">Users</a></li>
-            <li role="separator" class="divider"></li>
-            <li><a href="#">ItemSix</a></li>
           </ul>
         </li>
       </ul>

File web/app/main/views.py MODIFIED

 @main.route('/<page>/')
 def main_page(page):
     try:
-        logging.debug( "main_page( %s )" % page )
+        logging.debug( 'main_page( page:%s )' % (page) )
         return render_template('%s.html' % (page))
     except TemplateNotFound:
         logging.info('TemplateNotFound: %s.html' % (page))

File web/app/static/js/flaskapp.js MODIFIED

  • New $(document).ready() function searches for anchor tags with the attribute data-confirm-link, and attaches a javascript confirm() dialog.
  • eg, <a data-confirm-link="Really do it?" href="/doit/123">Do It</a>
+/**
+ * add confirm dialog for <a> with data-confirm-link attribute
+ * @see item_edit.html
+ */
+$(document).ready(function () {
+    $('a[data-confirm-link]').click(function () {
+        if (confirm($(this).data('confirm-link')))
+            window.location = $(this).attr('href');
+        return false;
+    });
+});

Commit-v0.15 | Commit-v0.16 | Commit-v0.17

Clone this wiki locally