mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2025-01-15 19:22:21 -06:00
Fix various issues with pgAgent job steps and schedules:
1) Error on clicking SQL panel when Schedule OR Step node is selected in browser. Fixes #1888 2) Error while dropping Schedule OR Step node. Fixes #1889 3) Newly created Schedule/Step node was not displaying in browser. Fixes #1890
This commit is contained in:
parent
88737248ab
commit
b149fe371e
@ -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
|
||||
)
|
||||
)
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -31,7 +31,7 @@ define([
|
||||
canDrop: function(node) {
|
||||
return true;
|
||||
},
|
||||
label: gettext('Steps'),
|
||||
label: gettext('Step'),
|
||||
node_image: function() {
|
||||
return 'icon-pga_jobstep';
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user