Hi,

Please find attached patch to fix the issues in pgAgent's Schedule and Step
module.

1) Error on clicking SQL panel when Schedule OR Step node is selected in
browser.
RM#1888

2) Error while dropping Schedule OR Step node.
RM#1889

3) Newly created Schedule/Step node was not displaying in browser.
RM#1890

Other misc changes are for PEP-8.

--
Regards,
Murtuza Zabuawala
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company
diff --git a/web/pgadmin/browser/server_groups/servers/pgagent/__init__.py 
b/web/pgadmin/browser/server_groups/servers/pgagent/__init__.py
index 912ed02..bd6e248 100644
--- a/web/pgadmin/browser/server_groups/servers/pgagent/__init__.py
+++ b/web/pgadmin/browser/server_groups/servers/pgagent/__init__.py
@@ -345,7 +345,7 @@ SELECT EXISTS(
         status, res = self.conn.execute_dict(
             render_template(
                 "/".join([self.template_path, 'nodes.sql']),
-                jid=res, conn=self.conn
+                jid=jid, conn=self.conn
             )
         )
 
diff --git 
a/web/pgadmin/browser/server_groups/servers/pgagent/schedules/__init__.py 
b/web/pgadmin/browser/server_groups/servers/pgagent/schedules/__init__.py
index 51ae632..fefcc49 100644
--- a/web/pgadmin/browser/server_groups/servers/pgagent/schedules/__init__.py
+++ b/web/pgadmin/browser/server_groups/servers/pgagent/schedules/__init__.py
@@ -12,7 +12,7 @@
 import json
 from functools import wraps
 
-from flask import render_template, make_response, request
+from flask import render_template, make_response, request, jsonify
 from flask_babel import gettext
 from pgadmin.browser.collection import CollectionNodeModule
 from pgadmin.browser.utils import PGChildNodeView
@@ -64,7 +64,8 @@ class JobScheduleModule(CollectionNodeModule):
     @property
     def script_load(self):
         """
-        Load the module script for language, when any of the database nodes 
are initialized.
+        Load the module script for schedule, when any of the pga_job
+        nodes are initialized.
 
         Returns: node type of the server module.
         """
@@ -78,9 +79,9 @@ class JobScheduleView(PGChildNodeView):
     """
     class JobScheduleView(PGChildNodeView)
 
-        A view class for JobSchedule node derived from PGChildNodeView. This 
class is
-        responsible for all the stuff related to view like updating language
-        node, showing properties, showing sql in sql pane.
+        A view class for JobSchedule node derived from PGChildNodeView.
+        This class is responsible for all the stuff related to view like
+        updating schedule node, showing properties, showing sql in sql pane.
 
     Methods:
     -------
@@ -97,20 +98,28 @@ class JobScheduleView(PGChildNodeView):
         manager,conn & template_path properties to self
 
     * list()
-      - This function is used to list all the language nodes within that 
collection.
+      - This function is used to list all the schedule nodes within that
+      collection.
 
     * nodes()
-      - This function will used to create all the child node within that 
collection.
-        Here it will create all the language node.
+      - This function will used to create all the child node within that
+      collection. Here it will create all the schedule node.
 
     * properties(gid, sid, jid, jscid)
-      - This function will show the properties of the selected language node
+      - This function will show the properties of the selected schedule node
 
     * update(gid, sid, jid, jscid)
-      - This function will update the data for the selected language node
+      - This function will update the data for the selected schedule node
 
     * msql(gid, sid, jid, jscid)
-      - This function is used to return modified SQL for the selected language 
node
+      - This function is used to return modified SQL for the
+      selected schedule node
+
+    * sql(gid, sid, jid, jscid)
+      - Dummy response for sql panel
+
+    * delete(gid, sid, jid, jscid)
+      - Drops job schedule
     """
 
     node_type = blueprint.node_type
@@ -126,18 +135,20 @@ class JobScheduleView(PGChildNodeView):
 
     operations = dict({
         'obj': [
-            {'get': 'properties', 'put': 'update'},
+            {'get': 'properties', 'put': 'update', 'delete': 'delete'},
             {'get': 'list', 'post': 'create'}
         ],
         'nodes': [{'get': 'nodes'}, {'get': 'nodes'}],
         'msql': [{'get': 'msql'}, {'get': 'msql'}],
+        'sql': [{'get': 'sql'}],
         'module.js': [{}, {}, {'get': 'module_js'}]
     })
 
     def _init_(self, **kwargs):
         """
         Method is used to initialize the JobScheduleView and its base view.
-        Initialize all the variables create/used dynamically like conn, 
template_path.
+        Initialize all the variables create/used dynamically like conn,
+        template_path.
 
         Args:
             **kwargs:
@@ -184,7 +195,8 @@ class JobScheduleView(PGChildNodeView):
     @check_precondition
     def list(self, gid, sid, jid):
         """
-        This function is used to list all the language nodes within that 
collection.
+        This function is used to list all the language nodes within
+        that collection.
 
         Args:
             gid: Server Group ID
@@ -208,8 +220,8 @@ class JobScheduleView(PGChildNodeView):
     @check_precondition
     def nodes(self, gid, sid, jid, jscid=None):
         """
-        This function is used to create all the child nodes within the 
collection.
-        Here it will create all the language nodes.
+        This function is used to create all the child nodes within
+        the collection. Here it will create all the language nodes.
 
         Args:
             gid: Server Group ID
@@ -230,11 +242,13 @@ class JobScheduleView(PGChildNodeView):
 
         if jscid is not None:
             if len(result['rows']) == 0:
-                return gone(errormsg="Could not find the specified job step.")
+                return gone(
+                    errormsg=gettext("Could not find the specified job step.")
+                )
 
             row = result['rows'][0]
             return make_json_response(
-                self.blueprint.generate_browser_node(
+                data=self.blueprint.generate_browser_node(
                     row['jscid'],
                     row['jscjobid'],
                     row['jscname'],
@@ -280,17 +294,33 @@ class JobScheduleView(PGChildNodeView):
             return internal_server_error(errormsg=res)
 
         if len(res['rows']) == 0:
-            return gone(errormsg="Could not find the specified job step.")
+            return gone(
+                errormsg=gettext("Could not find the specified job step.")
+            )
 
         return ajax_response(
             response=res['rows'][0],
             status=200
         )
 
+    @staticmethod
+    def format_list_data(value):
+        """
+        Converts to proper array data for sql
+        Args:
+            value: data to be converted
+
+        Returns:
+            Converted data
+        """
+        if not isinstance(value, list):
+            return value.replace("[", "{").replace("]", "}")
+        return value
+
     @check_precondition
     def create(self, gid, sid, jid):
         """
-        This function will update the data for the selected language node.
+        This function will update the data for the selected schedule node.
 
         Args:
             gid: Server Group ID
@@ -309,11 +339,21 @@ class JobScheduleView(PGChildNodeView):
         else:
             data = json.loads(request.data.decode())
             # convert python list literal to postgres array literal.
-            data['jscminutes'] = data['jscminutes'].replace("[", 
"{").replace("]", "}")
-            data['jschours'] = data['jschours'].replace("[", "{").replace("]", 
"}")
-            data['jscweekdays'] = data['jscweekdays'].replace("[", 
"{").replace("]", "}")
-            data['jscmonthdays'] = data['jscmonthdays'].replace("[", 
"{").replace("]", "}")
-            data['jscmonths'] = data['jscmonths'].replace("[", 
"{").replace("]", "}")
+            data['jscminutes'] = JobScheduleView.format_list_data(
+                data['jscminutes']
+            )
+            data['jschours'] = JobScheduleView.format_list_data(
+                data['jschours']
+            )
+            data['jscweekdays'] = JobScheduleView.format_list_data(
+                data['jscweekdays']
+            )
+            data['jscmonthdays'] = JobScheduleView.format_list_data(
+                data['jscmonthdays']
+            )
+            data['jscmonths'] = JobScheduleView.format_list_data(
+                data['jscmonths']
+            )
 
         sql = render_template(
             "/".join([self.template_path, 'create.sql']),
@@ -335,7 +375,7 @@ class JobScheduleView(PGChildNodeView):
 
         self.conn.execute_void('END')
         sql = render_template(
-            "/".join([self.template_path, 'nodes.sql']),
+            "/".join([self.template_path, 'properties.sql']),
             jscid=res,
             jid=jid
         )
@@ -344,20 +384,27 @@ class JobScheduleView(PGChildNodeView):
         if not status:
             return internal_server_error(errormsg=res)
 
+        if len(res['rows']) == 0:
+            return gone(
+                errormsg=gettext("Job schedule creation failed.")
+            )
         row = res['rows'][0]
-        return make_json_response(
-            data=self.blueprint.generate_browser_node(
+
+        return jsonify(
+            node=self.blueprint.generate_browser_node(
                 row['jscid'],
                 row['jscjobid'],
                 row['jscname'],
-                icon="icon-pga_schedule"
+                icon="icon-pga_schedule",
+                enabled=row['jscenabled']
             )
         )
 
+
     @check_precondition
     def update(self, gid, sid, jid, jscid):
         """
-        This function will update the data for the selected language node.
+        This function will update the data for the selected schedule node.
 
         Args:
             gid: Server Group ID
@@ -377,20 +424,26 @@ class JobScheduleView(PGChildNodeView):
         else:
             data = json.loads(request.data.decode())
             # convert python list literal to postgres array literal.
-            if 'jscminutes' in data:
-                data['jscminutes'] = data['jscminutes'].replace("[", 
"{").replace("]", "}")
-
-            if 'jschours' in data:
-                data['jschours'] = data['jschours'].replace("[", 
"{").replace("]", "}")
-
-            if 'jscweekdays' in data:
-                data['jscweekdays'] = data['jscweekdays'].replace("[", 
"{").replace("]", "}")
-
-            if 'jscmonthdays' in data:
-                data['jscmonthdays'] = data['jscmonthdays'].replace("[", 
"{").replace("]", "}")
-
-            if 'jscmonths' in data:
-                data['jscmonths'] = data['jscmonths'].replace("[", 
"{").replace("]", "}")
+            if 'jscminutes' in data and data['jscminutes'] is not None:
+                data['jscminutes'] = JobScheduleView.format_list_data(
+                    data['jscminutes']
+                )
+            if 'jschours' in data and data['jschours'] is not None:
+                data['jschours'] = JobScheduleView.format_list_data(
+                    data['jschours']
+                )
+            if 'jscweekdays' in data and data['jscweekdays'] is not None:
+                data['jscweekdays'] = JobScheduleView.format_list_data(
+                    data['jscweekdays']
+                )
+            if 'jscmonthdays' in data and data['jscmonthdays'] is not None:
+                data['jscmonthdays'] = JobScheduleView.format_list_data(
+                    data['jscmonthdays']
+                )
+            if 'jscmonths' in data and data['jscmonths'] is not None:
+                data['jscmonths'] = JobScheduleView.format_list_data(
+                    data['jscmonths']
+                )
 
         sql = render_template(
             "/".join([self.template_path, 'update.sql']),
@@ -405,7 +458,7 @@ class JobScheduleView(PGChildNodeView):
             return internal_server_error(errormsg=res)
 
         sql = render_template(
-            "/".join([self.template_path, 'nodes.sql']),
+            "/".join([self.template_path, 'properties.sql']),
             jscid=jscid,
             jid=jid
         )
@@ -415,19 +468,41 @@ class JobScheduleView(PGChildNodeView):
             return internal_server_error(errormsg=res)
 
         row = res['rows'][0]
-        return make_json_response(
-            self.blueprint.generate_browser_node(
-                row['jscid'],
-                row['jscjobid'],
+        if len(res['rows']) == 0:
+            return gone(
+                errormsg=gettext("Job schedule update failed.")
+            )
+
+        return jsonify(
+            node=self.blueprint.generate_browser_node(
+                jscid,
+                jid,
                 row['jscname'],
-                icon="icon-pga_schedule"
+                icon="icon-pga_schedule",
+                enabled=row['jscenabled']
+            )
+        )
+
+    @check_precondition
+    def delete(self, gid, sid, jid, jscid):
+        """Delete the Job Schedule."""
+
+        status, res = self.conn.execute_void(
+            render_template(
+                "/".join([self.template_path, 'delete.sql']),
+                jid=jid, jscid=jscid, conn=self.conn
             )
         )
+        if not status:
+            return internal_server_error(errormsg=res)
+
+        return make_json_response(success=1)
 
     @check_precondition
     def msql(self, gid, sid, jid, jscid=None):
         """
-        This function is used to return modified SQL for the selected language 
node.
+        This function is used to return modified SQL for the
+        selected Schedule node.
 
         Args:
             gid: Server Group ID
@@ -465,5 +540,20 @@ class JobScheduleView(PGChildNodeView):
             status=200
         )
 
+    @check_precondition
+    def sql(self, gid, sid, jid, jscid):
+        """
+        Dummy response for sql route.
+        As we need to have msql tab for create and edit mode we can not
+        disable it setting hasSQL=false because we have a single 'hasSQL'
+        flag in JS to display both sql & msql tab
+        """
+        return ajax_response(
+            response=gettext(
+                "-- No SQL could be generated for the selected object."
+            ),
+            status=200
+        )
+
 
 JobScheduleView.register_node_view(blueprint)
diff --git 
a/web/pgadmin/browser/server_groups/servers/pgagent/steps/__init__.py 
b/web/pgadmin/browser/server_groups/servers/pgagent/steps/__init__.py
index 35f1fbb..3aba293 100644
--- a/web/pgadmin/browser/server_groups/servers/pgagent/steps/__init__.py
+++ b/web/pgadmin/browser/server_groups/servers/pgagent/steps/__init__.py
@@ -12,7 +12,7 @@
 import json
 from functools import wraps
 
-from flask import render_template, make_response, request
+from flask import render_template, make_response, request, jsonify
 from flask_babel import gettext
 from pgadmin.browser.collection import CollectionNodeModule
 from pgadmin.browser.utils import PGChildNodeView
@@ -64,7 +64,8 @@ class JobStepModule(CollectionNodeModule):
     @property
     def script_load(self):
         """
-        Load the module script for language, when any of the database nodes 
are initialized.
+        Load the module script for language, when any of the pga_job nodes
+        are initialized.
 
         Returns: node type of the server module.
         """
@@ -78,9 +79,9 @@ class JobStepView(PGChildNodeView):
     """
     class JobStepView(PGChildNodeView)
 
-        A view class for JobStep node derived from PGChildNodeView. This class 
is
-        responsible for all the stuff related to view like updating language
-        node, showing properties, showing sql in sql pane.
+        A view class for JobStep node derived from PGChildNodeView.
+        This class is responsible for all the stuff related to view like
+        updating job step node, showing properties, showing sql in sql pane.
 
     Methods:
     -------
@@ -97,20 +98,29 @@ class JobStepView(PGChildNodeView):
         manager,conn & template_path properties to self
 
     * list()
-      - This function is used to list all the language nodes within that 
collection.
+      - This function is used to list all the job step nodes within that
+      collection.
 
     * nodes()
-      - This function will used to create all the child node within that 
collection.
-        Here it will create all the language node.
+      - This function will used to create all the child node within that
+      collection.
+        Here it will create all the job step node.
 
     * properties(gid, sid, jid, jstid)
-      - This function will show the properties of the selected language node
+      - This function will show the properties of the selected job step node
 
     * update(gid, sid, jid, jstid)
-      - This function will update the data for the selected language node
+      - This function will update the data for the selected job step node
 
     * msql(gid, sid, jid, jstid)
-      - This function is used to return modified SQL for the selected language 
node
+      - This function is used to return modified SQL for the selected
+      job step node
+
+    * sql(gid, sid, jid, jscid)
+      - Dummy response for sql panel
+
+    * delete(gid, sid, jid, jscid)
+      - Drops job step
     """
 
     node_type = blueprint.node_type
@@ -126,11 +136,12 @@ class JobStepView(PGChildNodeView):
 
     operations = dict({
         'obj': [
-            {'get': 'properties', 'put': 'update'},
+            {'get': 'properties', 'put': 'update', 'delete': 'delete'},
             {'get': 'list', 'post': 'create'}
         ],
         'nodes': [{'get': 'nodes'}, {'get': 'nodes'}],
         'msql': [{'get': 'msql'}, {'get': 'msql'}],
+        'sql': [{'get': 'sql'}],
         'stats': [{'get': 'statistics'}],
         'module.js': [{}, {}, {'get': 'module_js'}]
     })
@@ -138,7 +149,8 @@ class JobStepView(PGChildNodeView):
     def _init_(self, **kwargs):
         """
         Method is used to initialize the JobStepView and its base view.
-        Initialize all the variables create/used dynamically like conn, 
template_path.
+        Initialize all the variables create/used dynamically like conn,
+        template_path.
 
         Args:
             **kwargs:
@@ -196,7 +208,8 @@ SELECT EXISTS(
     @check_precondition
     def list(self, gid, sid, jid):
         """
-        This function is used to list all the language nodes within that 
collection.
+        This function is used to list all the job step nodes within
+        that collection.
 
         Args:
             gid: Server Group ID
@@ -221,8 +234,9 @@ SELECT EXISTS(
     @check_precondition
     def nodes(self, gid, sid, jid, jstid=None):
         """
-        This function is used to create all the child nodes within the 
collection.
-        Here it will create all the language nodes.
+        This function is used to create all the child nodes
+        within the collection.
+        Here it will create all the job step nodes.
 
         Args:
             gid: Server Group ID
@@ -277,7 +291,7 @@ SELECT EXISTS(
     @check_precondition
     def properties(self, gid, sid, jid, jstid):
         """
-        This function will show the properties of the selected language node.
+        This function will show the properties of the selected job step node.
 
         Args:
             gid: Server Group ID
@@ -307,7 +321,7 @@ SELECT EXISTS(
     @check_precondition
     def create(self, gid, sid, jid):
         """
-        This function will update the data for the selected language node.
+        This function will update the data for the selected job step node.
 
         Args:
             gid: Server Group ID
@@ -348,9 +362,15 @@ SELECT EXISTS(
         if not status:
             return internal_server_error(errormsg=res)
 
+        if len(res['rows']) == 0:
+            return gone(
+                errormsg=gettext(
+                    "Job step creation failed."
+                )
+            )
         row = res['rows'][0]
-        return make_json_response(
-            data=self.blueprint.generate_browser_node(
+        return jsonify(
+            node=self.blueprint.generate_browser_node(
                 row['jstid'],
                 row['jstjobid'],
                 row['jstname'],
@@ -361,7 +381,7 @@ SELECT EXISTS(
     @check_precondition
     def update(self, gid, sid, jid, jstid):
         """
-        This function will update the data for the selected language node.
+        This function will update the data for the selected job step node.
 
         Args:
             gid: Server Group ID
@@ -428,20 +448,43 @@ SELECT EXISTS(
         if not status:
             return internal_server_error(errormsg=res)
 
+        if len(res['rows']) == 0:
+            return gone(
+                errormsg=gettext(
+                    "Job step update failed."
+                )
+            )
         row = res['rows'][0]
-        return make_json_response(
-            self.blueprint.generate_browser_node(
-                row['jstid'],
-                row['jstjobid'],
+        return jsonify(
+            node=self.blueprint.generate_browser_node(
+                jstid,
+                jid,
                 row['jstname'],
                 icon="icon-pga_jobstep"
             )
         )
 
     @check_precondition
+    def delete(self, gid, sid, jid, jstid):
+        """Delete the Job step."""
+
+        status, res = self.conn.execute_void(
+            render_template(
+                "/".join([self.template_path, 'delete.sql']),
+                jid=jid, jstid=jstid, conn=self.conn
+            )
+        )
+        if not status:
+            return internal_server_error(errormsg=res)
+
+        return make_json_response(success=1)
+
+
+    @check_precondition
     def msql(self, gid, sid, jid, jstid=None):
         """
-        This function is used to return modified SQL for the selected language 
node.
+        This function is used to return modified SQL for the selected
+        job step node.
 
         Args:
             gid: Server Group ID
@@ -535,5 +578,20 @@ SELECT EXISTS(
             status=200
         )
 
+    @check_precondition
+    def sql(self, gid, sid, jid, jstid):
+        """
+        Dummy response for sql route.
+        As we need to have msql tab for create and edit mode we can not
+        disable it setting hasSQL=false because we have a single 'hasSQL'
+        flag in JS to display both sql & msql tab
+        """
+        return ajax_response(
+            response=gettext(
+                "-- No SQL could be generated for the selected object."
+            ),
+            status=200
+        )
+
 
 JobStepView.register_node_view(blueprint)
-- 
Sent via pgadmin-hackers mailing list (pgadmin-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgadmin-hackers

Reply via email to