[chronojump-server] Final version of Stations and Exercises Page with the addition of modification and deletion function



commit cd933577297d08c6ab6f37a78339fc203a440a0d
Author: Marcos Venteo García <mventeo gmail com>
Date:   Tue Jun 27 22:37:16 2017 +0200

    Final version of Stations and Exercises Page with the addition of modification and deletion functionality.
    This commit completes the initial version of the server.

 chronojumpserver/api.py                      |   90 ++++++++--
 chronojumpserver/js/players.js               |   12 +-
 chronojumpserver/js/stations.js              |  258 +++++++++++++++++++-------
 chronojumpserver/models.py                   |   83 +++++----
 chronojumpserver/static/style.css            |   12 +-
 chronojumpserver/templates/station_list.html |   45 ++---
 6 files changed, 344 insertions(+), 156 deletions(-)
---
diff --git a/chronojumpserver/api.py b/chronojumpserver/api.py
index fbfed01..dcf735c 100755
--- a/chronojumpserver/api.py
+++ b/chronojumpserver/api.py
@@ -8,6 +8,7 @@ from chronojumpserver.database import db_session
 from chronojumpserver.models import Person, ResultEncoder, Station, Task
 from chronojumpserver.models import ResultSprint, Exercise
 from flask import jsonify, request
+from sqlalchemy.exc import IntegrityError, InvalidRequestError, OperationalError
 from time import sleep
 import os
 import subprocess
@@ -57,7 +58,6 @@ def get_all_players():
 def get_exercises_by_station():
     """Return all the exercises of a given station."""
     stationId = request.args.get('station_id')
-    print "STATION ID IS %s" % stationId
     station = Station.query.filter(Station.id == stationId).first()
     exercises = []
     for exercise in station.exercises:
@@ -66,6 +66,12 @@ def get_exercises_by_station():
         print exercise.percentBodyMassDisplaced
     return jsonify(data=exercises)
 
+@app.route('/api/v1/stations')
+def get_stations():
+    """Return all the stations."""
+    stations = [station.serialize for station in Station.query.all()]
+    return jsonify(data=stations)
+
 
 @app.route('/api/v1/rfid/register')
 def register_rfid():
@@ -168,34 +174,88 @@ def add_modify_delete_task():
     return jsonify(msg='Task has been successfully added')
 
 
-@app.route('/api/v1/stations', methods=['PUT', 'DELETE'])
+@app.route('/api/v1/station', methods=['PUT', 'DELETE'])
 def add_modify_delete_stations():
+    status_code = 200
+    msg = "Success"
     if request.method == "PUT":
-        stationId = request.form['stationId']
+        print "STATION PUT"
+        stationId = int(request.form['stationId'])
         stationName = request.form['stationName']
         stationType = request.form['stationType']
-
-        if int(stationId) == -1:
+        print "STATION ID passed " + str(stationId)
+        if stationId == -1:
             # New station
             s = Station(name=stationName, type=stationType)
             db_session.add(s)
-            db_session.commit()
+            try:
+                db_session.commit()
+            except IntegrityError:
+                msg = "ERROR: Aquest estació ja existeix."
+                status_code = 500
+        else:
+            # Update the station
+            db_session.query(Station).filter_by(id=stationId).update({
+                'name' : stationName,
+                'type' : stationType
+            })
+            try:
+                db_session.commit()
+            except IntegrityError:
+                msg = "ERROR: No s'ha pogut actualitzar."
+                status_code = 500
+    else:
+        # Delete the station
+        stationId = int(request.form['stationId'])
+        print stationId
+        s = Station.getById(stationId)
+        db_session.delete(s)
+        db_session.commit()
 
-    return jsonify(msg="Success")
+    response = jsonify(msg=msg.decode('utf-8'))
+    response.status_code = status_code
+    return response
 
-@app.route('/api/v1/exercise/add', methods=['PUT', 'DELETE'])
+@app.route('/api/v1/exercise', methods=['PUT', 'DELETE'])
 def add_modify_delete_exercises():
