def get_display(self): outer_div = DivWdg() outer_div.set_id('change-instructions') instructions_code = self.component_sobject.get_value( 'instructions_code') if instructions_code: instructions_search = Search('twog/instructions') instructions_search.add_code_filter(instructions_code) instructions_sobject = instructions_search.get_sobject() outer_div.add( 'Instruction Document is currently set to: {0}'.format( instructions_sobject.get_value('name'))) else: outer_div.add('No Instructions Document currently selected') outer_div.add(get_instructions_select_wdg()) submit_button = SubmitWdg('Submit') submit_button.add_behavior(self.get_submit_button_behavior()) outer_div.add(submit_button) return outer_div
def get_display(self): outer_div = DivWdg() outer_div.set_id('add_deliverable_files_to_package') order_code = self.package_sobject.get('order_code') order_search = Search('twog/order') order_search.add_code_filter(order_code) order_sobject = order_search.get_sobject() deliverable_files = get_deliverable_files_in_order(order_sobject) selected_files = get_files_for_package(self.package_sobject.get_code()) # Only show the selectable files and the submit button if the parent order has any deliverable files if deliverable_files: deliverable_file_select_wdg = get_files_checkbox_from_file_list(deliverable_files, selected_files) outer_div.add(deliverable_file_select_wdg) submit_button = SubmitWdg('Submit') submit_button.add_behavior(self.get_submit_button_behavior()) outer_div.add(submit_button) else: outer_div.add('<div>No deliverable files are available for this Order yet.</div>') return outer_div
def get_display(self): outer_div = DivWdg() outer_div.set_id('add_deliverable_files_to_package') order_code = self.package_sobject.get('order_code') order_search = Search('twog/order') order_search.add_code_filter(order_code) order_sobject = order_search.get_sobject() deliverable_files = get_deliverable_files_in_order(order_sobject) selected_files = get_files_for_package(self.package_sobject.get_code()) # Only show the selectable files and the submit button if the parent order has any deliverable files if deliverable_files: deliverable_file_select_wdg = get_files_checkbox_from_file_list( deliverable_files, selected_files) outer_div.add(deliverable_file_select_wdg) submit_button = SubmitWdg('Submit') submit_button.add_behavior(self.get_submit_button_behavior()) outer_div.add(submit_button) else: outer_div.add( '<div>No deliverable files are available for this Order yet.</div>' ) return outer_div
def add_task_to_component(self, process, component_code, login): server = TacticServerStub.get() component_search = Search('twog/component') component_search.add_code_filter(component_code) component = component_search.get_sobject() server.insert('sthpw/task', {'process': process, 'login': login}, parent_key=component.get_search_key())
def get_platform_connection_by_package_sobject(package_sobject): order_search = Search('twog/order') order_search.add_code_filter(package_sobject.get('order_code')) order_sobject = order_search.get_sobject() platform_connection_search = Search('twog/platform_connection') platform_connection_search.add_filter('platform_code', package_sobject.get('platform_code')) platform_connection_search.add_filter('division_code', order_sobject.get('division_code')) platform_connection = platform_connection_search.get_sobject() return platform_connection
def init(self): self.task_sobject = self.get_sobject_from_kwargs() self.task_data = get_task_data_sobject_from_task_code(self.task_sobject.get_code()) component = self.task_sobject.get_parent() order_search = Search('twog/order') order_search.add_code_filter(component.get('order_code')) self.order = order_search.get_sobject() self.order_files = get_files_for_order(self.order.get_code()) self.selected_files = get_task_data_in_files(self.task_data.get_code())
def init(self): self.order_sobject = self.get_sobject_from_kwargs() division_search = Search('twog/division') division_search.add_code_filter( self.order_sobject.get('division_code')) self.division_sobject = division_search.get_sobject() self.parent_widget_title = self.kwargs.get('parent_widget_title') self.parent_widget_name = self.kwargs.get('parent_widget_name') self.parent_widget_search_key = self.kwargs.get( 'parent_widget_search_key')
def add_task_to_component(self, process, component_code, login): server = TacticServerStub.get() component_search = Search('twog/component') component_search.add_code_filter(component_code) component = component_search.get_sobject() server.insert('sthpw/task', { 'process': process, 'login': login }, parent_key=component.get_search_key())
def main(server=None, trigger_input=None): """ On the insert|twog/package event, search for an existing connection from the package's division to platform. If no entry exists in the twog/platform_connection table, create it by inserting the division_code, platform_code, and a connection_status set to 'disconnected'. :param server: the TacticServerStub object :param trigger_input: a dict with data like like search_key, search_type, sobject, and update_data :return: None """ if not trigger_input: return try: from pyasm.search import Search # Get the package sobject. package_sobject = trigger_input.get('sobject') # Search for the twog/order sobject (which leads to the division) order_search = Search('twog/order') order_search.add_code_filter(package_sobject.get('order_code')) order_sobject = order_search.get_sobject() # Search for the twog/division sobject division_search = Search('twog/division') division_search.add_code_filter(order_sobject.get('division_code')) division_sobject = division_search.get_sobject() # Search for an existing entry in the twog/platform_connection table. If it already exists, no action is needed existing_platform_connection_search = Search( 'twog/platform_connection') existing_platform_connection_search.add_filter( 'division_code', division_sobject.get_code()) existing_platform_connection_search.add_filter( 'platform_code', package_sobject.get('platform_code')) existing_platform_connection = existing_platform_connection_search.get_sobject( ) if not existing_platform_connection: # Insert the new entry data_to_insert = { 'division_code': division_sobject.get_code(), 'platform_code': package_sobject.get('platform_code'), 'connection_status': 'disconnected' } server.insert('twog/platform_connection', data_to_insert) except Exception as e: traceback.print_exc() print str(e) raise e
def get_order_sobject_from_component_sobject(component_sobject): """ Given a twog/component sobject, get the order that it is assigned to. :param component_sobject: twog/component sobject :return: twog/order sobject """ order_search = Search('twog/order') order_search.add_code_filter(component_sobject.get('order_code')) order_sobject = order_search.get_sobject() return order_sobject
def main(server=None, trigger_input=None): """ On the insert|twog/package event, search for an existing connection from the package's division to platform. If no entry exists in the twog/platform_connection table, create it by inserting the division_code, platform_code, and a connection_status set to 'disconnected'. :param server: the TacticServerStub object :param trigger_input: a dict with data like like search_key, search_type, sobject, and update_data :return: None """ if not trigger_input: return try: from pyasm.search import Search # Get the package sobject. package_sobject = trigger_input.get('sobject') # Search for the twog/order sobject (which leads to the division) order_search = Search('twog/order') order_search.add_code_filter(package_sobject.get('order_code')) order_sobject = order_search.get_sobject() # Search for the twog/division sobject division_search = Search('twog/division') division_search.add_code_filter(order_sobject.get('division_code')) division_sobject = division_search.get_sobject() # Search for an existing entry in the twog/platform_connection table. If it already exists, no action is needed existing_platform_connection_search = Search('twog/platform_connection') existing_platform_connection_search.add_filter('division_code', division_sobject.get_code()) existing_platform_connection_search.add_filter('platform_code', package_sobject.get('platform_code')) existing_platform_connection = existing_platform_connection_search.get_sobject() if not existing_platform_connection: # Insert the new entry data_to_insert = { 'division_code': division_sobject.get_code(), 'platform_code': package_sobject.get('platform_code'), 'connection_status': 'disconnected' } server.insert('twog/platform_connection', data_to_insert) except Exception as e: traceback.print_exc() print str(e) raise e
def get_task_estimated_hours_from_task_code(task_code): task_search = Search('sthpw/task') task_search.add_code_filter(task_code) task = task_search.get_sobject() component = task.get_parent() instructions_code = component.get('instructions_code') if instructions_code: instructions_sobject = get_sobject_by_code('twog/instructions', instructions_code) if instructions_sobject: return get_task_estimated_hours_from_instructions_document(instructions_sobject, task.get('process')) return 0
def get_client_division_sobject_from_order_sobject(order_sobject): """ Given an order sobject, get the division sobject associated with it. If there isn't one, return None :param order_sobject: twog/order sobject :return: twog/division sobject or None """ division_search = Search('twog/division') division_search.add_code_filter(order_sobject.get('division_code')) division_sobject = division_search.get_sobject() if division_sobject: return division_sobject else: return None
def get_name_from_code(code, search_type): """ Using a unique code and a search type, find an SObject and return its name :param code: String, Unique code for an SObject (ex: CLIENT00050) :param search_type: String, An SType (ex: 'twog/client') :return: String, Name of an SObject """ search = Search(search_type) search.add_code_filter(code) sobject = search.get_sobject() if not sobject: return None return sobject.get('name')
def execute(self): # Get the task sobject (in this case, should be attached to twog/department_request) task_sobject = self.input.get('sobject') # Do a sanity check on the search_type to make sure we're working with a twog/department_request search_type = task_sobject.get('search_type') if search_type != u'twog/department_request?project=twog': raise TacticException( "Something went wrong. A trigger was called on a task that it should not have been." "Trigger Name: {0}".format(self.__class__.__name__)) # Get the twog/department_request sobject search_code = task_sobject.get('search_code') department_request_search = Search('twog/department_request') department_request_search.add_code_filter(search_code) department_request_sobject = department_request_search.get_sobject() # Task process should be either 'Request' or 'Approval' task_process = task_sobject.get('process').lower() # For this trigger, only 'Complete', 'Rejected', and 'Approved' apply task_status = task_sobject.get('status').lower() # Get a server instance to send the data server = TacticServerStub.get() if task_process == 'request' and task_status == 'complete': # Check if the department request has its 'Response' column filled out. If not, raise an error if not department_request_sobject.get('response'): raise TacticException( "Before marking the request as 'Complete', you must fill out the 'Response' " "column.") # Mark the twog/department_request status as needing approval server.update(department_request_sobject.get_search_key(), data={'status': 'approval'}) elif task_process == 'approval': if task_status == 'rejected': # Need to set the twog/department_request status back to 'in_progress' so that it appears on the # department's list again. Setting the task status to 'Revise' is not handled here (the pipeline # takes care of that). server.update(department_request_sobject.get_search_key(), data={'status': 'in_progress'}) elif task_status == 'approved': # If the Approval task is marked as 'approved', then the request is finished. Mark the # twog/department_request status as 'complete' so it disappears from all views. server.update(department_request_sobject.get_search_key(), data={'status': 'complete'})
def get_sobject_by_code(search_type, sobject_code): """ Given a search type and an sobject code, return the sobject associated with the code. :param search_type: Search type ('twog/order' for example) :param sobject_code: sobject unique code :return: sobject """ search = Search(search_type) search.add_code_filter(sobject_code) search_result = search.get_sobject() if search_result: return search_result else: return None
def get_client_name_from_division_code(division_code): """ Get the name of the client that owns the division. :param division_code: A unique division code :return: The client's name """ division_search = Search('twog/division') division_search.add_code_filter(division_code) division = division_search.get_sobject() if division: client_search = Search('twog/client') client_search.add_code_filter(division.get('client_code')) client = client_search.get_sobject() if client: return client.get('name') return None
def get_client_division_sobject_for_task_sobject(task): """ Given a task sobject, travel up the chain of Component and Order to get the Division the order is assigned to. This will only work for tasks that are assigned to components. :param task: task sobject :return: twog/division sobject """ parent_component = task.get_parent() order_search = Search('twog/order') order_search.add_code_filter(parent_component.get('order_code')) order = order_search.get_sobject() division_search = Search('twog/division') division_search.add_code_filter(order.get('division_code')) division = division_search.get_sobject() return division
def main(server=None, trigger_input=None): """ :param server: the TacticServerStub object :param trigger_input: a dict with data like like search_key, search_type, sobject, and update_data :return: None """ if not trigger_input: trigger_input = {} # Get the task task_sobject = trigger_input.get('sobject') # Only proceed if the task exists and is attached to a twog/component sobject if not (task_sobject and task_sobject.get('search_type') == u'twog/component?project=twog'): return component_search_code = task_sobject.get('search_code') component_search = Search('twog/component') component_search.add_code_filter(component_search_code) component = component_search.get_sobject() task_status = task_sobject.get('status') # If the task is marked as complete, check if the component needs to be set to complete as well (only happens if # all other tasks on that component are marked as complete) if task_status.lower() == 'complete': tasks = get_task_sobjects_from_component_sobject(component) for task in tasks: if task.get('status') != 'Complete': return else: server.update(component.get_search_key(), {'status': 'complete'}) elif task_status.lower() == 'in progress': if component.get('status').lower() != 'in_progress': server.update(component.get_search_key(), {'status': 'in_progress'})
def get_display(self): outer_div = DivWdg() outer_div.set_id('change-title') title_code = self.component_sobject.get_value('title_code') if title_code: title_sobject_search = Search('twog/title') title_sobject_search.add_code_filter(title_code) title_sobject = title_sobject_search.get_sobject() outer_div.add('Title is currently set to: {0}'.format(title_sobject.get_value('name'))) else: outer_div.add('No Title currently selected') outer_div.add(get_title_select_wdg()) submit_button = SubmitWdg('Submit') submit_button.add_behavior(self.get_submit_button_behavior()) outer_div.add(submit_button) return outer_div
def get_display(self): outer_div = DivWdg() outer_div.set_id('change-title') title_code = self.component_sobject.get_value('title_code') if title_code: title_sobject_search = Search('twog/title') title_sobject_search.add_code_filter(title_code) title_sobject = title_sobject_search.get_sobject() outer_div.add('Title is currently set to: {0}'.format( title_sobject.get_value('name'))) else: outer_div.add('No Title currently selected') outer_div.add(get_title_select_wdg()) submit_button = SubmitWdg('Submit') submit_button.add_behavior(self.get_submit_button_behavior()) outer_div.add(submit_button) return outer_div
def main(server=None, input=None): """ :param server: the TacticServerStub object :param input: a dict with data like like search_key, search_type, sobject, and update_data :return: None """ # Start by getting all the divisions divisions_search = Search('twog/division') divisions = divisions_search.get_sobjects() for division in divisions: # Get the division's retention policy, if one exists retention_policy_search = Search('twog/retention_policy') retention_policy_search.add_code_filter(division.get('retention_policy_code')) retention_policy = retention_policy_search.get_sobject() if retention_policy: # Get the number of days until archive source_days_to_archive = retention_policy.get('source_file_archive_days') intermediate_days_to_archive = retention_policy.get('intermediate_file_archive_days') deliverable_days_to_archive = retention_policy.get('deliverable_file_archive_days') # Get the number of days until deletion source_days_to_delete = retention_policy.get('source_file_delete_days') intermediate_days_to_delete = retention_policy.get('intermediate_file_delete_days') deliverable_days_to_delete = retention_policy.get('deliverable_file_delete_days') # Get all the files associated with the division, if any division_file_search = Search('twog/file') division_file_search.add_filter('division_code', division.get_code()) # Only get files with san_status 'exists', 'needs_archive', or 'archived', they are the only files that # potentially need updating division_file_search.add_filter('san_status', 'deleted', op='!=') division_file_search.add_filter('san_status', 'needs_delete', op='!=') division_files = division_file_search.get_sobjects() for division_file in division_files: # Search for any orders that the file is a part of file_in_order_search = Search('twog/file_in_order') file_in_order_search.add_filter('file_code', division_file.get_code()) file_in_order_entries = file_in_order_search.get_sobjects() # Get all the orders that the file is a part of. Do this by first getting all the order codes, # then doing a search for all the order sobjects order_codes = [] for file_in_order_entry in file_in_order_entries: order_code = "'{0}'".format(file_in_order_entry.get('order_code')) if order_code not in order_codes: order_codes.append(order_code) if order_codes: # Search for the orders orders_search = Search('twog/order') orders_search.add_where('\"code\" in ({0})'.format(','.join(order_codes))) orders = orders_search.get_sobjects() # If the file is part of any order that isn't marked as complete, return immediately, since the # file is still in use. If it is complete, use the most recent completion date from all the orders # to determine when the file was last used most_recent_completion_date = get_most_recent_completed_order_date(orders) if most_recent_completion_date: number_of_days_passed = (datetime.today() - most_recent_completion_date).days file_classification = division_file.get('classification') # Determine the file type, and which part of the retention policy to compare against if file_classification == 'source': days_to_archive = source_days_to_archive days_to_delete = source_days_to_delete elif file_classification == 'intermediate': days_to_archive = intermediate_days_to_archive days_to_delete = intermediate_days_to_delete else: days_to_archive = deliverable_days_to_archive days_to_delete = deliverable_days_to_delete if days_to_delete and days_to_delete < number_of_days_passed: # Mark the file for deletion search_key = server.build_search_key('twog/file', division_file.get_code(), project_code='twog') server.update(search_key, {'san_status': 'needs_delete'}) elif days_to_archive and days_to_archive < number_of_days_passed: # Mark the file for archiving search_key = server.build_search_key('twog/file', division_file.get_code(), project_code='twog') server.update(search_key, {'san_status': 'needs_archive'})
def get_instruction_text_from_code(code): title_order_search = Search('twog/title_order') title_order_search.add_code_filter(code) title_order = title_order_search.get_sobject() return title_order.get('instructions')
def main(server=None, input=None): """ :param server: the TacticServerStub object :param input: a dict with data like like search_key, search_type, sobject, and update_data :return: None """ # Start by getting all the divisions divisions_search = Search('twog/division') divisions = divisions_search.get_sobjects() for division in divisions: # Get the division's retention policy, if one exists retention_policy_search = Search('twog/retention_policy') retention_policy_search.add_code_filter( division.get('retention_policy_code')) retention_policy = retention_policy_search.get_sobject() if retention_policy: # Get the number of days until archive source_days_to_archive = retention_policy.get( 'source_file_archive_days') intermediate_days_to_archive = retention_policy.get( 'intermediate_file_archive_days') deliverable_days_to_archive = retention_policy.get( 'deliverable_file_archive_days') # Get the number of days until deletion source_days_to_delete = retention_policy.get( 'source_file_delete_days') intermediate_days_to_delete = retention_policy.get( 'intermediate_file_delete_days') deliverable_days_to_delete = retention_policy.get( 'deliverable_file_delete_days') # Get all the files associated with the division, if any division_file_search = Search('twog/file') division_file_search.add_filter('division_code', division.get_code()) # Only get files with san_status 'exists', 'needs_archive', or 'archived', they are the only files that # potentially need updating division_file_search.add_filter('san_status', 'deleted', op='!=') division_file_search.add_filter('san_status', 'needs_delete', op='!=') division_files = division_file_search.get_sobjects() for division_file in division_files: # Search for any orders that the file is a part of file_in_order_search = Search('twog/file_in_order') file_in_order_search.add_filter('file_code', division_file.get_code()) file_in_order_entries = file_in_order_search.get_sobjects() # Get all the orders that the file is a part of. Do this by first getting all the order codes, # then doing a search for all the order sobjects order_codes = [] for file_in_order_entry in file_in_order_entries: order_code = "'{0}'".format( file_in_order_entry.get('order_code')) if order_code not in order_codes: order_codes.append(order_code) if order_codes: # Search for the orders orders_search = Search('twog/order') orders_search.add_where('\"code\" in ({0})'.format( ','.join(order_codes))) orders = orders_search.get_sobjects() # If the file is part of any order that isn't marked as complete, return immediately, since the # file is still in use. If it is complete, use the most recent completion date from all the orders # to determine when the file was last used most_recent_completion_date = get_most_recent_completed_order_date( orders) if most_recent_completion_date: number_of_days_passed = ( datetime.today() - most_recent_completion_date).days file_classification = division_file.get( 'classification') # Determine the file type, and which part of the retention policy to compare against if file_classification == 'source': days_to_archive = source_days_to_archive days_to_delete = source_days_to_delete elif file_classification == 'intermediate': days_to_archive = intermediate_days_to_archive days_to_delete = intermediate_days_to_delete else: days_to_archive = deliverable_days_to_archive days_to_delete = deliverable_days_to_delete if days_to_delete and days_to_delete < number_of_days_passed: # Mark the file for deletion search_key = server.build_search_key( 'twog/file', division_file.get_code(), project_code='twog') server.update(search_key, {'san_status': 'needs_delete'}) elif days_to_archive and days_to_archive < number_of_days_passed: # Mark the file for archiving search_key = server.build_search_key( 'twog/file', division_file.get_code(), project_code='twog') server.update(search_key, {'san_status': 'needs_archive'})
def main(server=None, input_data=None): if not input_data: return # The input for the script should be a sthpw/task sobject task_sobject = input_data.get('sobject') # This script only applies to tasks that are marked as Complete, and are attached to twog/component sobjects if not (task_sobject.get('status') == 'Complete' and task_sobject.get( 'search_type') == u'twog/component?project=twog'): return # Tasks saved on twog/component have extra data associated with them, saved under twog/task_data # Retrieve the entry of twog/task_data for this task sobject task_data_search = Search('twog/task_data') task_data_search.add_filter('task_code', task_sobject.get('code')) task_data = task_data_search.get_sobject() if not task_data: return # Get the next task in the pipeline # Start by getting the component sobject the task is attached to component_search = Search('twog/component') component_search.add_code_filter(task_sobject.get('search_code')) component_sobject = component_search.get_sobject() if not component_sobject: return # Then get the output processes. Start by fetching the pipeline object pipeline = Pipeline('twog/component') pipeline.set_pipeline(get_pipeline_xml(component_sobject.get('pipeline_code'))) # Then get the names of the processes contained in that pipeline (which corresponds to all the names of the tasks # within this component) output_processes = pipeline.get_output_processes(task_sobject.get('process')) # Now, get the actual task objects tasks_search = Search('sthpw/task') tasks_search.add_filter('process', output_processes) tasks_search.add_parent_filter(component_sobject) output_tasks = tasks_search.get_sobjects() # Fetch the output files attached to the original task out_files_search = Search('twog/task_data_out_file') out_files_search.add_filter('task_data_code', task_data.get_code()) out_files = out_files_search.get_sobjects() if not out_files: return # Go through each output task and attach the output files as input files for output_task in output_tasks: output_task_data_search = Search('twog/task_data') output_task_data_search.add_filter('task_code', output_task.get_code()) output_task_data = output_task_data_search.get_sobject() for out_file in out_files: inserted_data = { 'task_data_code': output_task_data.get_code(), 'file_code': out_file.get('file_code') } server.insert('twog/task_data_in_file', inserted_data) # The file should be added to the files in order list server.insert('twog/file_in_order', {'order_code': component_sobject.get('order_code'), 'file_code': out_file.get('file_code')})
def set_row(self, order, table, counter, header_groups, tasks): order_name = order.get('name') order_code = order.get('code') division_code = order.get('division_code') due_date = order.get('due_date') order_table = Table() order_table.add_style('width', '100%') name_row = order_table.add_row() name_row.add_style('font-size', '14px') name_row.add_style('font-weight', 'bold') name_data = '<span style="color: #FF0000">{0}.</span> <u>{1}</u>'.format(counter, order_name) order_table.add_cell(data=name_data, row=name_row, css='order-row') code_row = order_table.add_row() code_row.add_style('font-size', '12px') code_cell = order_table.add_cell(data='<strong>Order code:</strong> {0}'.format(order_code), row=code_row) code_cell.add_style('padding-top', '3px') code_cell.add_style('padding-bottom', '3px') code_cell.add_style('padding-left', '3px') division_row = order_table.add_row() division_search = Search('twog/division') division_search.add_code_filter(division_code) division = division_search.get_sobject() # TODO: Find the division image division_data = '<b>Division:</b> {0}'.format(division.get('name')) order_table.add_cell(data=division_data, row=division_row) date_row = order_table.add_row() due_date_data = '<b>Due:</b> {0}'.format(due_date) order_table.add_cell(data=due_date_data, row=date_row) # Add the buttons for the Order button_row = order_table.add_row() order_builder_button = ButtonNewWdg(title='Order Builder', icon='WORK') order_builder_button.add_behavior(get_order_builder_launch_behavior(order.get('__search_key__'))) note_button = ButtonNewWdg(title='Add Note', icon='NOTE') note_button.add_behavior(get_add_notes_behavior(order.get('__search_key__'))) note_button.add_style('display', 'inline-block') order_table.add_cell(data=order_builder_button, row=button_row) order_table.add_cell(data=note_button, row=button_row) current_row = table.add_row() current_row.add_style('width', '100%') current_row.add_style('vertical-align', 'top') order_cell_background_color = '#D7D7D7' order_cell = table.add_cell(order_table, row=current_row) order_cell.add_style('background-color', order_cell_background_color) order_cell.add_style('border', '1px solid #EEE') order_cell.add_style('padding', '4px') order_cell.add_style('width', '24%') for column in header_groups: if tasks: column_tasks = tasks.get(column) else: column_tasks = [] if column_tasks: task_table = Table() task_table.add_style('width', '100%') task_table.add_style('font-size', '10px') for task in column_tasks: current_task_row = task_table.add_row() current_task_row.add_style('background-color', self.TASK_COLOR_DICT.get(task.get_value('status').lower(), '#FFFFFF')) current_task_row.add_style('padding', '3px') current_task_row.add_style('min-height', '20px') current_task_row.add_style('border-top-left-radius', '10px') current_task_row.add_style('border-bottom-left-radius', '10px') inspect_button = ButtonNewWdg(title='Task Inspect', icon='WORK') inspect_button.add_behavior(get_load_popup_widget_behavior('Task Inspect', 'widgets.TaskInspectWdg', task.get_search_key(), width=600, height=600)) task_table.add_cell(data=inspect_button, row=current_task_row) # Each task in the row will have the following properties to be displayed cell_names = ['process', 'status'] # Add each property from left to right in the current task row. Abbreviate the text to make it # fit better for cell_name in cell_names: task_table.add_cell(data=abbreviate_text(task.get_value(cell_name), 15), row=current_task_row) row_cell = table.add_cell(task_table) row_cell.add_style('border', '1px solid #EEE') row_cell.add_style('vertical-align', 'top') row_cell.add_style('width', '{0}%'.format(76.0 / len(header_groups))) else: table.add_cell()