Displaying differences for changeset
 
display as  

src/moplay/js/multiobj.js

@@ -5,8 +5,8 @@
  */
 
 // methods and available options from MOEA Framework 2.4 user manual
-var REAL_DIV = '<div id="{x}_extra" class="param-half"><input id="{x}_lower" type="text" class="param-half margin-small" placeholder="Lower Bound" value="{lower}"></input><input id="{x}_upper" type="text" class="param-half margin-small" placeholder="Upper Bound" value="{upper}"></input></div>';
-var BINARY_DIV = '<div id="{x}_extra" class="param-half"><input id="{x}_nbits" type="text" class="param-half margin-small" placeholder="No. Bits" value="{nbits}"></input></div>';
+var REAL_DIV = '<div id="{x}_extra" class="param-half"><input id="{x}_lower" type="text" class="param-half margin-small" placeholder="Lower Bound" title="Lower Bound of Variable" value="{lower}"></input><input id="{x}_upper" type="text" class="param-half margin-small" placeholder="Upper Bound" title="Upper Bound of Variable" value="{upper}"></input></div>';
+var BINARY_DIV = '<div id="{x}_extra" class="param-half"><input id="{x}_nbits" type="text" class="param-half margin-small" placeholder="No. Bits" title="Number of Bits in Variable" value="{nbits}"></input></div>';
 var BOOLEAN_DIV = '<div id="{x}_extra" class="param-half"></div>';
 var TABLE_DIV = '<table id="output_table" class="display" cellspacing="0" width="100%"><thead><tr>{headers}</tr></thead></table>';
 var VARTYPE_DIV = {
@@ -458,16 +458,14 @@
     "use strict";
 
     // update variables and options
-    var x_i, x_name, x_type, var_elem, var_div, v,
-        $var_elem,
-        $elem = $('#' + elem_id);
+    var $elem = $('#' + elem_id);
 
     // remove all previous variables
     $elem.empty();
 
     // update with new variables
-    for (x_i in variables) {
-        addVariable(elem_id, x_i, method, variables[x_i]);
+    for (var i = 0; i < variables.length; i++) {
+        addVariable(elem_id, i, method, variables[i]);
     }
 
 }
@@ -475,19 +473,20 @@
 /**
  * Fill the select elements
  */
-function fillMethods(elem_id, variables, method) {
+function fillMethods(elem_id, method) {
     "use strict";
 
     // element
-    var elem = document.getElementById(elem_id),
-        i;
+    var elem = document.getElementById(elem_id);
 
     // remove previous options
     elem.length = 0;
 
     // fill methods select element
-    for (i in METHODS) {
-        elem.options[elem.length] = new Option(i, i);
+    for (var methodName in METHODS) {
+        if (METHODS.hasOwnProperty(methodName)) {
+            elem.options[elem.length] = new Option(methodName, methodName);
+        }
     }
 
     elem.value = method;
@@ -496,13 +495,14 @@
 }
 
 function getCSIPParam(csipResponse, paramName) {
-
-    for (var i in csipResponse.result) {
+    "use strict";
+    var i;
+    for (i = 0; i < csipResponse.result.length; i++) {
         if (csipResponse.result[i].name === paramName) {
             return csipResponse.result[i].value;
         }
     }
-    for (var i in csipResponse.parameter) {
+    for (i = 0; i < csipResponse.parameter.length; i++) {
         if (csipResponse.parameter[i].name === paramName) {
             return csipResponse.parameter[i].value;
         }
@@ -511,6 +511,8 @@
 }
 
 function getCSIPRequest() {
+    "use strict"
+
     return {
         "metainfo": {
             "keep_results": 1200000
@@ -521,7 +523,7 @@
                 "value": $('#problem_name').val()
             },
             {
-                "name": "public",
+                "name": "is_public",
                 "value": document.getElementById('problem_public').checked
             },
             {
@@ -554,7 +556,7 @@
             },
             {
                 "name": "vars",
-                "value": variables
+                "value": getVariables('variables')
             }
         ]
     };
@@ -587,8 +589,24 @@
     return spinner;
 }
 
+function deleteProblem(problemID) {
+    "use strict";
+    $.ajax({
+        url: '/problem',
+        type: 'DELETE',
+        contentType: "application/json; charset=utf-8",
+        dataType: 'json',
+        data: JSON.stringify({ id: problemID }),
+        success: function(response) {
+            if (response.status !== 'success') {
+                alert('Data not deleted for some reason!');
+            }
+        }
+    })
+}
+
 // open the problems list dialog
-function openDialog() {
+function openDialog(nextPage) {
     "use strict";
 
     // open the window
@@ -598,11 +616,12 @@
     var spinner = startSpinner('openModalInner');
 
     // get the data to send
-    var cursor_val = $('#cursor').val();
+    var cursor = $('#cursor');
+    var cursor_val = cursor.val();
     var data = {
         limit: 20
     };
-    if (cursor_val !== '') {
+    if (cursor_val !== '' && typeof nextPage !== 'undefined' && nextPage) {
         data.cursor = cursor_val;
     }
 
@@ -621,17 +640,40 @@
             if (typeof response.problems !== 'undefined') {
 
                 if (response.problems.length == 0) {
+
                     problemsList.append('<span>No optimization problems saved yet!</span>');
+
                 } else {
+
+                    if (response.cursor !== '') {
+                        cursor.val(response.cursor);
+                    }
                     response.problems.forEach( function(problem) {
+
+                        // problem name and link
                         var button = document.createElement('a');
                         button.className = "a-button-type padding-10";
                         button.setAttribute('href', "/?id=" + problem.id);
                         button.innerHTML = problem.name;
+
+                        // problem name
+                        var deleteButton = document.createElement('button');
+                        deleteButton.className = "button-type delete-button";
+                        deleteButton.onclick = function() {
+                            deleteProblem(problem.id);
+                            button.remove();
+                            deleteButton.remove();
+                            // problemsList.remove(deleteButton);
+                        };
+                        deleteButton.innerHTML = "X";
+
+                        // add to the problem list
                         problemsList.append(button);
+                        problemsList.append(deleteButton);
                     });
                 }
 
+            } else {
             }
 
             spinner.stop();
@@ -645,8 +687,7 @@
     
     console.log('Attempting run...');
 
-    var variables = getVariables('variables'),
-        request = getCSIPRequest(),
+    var request = getCSIPRequest(),
         spinner = startSpinner('chartModalInner');
 
     // print request
@@ -845,8 +886,6 @@
     $.ajax({
         url: '/problem_id',
         type: 'GET',
-        contentType: "application/json; charset=utf-8",
-        dataType: "json",
         async: false,
         data: {
             name: $('problem_name').val()

src/moplay/main.py

@@ -17,7 +17,10 @@
         if key is not None:
             problem = ndb.Key(urlsafe=key).get()
         else:
-            problem = Problem.from_json(env.get_template('Kursawe.json').render())
+            problem = None
+
+        # else:
+        #     problem = Problem.from_json(env.get_template('Kursawe.json').render())
 
         # get the user (login and logout urls)
         user = users.get_current_user()
@@ -29,7 +32,6 @@
 
         # render the page
         index = env.get_template('index.html').render(problem=problem,
-                                                      vars=problem.vars_json(),
                                                       has_user=has_user,
                                                       user_url=user_url)
         self.response.write(index)

src/moplay/models.py

@@ -186,6 +186,8 @@
         # check existence of problem in datastore
         params = d["parameter"]
         name = get_param(params, 'name')
+        if not name:
+            return None
         if owner_id is not None and Problem.exists_by_name(name, owner_id):
             p = Problem.retrieve_by_name(name, owner_id)
         else:
@@ -195,7 +197,7 @@
                 p.owner_id = owner_id
                 p.set_key()
 
-        p.is_public = get_param(params, 'is_public', False)
+        p.is_public = get_param(params, 'is_public')
         p.method = get_param(params, 'method')
         p.max_evals = get_param(params, 'max_evals')
         p.population = get_param(params, 'population')

src/moplay/problems.py

@@ -1,6 +1,5 @@
 import json
 import webapp2
-from templates import env
 from models import Problem
 from google.appengine.api import users
 from google.appengine.datastore.datastore_query import Cursor
@@ -17,7 +16,7 @@
 
         if Problem.exists(problem_id):
             problem = Problem.retrieve(problem_id)
-            if problem.public:
+            if problem.is_public:
                 self.response.write(problem.to_json())
 
             else:
@@ -30,6 +29,8 @@
                         self.error(403)
                 else:
                     self.redirect('/')
+        else:
+            self.error(404)
 
     def post(self):
         """
@@ -40,11 +41,46 @@
         if user:
 
             problem = Problem.from_json(self.request.body, owner_id=user.user_id())
-            problem.put()
+            if problem:
+                problem.put()
 
         else:
             self.error(403)
 
+    def delete(self):
+        """
+        Delete a problem from the datastore
+        """
+
+        # get parameters (not able to get these with self.request.get for some reason)
+        d = json.loads(self.request.body)
+        if 'id' not in d:
+            self.response.set_status(400, 'Need to add ID to request!')
+            self.response.write(json.dumps({'status': 'failed'}))
+            return
+
+        # find and delete the entity
+        problem_id = d['id']
+        if problem_id and Problem.exists(problem_id):
+            user = users.get_current_user()
+            if user:
+                owner_id = user.user_id()
+                problem = Problem.retrieve(problem_id)
+                if problem.is_public and users.is_current_user_admin():
+                    problem.key.delete()
+                    self.response.write(json.dumps({'status': 'success'}))
+
+                elif owner_id == problem.owner_id:
+                    problem.key.delete()
+                    self.response.write(json.dumps({'status': 'success'}))
+
+                else:
+                    self.error(403)
+            else:
+                self.error(403)
+        else:
+            self.error(404)
+
 
 class ProblemIDHandler(webapp2.RequestHandler):
 
@@ -58,7 +94,7 @@
 
         if user and Problem.exists_by_name(name, user.user_id()):
             problem = Problem.retrieve_by_name(name, user.user_id())
-            if problem.public or problem.owner_id == user.user_id():
+            if problem.is_public or problem.owner_id == user.user_id():
                 self.response.write(json.dumps({
                     'id': problem.key.urlsafe()
                 }))
@@ -76,7 +112,7 @@
         user = users.get_current_user()
         if user:
 
-            limit = int(self.request.get('limit', 20))
+            limit = int(self.request.get('limit', 5))
             cursor = self.request.get('cursor')
 
             q = Problem.query(Problem.owner_id == user.user_id()).order(-Problem.date_modified)
@@ -86,7 +122,7 @@
                 problems, next_cursor, more = q.fetch_page(limit)
             self.response.write(json.dumps({
                 'limit': limit,
-                'cursor': next_cursor.urlsafe(),
+                'cursor': next_cursor.urlsafe() if next_cursor else '',
                 'more': more,
                 'problems': [{
                     'name': p.name,

src/moplay/stylesheets/main.css

@@ -366,6 +366,13 @@
     background-size: 29px;
 }
 
+.delete-button {
+    margin-left: -10px;
+    border-radius: 20px;
+    padding: 0;
+    background: #333;
+}
+
 /*
  * MISC
  */
@@ -399,4 +406,8 @@
 
 .fill-height {
     max-height: 100%;
+}
+
+.x-large-text {
+    font-size: x-large;
 }
\ No newline at end of file

src/moplay/templates/index.html

@@ -43,9 +43,9 @@
                 </div>
                 <div class="flex-right">
                     {% if has_user %}
-                        {% if problem.key %}
-                        <button onclick="window.prompt('Press Ctrl+C to Copy the link below!', 'http://' + location.host + '/?id={{ problem.key.urlsafe() }}');" class="button-type link-button" title="Get Link to This Optimization Problem!"></button>
-                        {% endif %}
+                    {% if problem and problem.key %}
+                    <button id="public_link" onclick="window.prompt('Press Ctrl+C to Copy the link below!', 'http://' + location.host + '/?id={{ problem.key.urlsafe() }}');" class="button-type link-button" title="Get Link to This Optimization Problem!"></button>
+                    {% endif %}
                     <button onclick="saveCode();" class="button-type save-button" title="Save this Optimization Problem"></button>
                     <a href="{{ user_url }}" class="a-button-type button-padding-extra">Sign Out</a>
                     {% else %}
@@ -57,16 +57,16 @@
     </div>
 
     <div id="parameters" class="left-panel">
-        <div id="parameter_rows" class="flex-container">
+        <div id="parameter_rows" class="flex-container flex-wrap">
 
             <h2 class="param-row margin-top">Optimization Problem</h2>
 
             <div class="param-row">
-                <input id="problem_name" type="text" class="margin-small param-full auto-margin" value="{{ problem.name }}"/>
+                <input id="problem_name" type="text" class="margin-small param-full auto-margin" placeholder="Name of the Optimization Problem" title="Name of the Optimization Problem" value="{{ problem.name if problem else '' }}"/>
             </div>
 
             <div class="param-row">
-                <input id="problem_public" type="checkbox" class="" {{ "checked" if problem.public else "" }}/>
+                <input id="problem_public" type="checkbox" class="" onchange="console.log($('#problem_public').is(':checked')); if ($('#problem_public').is(':checked')) { $('#public_link').show(); } else { $('#public_link').hide(); }" {{ ("checked" if problem.is_public else '') if problem else '' }}/>
                 Make Public
             </div>
 
@@ -80,12 +80,12 @@
 
             <div class="param-row">
                 <div class="param-half">Max Evaluations:</div>
-                <input id="max_evals" type="text" class="param-half margin-small" value="{{ problem.max_evals }}"/>
+                <input id="max_evals" type="text" placeholder="Maximum Evaluations" title="Maximum Evaluations" class="param-half margin-small" value="{{ problem.max_evals if problem else '' }}"/>
             </div>
 
             <div class="param-row">
                 <div class="param-half">Population Size:</div>
-                <input id="population" type="text" class="param-half margin-small" value="{{ problem.population }}"/>
+                <input id="population" type="text" placeholder="Population Size" title="Population Size" class="param-half margin-small" value="{{ problem.population if problem else '' }}"/>
             </div>
 
 
@@ -93,28 +93,28 @@
 
             <div class="param-row">
                 <div class="param-half">No. Decisions:</div>
-                <input id="nDecisions" type="text" class="param-half margin-small" value="{{ problem.n_decisions }}"/>
+                <input id="nDecisions" type="text" placeholder="Number of Decision Variables" title="Number of Decision Variables" class="param-half margin-small" value="{{ problem.n_decisions if problem else '' }}"/>
             </div>
 
             <div class="param-row">
                 <div class="param-half">No. Objectives:</div>
-                <input id="nObjectives" type="text" class="param-half margin-small" value="{{ problem.n_objectives }}"/>
+                <input id="nObjectives" type="text" placeholder="Number of Objective Values" title="Number of Objective Values" class="param-half margin-small" value="{{ problem.n_objectives if problem else '' }}"/>
             </div>
 
             <div class="param-row">
                 <div class="param-half">No. Constraints:</div>
-                <input id="nConstraints" type="text" class="param-half margin-small" value="{{ problem.n_constraints }}"/>
+                <input id="nConstraints" type="text" placeholder="Number of Constraints" title="Number of Constraints" class="param-half margin-small" value="{{ problem.n_constraints if problem else '' }}"/>
             </div>
 
             <h2 class="param-row">Variables</h2>
 
-            <div id="variables" class="flex-container"></div>
+            <div id="variables" class="flex-container flex-wrap"></div>
 
         </div>
 
     </div>
 
-    <div id="editor">{{ problem.code.strip()|safe }}</div>
+    <div id="editor">{{ (problem.code.strip() if problem else '')|safe  }}</div>
 
     <div id="chartModal" class="chartModal">
         <div id="chartModalInner">
@@ -126,13 +126,18 @@
     <div id="openModal" class="openModal">
         <div id="openModalInner">
             <div class="flex-container-v">
-                <div class="param-full flex-fixed">Header</div>
+                <div class="param-full flex-fixed flex-center x-large-text margin-10">My Problems</div>
                 <div class="flex-fill-v problems-list-container">
                     <div id="problemsList" class="flex-container flex-center flex-wrap">
 
                     </div>
                 </div>
-                <div class="param-full flex-fixed">Footer</div>
+                <div class="param-full flex-fixed flex-center x-large-text margin-10">Public Problems</div>
+                <div class="flex-fill-v problems-list-container">
+                    <div id="publicProblemsList" class="flex-container flex-center flex-wrap">
+
+                    </div>
+                </div>
                 <a href="#close" title="Close" class="close">X</a>
             </div>
         </div>
@@ -146,13 +151,21 @@
 <script>
 
     // set up the left pane
+    fillMethods('method', "{{ problem.method if problem else 'NSGAII' }}");
+
+    {% if problem %}
+
+    // add the button for retrieving the public link if possible
+    if ({{ 'false' if problem.is_public else 'true' }}) {
+        $('#public_link').hide();
+    }
 
     // variables
-    var variables = {{ vars|safe }};
+    var variables = {{ problem.vars_json()|safe }};
 
     // populate the select elements
-    fillMethods('method', variables, "{{ problem.method }}");
     fillVariables('variables', variables, "{{ problem.method }}");
+    {% endif %}
 
     // set event listeners
     var ndec = document.getElementById('nDecisions');
@@ -169,7 +182,7 @@
 
             // add some variable elements
             for (i = 0; i < ndec - var_cnt; i++) {
-                addVariable('variables', var_cnt + i, "{{ problem.method }}", null);
+                addVariable('variables', var_cnt + i, "{{ problem.method if problem else 'NSGAII' }}", null);
             }
 
         } else if (var_cnt > ndec) {