+    status_code = 200
+    msg = "Success"
     if request.method == "PUT":
-        exerciseId = request.form['id']
-        stationId = request.form['stationId']
+        print "ddede"
+        exerciseId = int(request.form['id'])
+        stationId = int(request.form['stationId'])
         name = request.form['name']
         percentBodyMassDisplaced = request.form['percentBodyMassDisplaced']
-
-        if int(exerciseId) == -1:
-            # New station
+        print "HOLA"
+        if exerciseId == -1:
+            # New Exercise
             e = Exercise(name=name, stationId=stationId,
                          percentBodyMassDisplaced=percentBodyMassDisplaced)
             db_session.add(e)
-            db_session.commit()
+            try:
+                db_session.commit()
 
-    return jsonify(msg="Success")
+            except IntegrityError:
+                msg = "ERROR: Aquest exercici ja existeix en aquesta estació."
+                status_code = 500
+        else:
+            # Update the exercise
+            db_session.query(Exercise).filter_by(id=exerciseId).update({
+                'name' : name,
+                'percentBodyMassDisplaced' : percentBodyMassDisplaced
+            })
+            try:
+                db_session.commit()
+            except IntegrityError:
+                msg = "ERROR: No s'ha pogut actualitzar."
+                status_code = 500
+    else:
+        # Delete the exercise
+        exerciseId = int(request.form['exerciseId'])
+        e = Exercise.getById(exerciseId)
+        db_session.delete(e)
+        db_session.commit()
+
+    response = jsonify(msg=msg.decode('utf-8'))
+    response.status_code = status_code
+    return response
diff --git a/chronojumpserver/js/players.js b/chronojumpserver/js/players.js
index 1f4a496..a373666 100755
--- a/chronojumpserver/js/players.js
+++ b/chronojumpserver/js/players.js
@@ -26,7 +26,6 @@ function addModifyDeleteTask(action) {
                           2 - delete
     */
     /* Function to add or modify the task */
-    console.log('Adding or Modifying a task');
     var playerId = $('#playerId').val();
     var description = $('#taskComment').val();
     var taskId = $('#taskId').val();
@@ -145,12 +144,16 @@ $(document).ready(function() {
                     if (value.length > 0) {
                         var html = "<ol>";
                         $.each(value, function(index, task) {
-                            console.log(value);
                             if (task.type == 'F') {
                                 var _desc = task.description;
                             } else {
                                 // Compose the description based on values
-                                var _desc = task.nreps + " repeticions ";
+                                if (task.sets > 1) {
+                                    var _desc = task.sets + "x" + task.nreps + " repeticions ";
+                                } else {
+                                    var _desc = task.nreps + " repeticions ";
+                                }
+
                                 _desc += "de " + task.exercise;
                                 _desc += " a l'estació " + task.station;
                             }
@@ -245,7 +248,6 @@ $(document).ready(function() {
     /* To show the model to modify the task */
     $('#players').on('click', 'a.task-link', function() {
         var player = table.row($(this).parents('tr')).data();
-        console.log('Modify task ' + $(this).text());
         $('#taskComment').val($(this).text());
         $('#modal-title').text('Modificar tasca #' + $(this).attr('data-task-id') + ' per ' + player.name);
         var taskType = $(this).attr('data-task-type');
@@ -262,7 +264,6 @@ $(document).ready(function() {
         $('#taskFreeSelector').removeClass('active');
         $('#paramTask').removeClass('active');
         $('#paramFree').removeClass('active');
-        console.log(taskType);
         if (taskType == 'P') {
             // Show panel for parametrized tasks
             $('#taskParamSelector').addClass('active');
@@ -277,7 +278,6 @@ $(document).ready(function() {
         // Fill the modal
         $('#playerId').val(player.id);
         $('#taskId').val($(this).attr('data-task-id'));
-        console.log('Change the station for' + stationId);
         $('#stationSelect').val(stationId);
         refreshExercises(exerciseId);
         $('#numSets').val(taskSets);
diff --git a/chronojumpserver/js/stations.js b/chronojumpserver/js/stations.js
index dd24c98..db3dddc 100644
--- a/chronojumpserver/js/stations.js
+++ b/chronojumpserver/js/stations.js
@@ -20,55 +20,92 @@
 
 
 /* Show stationModalForm to create a new station */
-$('#btnShowStationModalForm').on('click', function() {
+$('#btnShowStationModalForm').on('click', function()
+{
+  $('stationId').val('-1');
+  $('#stationName').val('');
+  $('#stationType').val('G');
+  $('#btnAddModifyStation').text('Afegir');
+  $('#btnDeleteStation').addClass('hide');
   $('#stationModalForm').modal();
 });
 
-/* Add / Modify or Delete stations */
-$('#btnAddStation').on('click', function() {
+
+
+/* Add or Modify stations */
+$('#btnAddModifyStation').on('click', function() {
+  var stationId = $('#stationId').val();
   var stationName = $('#stationName').val();
   var stationType = $('#stationType').val();
   // Hide the modal form
 
   $.ajax({
-      url: '/api/v1/stations',
+      url: '/api/v1/station',
       method: 'PUT',
       data: {
-          stationId: -1,
+          stationId: stationId,
           stationName: stationName,
           stationType: stationType
       }
   }).done(function(data) {
-      var table = $('#players').DataTable();
-      table.ajax.reload(null, false);
+
       $('#stationModalForm').modal('hide');
-      // Reload the page
-      window.location.reload(false);
+      var table = $('#stations').DataTable();
+      table.ajax.reload(null, false);
   }).fail(function(xhr, status, error){
       var err = eval("(" + xhr.responseText + ")");
       alert(err.msg);
   });
 });
 
+/* Delete the station via Ajax .*/
+$('#btnDeleteStation').on('click', function() {
+    /* TODO: Implement Confirmation */
+    var stationId = $('#stationId').val();
+    $.ajax({
+        url: '/api/v1/station',
+        method: 'DELETE',
+        data: {
+            stationId: stationId
+        }
+    }).done(function(data) {
+        $('#stationModalForm').modal('hide');
+        var table = $('#stations').DataTable();
+        table.ajax.reload(null, false);
+    }).fail(function(xhr, status, error){
+        var err = eval("(" + xhr.responseText + ")");
+        alert(err.msg);
+    });
+});
+
+
 /* Show execiseModalForm to create a new exercise */
-$('#btnShowExerciseModalForm').on('click', function() {
-  $('#exerciseModalForm').modal();
+$('#btnShowExerciseModalForm').on('click', function()
+{
+   $('#exerciseId').val('-1');
+   $('#exerciseName').val('');
+   $('#exercisePercentBodyMassDisplaced').val('0');
+   $('#btnAddModifyExercise').text('Afegir');
+   $('#btnDeleteExercise').addClass('hide');
+   $('#exerciseModalForm').modal();
 });
 
 
 /* Add / Modify or Delete stations */
-$('#btnAddExercise').on('click', function() {
+$('#btnAddModifyExercise').on('click', function() {
 
+  var exerciseId = $('#exerciseId').val();
   var name = $('#exerciseName').val();
   var percentBodyMassDisplaced = $('#exercisePercentBodyMassDisplaced').val();
   // Hide the modal form
-
+  var stationId = $('#selectedStationId').val();
+  console.log('The selected station is ' + stationId);
   $.ajax({
-      url: '/api/v1/exercise/add',
+      url: '/api/v1/exercise',
       method: 'PUT',
       data: {
-          id: -1,
-          stationId: getStationSelected(),
+          id: exerciseId,
+          stationId: stationId,
           name: name,
           percentBodyMassDisplaced: percentBodyMassDisplaced
       }
@@ -79,16 +116,39 @@ $('#btnAddExercise').on('click', function() {
       var table = $('#exercises').DataTable();
       table.ajax.reload(null, false);
   }).fail(function(xhr, status, error){
-      alert(error);
+      var err = eval("(" + xhr.responseText + ")");
+      alert(err.msg);
   });
 });
 
+/* Delete the exercise via Ajax .*/
+$('#btnDeleteExercise').on('click', function() {
+    /* TODO: Implement Confirmation */
+    var exerciseId = $('#exerciseId').val();
+    $.ajax({
+        url: '/api/v1/exercise',
+        method: 'DELETE',
+        data: {
+            exerciseId: exerciseId
+        }
+    }).done(function(data) {
+        $('#exerciseModalForm').modal('hide');
+        var table = $('#exercises').DataTable();
+        table.ajax.reload(null, false);
+    }).fail(function(xhr, status, error){
+        var err = eval("(" + xhr.responseText + ")");
+        alert(err.msg);
+    });
+});
+
 /* Load exercises from the station selected creating a datatable and loading
    the exercises via Ajax */
-function loadExercises(station_id, first=false) {
-    if ( first == false) {
-        $('#exercises').DataTable().destroy();
-    }
+function loadExercises(station_id) {
+    var stationTable = $('#stations').DataTable();
+    var station = stationTable.row('.selected').data();
+
+    $('#selectedStationName').text(station.name);
+    $('#selectedStationId').val(station.id);
     var table = $('#exercises').DataTable({
         "columns": [
             {
@@ -107,76 +167,132 @@ function loadExercises(station_id, first=false) {
                 data: 'percentBodyMassDisplaced',
                 title: "% Masa de cos desplaçada",
                 render: $.fn.dataTable.render.number('', ',', 2)
+            },
+            {
+                type: "html",
+                data: null,
+                title: "",
+                orderable: false,
+                render: function(val, row) {
+                    return "<button class='btn btn-primary'>Editar</button>"
+                }
             }
         ],
+        "dom" : "",
         "pageLength": 10,
         "ajax": {
             'url': "/api/v1/exercises",
             'method': 'GET',
             'data': {
-                station_id: station_id
+                station_id: station.id
             }
         },
-        "processing": true,
-        "severSide": true,
-        "searching": false,
-        "bPaginate": false,
-        "bLengthChange": false,
-        "bFilter": true,
-        "bInfo": false,
-        "bAutoWidth": false,
         "language": {
-            "lengthMenu": "Mostrant _MENU_ exercisis per pàgina",
-            "zeroRecords": "No hi han exercisis per mostrar",
-            "info": "Mostrant els exercisis _START_ a _END_ d'un total de _TOTAL_",
-            "infoEmpty": "La busqueda no ha retornat resultats",
-            "infoFiltered": "(filtrat de _MAX_ jugadors)",
-            "decimal": ",",
-            "thousands": ".",
-            "paginate": {
-                "first": '<i class="fa fa-fast-backward"></i>',
-                "last": '<i class="fa fa-fast-forward"></i>',
-                "next": '<i class="fa fa-forward"></i>',
-                "previous": '<i class="fa fa-backward"></i>'
-            },
-            "search": "Cerca:"
-        }
+            "zeroRecords": "No hi han exercicis per mostrar",
+        },
     });
 
-}
-
-/* return the station selected in this moment */
-function getStationSelected() {
-  var stationselected = $('li.list-group-item.active');
 
-  if (stationselected) {
-    return $(stationselected).attr('data-station-id');
-  } else {
-    return -1;
-  }
 
 }
 
-/* Refresh Exercises from the station selected in the list */
-$('li.list-group-item').on('click', function() {
-  if (!$(this).hasClass('active')) {
-
-    var stationId = $(this).attr('data-station-id');
-    $('li.list-group-item.active').removeClass('active');
-    $(this).addClass('active');
-    loadExercises(stationId);
-  }
-})
-
 /*
   Load Players and tasks
 */
 $(document).ready(function() {
-    var stationSelected = getStationSelected();
 
-    if (stationSelected != -1) {
-      // Load the exercises of first station in the list
-      loadExercises(stationSelected, true);
-    }
+    var stationTable = $('#stations').DataTable({
+        "columns": [
+            {
+                type: "num",
+                title: "id",
+                data: 'id',
+                visible: false
+            },
+            {
+                type: "html",
+                data: "name",
+                title: "Nom",
+                className: 'stationName'
+            },
+            {
+                type: "html",
+                data: "type",
+                title: "Tipus",
+                render: function(val) {
+                    if (val == 'I') {
+                        return 'Inercial';
+                    }else if (val == 'G') {
+                        return 'Gravitatori';
+                    } else {
+                        return 'Sprint';
+                    }
+                }
+            },
+            {
+                type: "html",
+                data: null,
+                title: "",
+                orderable: false,
+                render: function(val, row) {
+                    return "<button class='btn btn-primary'>Editar</button>"
+                }
+            }
+        ],
+        "ajax": {
+            'url': "/api/v1/stations",
+            'method': 'GET'
+        },
+        "dom" : "",
+        "language": {
+            "zeroRecords": "No hi han estacions per mostrar",
+        },
+        "initComplete": function(){
+            // set the first station as selected
+            $('#stations tbody').find('tr:first').addClass('selected');
+            // Load the exercises from this station
+            loadExercises();
+        }
+    });
+
+    $('#stations tbody').on( 'click', 'td.stationName', function () {
+        var tr = $(this).parent();
+        if ( !$(tr).hasClass('selected') ) {
+            stationTable.$('tr.selected').removeClass('selected');
+            $(tr).addClass('selected');
+            // Destroy the previous exercise table
+            $('#exercises').DataTable().destroy();
+            // Call load exercise function
+            loadExercises();
+        }
+
+
+    } );
+
+    $('#stations').on('click', 'button', function() {
+        var station = stationTable.row($(this).parents('tr')).data();
+        $('#stationId').val(station.id);
+        $('#stationName').val(station.name);
+        $('#stationType').val(station.type);
+        $('#btnAddModifyStation').text('Modificar');
+        $('#btnDeleteStation').removeClass('hide');
+        $('#stationModalForm').modal();
+    });
+
+
+    $('#exercises').on('click', 'button', function() {
+        var table = $('#exercises').DataTable();
+        var exercise = table.row($(this).parents('tr')).data();
+        $('#exerciseId').val(exercise.id);
+        $('#exerciseName').val(exercise.name);
+        $('#exercisePercentBodyMassDisplaced').val(exercise.percentBodyMassDisplaced);
+        $('#btnAddModifyExercise').text('Modificar');
+        $('#btnDeleteExercise').removeClass('hide');
+        $('#exerciseModalForm').modal();
+    });
+
+
+
+
 
 });
diff --git a/chronojumpserver/models.py b/chronojumpserver/models.py
index 2bec6c4..cf34a74 100755
--- a/chronojumpserver/models.py
+++ b/chronojumpserver/models.py
@@ -1,10 +1,11 @@
 # -*- coding: utf-8 -*-
 from chronojumpserver.database import Base, db_session
 from datetime import datetime
-from sqlalchemy import Column, Integer, String, Float, DateTime, Enum, ForeignKey, UniqueConstraint
-from sqlalchemy.types import Boolean, Enum
+from sqlalchemy import Column, Integer, String, Float, DateTime,  ForeignKey, UniqueConstraint
+from sqlalchemy.types import Boolean
 from sqlalchemy.orm import relationship
 
+
 class HelperMixin(object):
 
     id = Column(Integer, primary_key=True)
@@ -35,14 +36,16 @@ class Person(HelperMixin, Base):
     imageName = Column(String(50))
     results = relationship("ResultEncoder",
                            order_by="desc(ResultEncoder.dt)",
-                           primaryjoin="ResultEncoder.personId==Person.id")
+                           primaryjoin="ResultEncoder.personId==Person.id",
+                           cascade="save-update, merge, delete")
     tasks = relationship("Task",
-                           order_by="desc(Task.ts)",
-                           primaryjoin="Task.personId==Person.id")
+                         order_by="desc(Task.ts)",
+                         primaryjoin="Task.personId==Person.id",
+                         cascade="save-update, merge, delete")
     active_tasks = relationship("Task",
-                           order_by="desc(Task.ts)",
-                           primaryjoin="and_(Task.personId==Person.id,"
-                                       "Task.done==0)")
+                                order_by="desc(Task.ts)",
+                                primaryjoin="and_(Task.personId==Person.id,"
+                                "Task.done==0)")
 
     def __init__(self, name=None, weight=None, height=None, rfid=None,
                  imageName=None):
@@ -69,13 +72,11 @@ class Person(HelperMixin, Base):
         """Representation of the object."""
         return '<Person %r>' % (self.name,)
 
-
     def add(self):
         db_session.add(self)
         db_session.commit()
 
 
-
 class Station(HelperMixin, Base):
     """Station model.
 
@@ -87,18 +88,22 @@ class Station(HelperMixin, Base):
     """
     __tablename__ = 'station'
     name = Column(String(30), unique=True)
-    type = Column(String(1), nullable=True) # G - gravitory, I - inertial, S - sprint
+    # G - gravitory, I - inertial, S - sprint
+    type = Column(String(1), nullable=True)
 
     # Relationships
     results = relationship("ResultEncoder",
                            order_by="desc(ResultEncoder.dt)",
-                           primaryjoin="ResultEncoder.stationId==Station.id")
+                           primaryjoin="ResultEncoder.stationId==Station.id",
+                           cascade="save-update, merge, delete")
     tasks = relationship("Task",
-                           order_by="desc(Task.ts)",
-                           primaryjoin="Task.stationId==Station.id")
+                         order_by="desc(Task.ts)",
+                         primaryjoin="Task.stationId==Station.id",
+                         cascade="save-update, merge, delete")
     exercises = relationship("Exercise",
-                            order_by="asc(Exercise.name)",
-                            primaryjoin="Exercise.stationId==Station.id")
+                             order_by="asc(Exercise.name)",
+                             primaryjoin="Exercise.stationId==Station.id",
+                             cascade="save-update, merge, delete")
 
     def __init__(self, name=None, type=None):
         self.name = name
@@ -108,7 +113,8 @@ class Station(HelperMixin, Base):
     def serialize(self):
         return {
             'id':        self.id,
-            'name':      self.name.decode('utf-8')
+            'name':      self.name.decode('utf-8'),
+            'type':      self.type
         }
 
     def __repr__(self):
@@ -116,7 +122,6 @@ class Station(HelperMixin, Base):
         return '<Station %r>' % (self.name,)
 
 
-
 class Exercise(HelperMixin, Base):
     """Exercise model.
 
@@ -130,8 +135,8 @@ class Exercise(HelperMixin, Base):
     """
     __tablename__ = 'exercise'
     __table_args__ = (
-            UniqueConstraint('name', 'stationId'),
-            )
+        UniqueConstraint('name', 'stationId'),
+    )
     # Columns
     name = Column(String(30))
     stationId = Column('stationId', ForeignKey('station.id'), nullable=False)
@@ -141,19 +146,22 @@ class Exercise(HelperMixin, Base):
     uniqueNameByStation = UniqueConstraint('name', 'stationId')
 
     # Relationships
-    station = relationship(Station, primaryjoin= stationId == Station.id)
+    station = relationship(Station, primaryjoin=stationId == Station.id)
     results = relationship("ResultEncoder",
                            order_by="desc(ResultEncoder.dt)",
-                           primaryjoin="ResultEncoder.exerciseId==Exercise.id")
+                           primaryjoin="ResultEncoder.exerciseId==Exercise.id",
+                           cascade="save-update, merge, delete")
     tasks = relationship("Task",
-                           order_by="desc(Task.ts)",
-                           primaryjoin="Task.exerciseId==Exercise.id")
+                         order_by="desc(Task.ts)",
+                         primaryjoin="Task.exerciseId==Exercise.id",
+                         cascade="save-update, merge, delete")
 
     def __init__(self, name=None, stationId=None, percentBodyMassDisplaced=None):
         """Initialize the object."""
         self.name = name
         if stationId is not None:
-            self.station = Station.query.filter(Station.id == stationId).first()
+            self.station = Station.query.filter(
+                Station.id == stationId).first()
         self.stationId = stationId
         self.percentBodyMassDisplaced = percentBodyMassDisplaced
 
@@ -180,7 +188,7 @@ class Task(Base):
     """
     __tablename__ = "task"
     id = Column(Integer, primary_key=True)
-    type = Column(String(1)) # F - Free, P - Parametrized
+    type = Column(String(1))  # F - Free, P - Parametrized
     ts = Column(DateTime, default=datetime.now)
     personId = Column('personId', ForeignKey('person.id'))
     person = relationship(Person, primaryjoin=personId == Person.id)
@@ -199,7 +207,7 @@ class Task(Base):
 
     def __init__(self, type=None, ts=None, stationId=None, personId=None,
                  exerciseId=None, nreps=-1, sets=-1, load=-1, speed=-1,
-                 percentMaxSpeed=-1,laterality=None, comment="", done=False):
+                 percentMaxSpeed=-1, laterality=None, comment="", done=False):
         """Initialize a Task object."""
         """laterality can have these values:
                 'RL' is done by both arms or legs at the same time
@@ -236,7 +244,7 @@ class Task(Base):
             'stationId':   self.stationId,
             'stationName': self.station.name,
             'exerciseId':  self.exerciseId,
-            'exerciseName':self.exercise.name,
+            'exerciseName': self.exercise.name,
             'nreps':       self.nreps,
             'load':        self.load,
             'laterality':  self.laterality,
@@ -353,6 +361,7 @@ class ResultEncoder(Base):
         """Representation od the object."""
         return '<Result %d>' % (self.id)
 
+
 class ResultSprint(Base):
     __tablename__ = 'resultSprint'
     id = Column('id', Integer, primary_key=True)
@@ -384,15 +393,15 @@ class ResultSprint(Base):
     def serialize(self):
         """Object serialization (Json)."""
         return {
-            'id' : self.id,
-            'dt' : self.dt,
+            'id': self.id,
+            'dt': self.dt,
             'personId': self.personId,
             'personName': self.person.name,
-            'distances' : self.distances,
-            'times' : self.times,
-            'k' : self.k,
-            'vmax' : self.vmax,
-            'amax' : self.amax,
-            'fmax' : self.fmax,
-            'pmax' : self.pmax
+            'distances': self.distances,
+            'times': self.times,
+            'k': self.k,
+            'vmax': self.vmax,
+            'amax': self.amax,
+            'fmax': self.fmax,
+            'pmax': self.pmax
         }
diff --git a/chronojumpserver/static/style.css b/chronojumpserver/static/style.css
index 9aef39c..89fb79f 100755
--- a/chronojumpserver/static/style.css
+++ b/chronojumpserver/static/style.css
@@ -64,9 +64,17 @@ body.home {
     vertical-align: middle;
 }
 
-#btnShowStationModalForm, #btnShowExerciseModalForm {
+#stations td {
+    vertical-align: middle;
+}
+
+#stations tr.selected {
+    font-weight: bold;
+}
+
+/*#btnShowStationModalForm, #btnShowExerciseModalForm {
     position: relative;
     top: -23px;
     right: -10px;
     float: right;
-}
+}*/
diff --git a/chronojumpserver/templates/station_list.html b/chronojumpserver/templates/station_list.html
index 5184f94..e02979a 100644
--- a/chronojumpserver/templates/station_list.html
+++ b/chronojumpserver/templates/station_list.html
@@ -5,32 +5,22 @@
 {% endblock %}
 
 {% block content %}
-<div class="page-header">
-    <h1>Estacions i Exercicis</h1>
-</div>
 <div class="row">
-    <div class="col-sm-4">
-        <div class="panel panel-default">
-            <div class="panel-heading">
-                <h3 class="panel-title">Estacions</h3><button id="btnShowStationModalForm" class="btn 
btn-default btn-sm">Afegir Estació</button>
-            </div>
-            <ul class="list-group">
-                {% for station in stations %}
-                <li data-station-id="{{station.id}}" class="list-group-item{% if loop.first %} active{% 
endif %}">{{station.name}} ({{station.type}})</li>
-                {% endfor %}
-            </ul>
+    <div class="col-sm-5">
+        <div class="page-header">
+            <h1>Estacions</h1>
         </div>
+        <button id="btnShowStationModalForm" class="btn btn-primary">Nova Estació</button>
+        <table id="stations" class="table table-hovered">
+        </table>
     </div>
-    <div class="col-sm-8">
-        {% if stations|length > 0 %}
-        <div class="panel panel-default">
-            <div class="panel-heading">
-                <h3 class="panel-title">Exercicis de l'Estació</h3><button id="btnShowExerciseModalForm" 
class="btn btn-default btn-sm">Afegir Exercici</button>
-            </div>
-            <table id="exercises" class="table table-hovered">
-               </table>
+    <div class="col-sm-7">
+        <div class="page-header">
+            <h1>Exercicis <small id="selectedStationName"></small></h1>
+        </div>
+        <button id="btnShowExerciseModalForm" class="btn btn-primary">Nou Exercici</button>
+        <table id="exercises" class="table table-hovered"></table>
         </div>
-        {% endif %}
     </div>
 </div>
 <div id="stationModalForm" class="modal fade" tabindex="-1" role="dialog">
@@ -42,6 +32,7 @@
                        </div>
                        <div class="modal-body">
         <form class="form">
+            <input type="hidden" id="stationId" value="-1" />
             <div class="form-group">
               <label for="stationName" class="control-label">Nom</label>
               <input id="stationName" name="stationName" type="text" class="form-control"/>
@@ -58,7 +49,8 @@
                        </div> <!-- .modal-body -->
                        <div class="modal-footer">
                                <button type="button" class="pull-left btn btn-default" 
data-dismiss="modal">Cancelar</button>
-                               <button id="btnAddStation" type="button" class="pull-right btn 
btn-primary">Afegir</button>
+                               <button id="btnAddModifyStation" type="button" class="pull-right btn 
btn-primary">Afegir</button>
+                <button id="btnDeleteStation" type="button" class="pull-right btn 
btn-danger">Eliminar</button>
                        </div>
                </div>
                <!-- /.modal-content -->
@@ -74,19 +66,22 @@
                        </div>
                        <div class="modal-body">
         <form class="form">
+            <input type="hidden" id="selectedStationId" />
+            <input type="hidden" id="exerciseId" />
             <div class="form-group">
               <label for="exerciseName" class="control-label">Nom</label>
               <input id="exerciseName" name="exerciseName" type="text" class="form-control"/>
             </div>
             <div class="form-group">
               <label for="exercisePercentBodyMassDisplaced" class="control-label">Masa de cos 
desplaçada</label>
-              <input id="exercisePercentBodyMassDisplaced" name="exercisePercentBodyMassDisplaced" 
type="number" class="form-control"/>
+              <input id="exercisePercentBodyMassDisplaced" name="exercisePercentBodyMassDisplaced" 
type="number" class="form-control" min="0" max="100" value="0"/>
             </div>
         </form>
                        </div> <!-- .modal-body -->
                        <div class="modal-footer">
                                <button type="button" class="pull-left btn btn-default" 
data-dismiss="modal">Cancelar</button>
-                               <button id="btnAddExercise" type="button" class="pull-right btn 
btn-primary">Afegir</button>
+                               <button id="btnAddModifyExercise" type="button" class="pull-right btn 
btn-primary">Afegir</button>
+                <button id="btnDeleteExercise" type="button" class="pull-right btn 
btn-danger">Eliminar</button>
                        </div>
                </div>
                <!-- /.modal-content -->


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]