def handle_td(my, td): super(LoginTableElementWdg, my).handle_td(td) task = my.get_current_sobject() if task: search_type = task.get_value('search_type') search_id = task.get_value('search_id') if not search_type or not search_id: return search_key = SearchKey.build_search_key(search_type, search_id, column='id') from pyasm.common import SObjectSecurityException try: parent = Search.get_by_search_key(search_key) pipeline = Pipeline.get_by_sobject(parent) if pipeline: attrs = pipeline.get_process_attrs(task.get_value('process')) td.add_attr('spt_pipeline_code', attrs.get('%s_login_group'%my.get_name())) except SObjectSecurityException, e: pass except SearchException, e: if e.__str__().find('not registered') != -1: pass elif e.__str__().find('does not exist for database') != -1: pass elif e.__str__().find('Cannot find project') != -1: pass else: raise
def get_input_state(self, sobject, process): pipeline = Pipeline.get_by_sobject(sobject) # use the first input process input_processes = pipeline.get_input_processes(process) if not input_processes: return {} # get the first process for now p = input_processes[0] process_name = p.get_name() key = self.get_state_key(sobject, process_name) from tactic_client_lib import TacticServerStub server = TacticServerStub.get() from pyasm.common import jsonloads message = server.get_message(key) message = message.get("message") if not message: state = {} else: state = jsonloads(message) return state
def execute(my): key = "enable_workflow_engine" from prod_setting import ProdSetting setting = ProdSetting.get_value_by_key(key) if setting not in [True, 'true']: return # find the node in the pipeline task = my.get_caller() sobject = task.get_parent() if not sobject: return pipeline = None process_code = task.get_value("process_code", no_exception=True) if process_code: process_sobj = Search.get_by_code("config/process", process_code) if process_sobj: pipeline_code = process_sobj.get_value("pipeline_code") pipeline = Pipeline.get_by_code("sthpw/pipeline", pipeline_code) if not pipeline: pipeline = Pipeline.get_by_sobject(sobject) if not pipeline: return process_name = task.get_value("process") status = task.get_value("status") process = pipeline.get_process(process_name) if not process: # we don't have enough info here return node_type = process.get_type() process_name = process.get_name() event = "process|%s" % status.lower() output = { 'sobject': sobject, 'pipeline': pipeline, 'process': process_name, } Trigger.call(task, event, output=output)
def preprocess(my): if my.sobjects: try: search = Search(Task) search_ids = [x.get_id() for x in my.sobjects] search.add_filters("search_id", search_ids) search_type = my.sobjects[0].get_search_type() search.add_filter("search_type", search_type) # go thru children of main search search = my.alter_task_search(search, prefix='children') # go thru Local Search search = my.alter_task_search( search, prefix='main_body', prefix_namespace=my.__class__.__name__) sobj = my.sobjects[0] pipeline = Pipeline.get_by_sobject(sobj) if pipeline: process_names = pipeline.get_process_names(True) search.add_enum_order_by("process", process_names) else: search.add_order_by("process") search.add_order_by("id") tasks = search.get_sobjects() # create a data structure for task in tasks: search_type = task.get_value("search_type") search_id = task.get_value("search_id") search_key = "%s|%s" % (search_type, search_id) sobject_tasks = my.data.get(search_key) if not sobject_tasks: sobject_tasks = [] my.data[search_key] = sobject_tasks sobject_tasks.append(task) except: from tactic.ui.app import SearchWdg parent_search_type = get_search_type() SearchWdg.clear_search_data(parent_search_type) raise
def execute(my): from pyasm.biz import Task, Pipeline src_task = my.get_caller() process = src_task.get_value("process") status = src_task.get_value("status") pipeline_code = src_task.get_value("pipeline_code") if pipeline_code == "approval": tasks = src_task.get_output_tasks() if status == "Revise": pass else: tasks = src_task.get_output_tasks(type="approval") # for approval, the task must be completed completion = src_task.get_completion() if completion != 100: return if not tasks: # autocreate ?? parent = src_task.get_parent() pipeline = Pipeline.get_by_sobject(parent) if not pipeline: return processes = pipeline.get_output_processes(process, type="approval") if not processes: return if processes: print "Missing task: ", processes # set those approvals to "Pending" for task in tasks: task.set_value("status", "Pending") task.commit()
def preprocess(my): if my.sobjects: try: search = Search(Task) search_ids = [x.get_id() for x in my.sobjects] search.add_filters("search_id", search_ids) search_type = my.sobjects[0].get_search_type() search.add_filter("search_type", search_type) # go thru children of main search search = my.alter_task_search(search, prefix='children') # go thru Local Search search = my.alter_task_search(search, prefix='main_body', prefix_namespace=my.__class__.__name__) sobj = my.sobjects[0] pipeline = Pipeline.get_by_sobject(sobj) if pipeline: process_names = pipeline.get_process_names(True) search.add_enum_order_by("process", process_names) else: search.add_order_by("process") search.add_order_by("id") tasks = search.get_sobjects() # create a data structure for task in tasks: search_type = task.get_value("search_type") search_id = task.get_value("search_id") search_key = "%s|%s" % (search_type, search_id) sobject_tasks = my.data.get(search_key) if not sobject_tasks: sobject_tasks = [] my.data[search_key] = sobject_tasks sobject_tasks.append(task) except: from tactic.ui.app import SearchWdg parent_search_type = get_search_type() SearchWdg.clear_search_data(parent_search_type) raise
def execute(my): web = WebContainer.get_web() value = web.get_form_value('value') if my.search_key == None or value == None or my.attr_name == None: raise CommandExitException() sobject = Search.get_by_search_key(my.search_key) old_value = sobject.get_value(my.attr_name) sobject.set_value(my.attr_name, value) sobject.commit() # setting target attributes if sobject is a task if sobject.get_search_type_obj().get_base_key() == Task.SEARCH_TYPE: task = sobject # FIXME: not sure what this if for??? my.users = [task.get_value("assigned")] process_name = task.get_value('process') task_description = task.get_value("description") my.parent = task.get_parent() # it should be task, notification will get the parent in the # email trigger logic my.sobject = task code = my.parent.get_code() name = my.parent.get_name() my.info['parent_centric'] = True my.description = "%s set to '%s' for %s (%s), task: %s, %s" % (\ my.attr_name.capitalize(), value, code, name, process_name, task_description) # set the states of the command pipeline = Pipeline.get_by_sobject(my.parent) process = pipeline.get_process(process_name) completion = task.get_completion() if pipeline and process: my.set_process(process_name) my.set_pipeline_code( pipeline.get_code() ) if completion == 100: my.set_event_name("task/approved") else: my.set_event_name("task/change") else: my.sobject = sobject code = my.sobject.get_code() my.description = "%s set to '%s' for %s" % (\ my.attr_name.capitalize(), value, code) process_name = "None" my.info['parent_centric'] = False my.sobjects.append(my.sobject) # set the information about this command my.info['to'] = value my.info['process'] = process_name
def get_display(self): self.task_per_process_dict = {} # get the sobject and relevent parameters sobject = self.get_current_sobject() search_type = sobject.get_search_type() if self.pipeline_code: pipeline = Pipeline.get_by_code(self.pipeline_code) else: pipeline = Pipeline.get_by_sobject(sobject, allow_default=True) if not pipeline: # while default is auto-generated, an empty pipeline code will trigger this Environment.add_warning('missing pipeline code', \ "Pipeline code is empty for [%s]" %sobject.get_code()) return if self.include_sub_task_value: self.recurse = True processes = pipeline.get_processes(recurse=self.recurse) # filter out process names if self.process_names != None: filtered_processes = [] for process in processes: if process.get_name() in self.process_names: filtered_processes.append(process) processes = filtered_processes # draw the proceses top = DivWdg() action = DivWdg() action.add_style("float: right") top.add(action) table = Table() table.add_style("font-size: 11px") top.add(table) #if self.max_count: # percent_width = float(len(processes)) / float(self.max_count+1) * 100 #else: # percent_width = 100 # we want them more squeezed together when in abbr mode if self.label_select_value != 'abbr': percent_width = 100 table.add_style("width: %d%%" % percent_width) tr = table.add_row() for process in processes: completion_wdg = self.get_completion(sobject, process,\ len(processes)) if not completion_wdg: continue td = table.add_cell(completion_wdg) td.add_style('border-width: 0px') tr = table.add_row(css='underline') tr.add_color("color", "color") label_format = self.get_option("label_format") if not label_format: label_format = self.label_select_value tup_list = self._get_labels(processes, label_format, show_sub_pipeline=self.is_ajax()) style = '' for i, tup in enumerate(tup_list): name, process = tup span = SpanWdg() child_pipeline = process.get_child_pipeline() if child_pipeline: title = SpanWdg() title.add("[%s]" % name) title.add_style("margin-left: -5px") swap = SwapDisplayWdg.get_triangle_wdg() content_id = '%s_%s' % (sobject.get_search_key(), child_pipeline.get_id()) content_id = self.generate_unique_id(content_id) content = DivWdg(id=content_id) SwapDisplayWdg.create_swap_title(title, swap, content) dyn_load = AjaxLoader(display_id=content_id) args_dict = {'search_type': sobject.get_search_type()} args_dict['search_id'] = sobject.get_id() args_dict['pipeline_skey'] = child_pipeline.get_search_key() dyn_load.set_load_method('_get_child_wdg') dyn_load.set_load_class('pyasm.widget.ParallelStatusWdg', load_args=args_dict) dyn_load.add_element_name('cal_sub_task') on_script = dyn_load.get_on_script(load_once=True) swap.add_action_script(on_script, "set_display_off('%s')" % content_id) script = "if ($(%s).getStyle('display')=='none') {%s}" \ %(swap.swap1_id, on_script) title.add_event('onclick', script) span.add(swap) span.add(title) span.add(HtmlElement.br()) span.add(HtmlElement.br()) span.add(content) else: span.add(name) if self.task_per_process_dict.get(process) == 0: span.add_class('unused') if label_format == 'small' or label_format == 'abbr': span.add_class('smaller') if not label_format == "none": table.add_cell(span) return top
def handle_instance(my, table, instance, asset, node_name='', publish=True, allow_ref_checkin=False): # handle the case where asset is not defined if not asset: table.add_row() table.add_blank_cell() table.add_blank_cell() # FIXME: Maya specific parts = instance.split(":") instance_name = parts[0] asset_code = parts[1] if instance_name == asset_code: table.add_cell(instance_name) else: table.add_cell(instance) td = table.add_cell() td.add("< %s node >" % my.session.get_node_type(instance_name)) table.add_blank_cell() return # get the pipeline for this asset and handlers for the pipeline process_name = my.process_select.get_value() handler_hidden = my.get_handler_input(asset, process_name) pipeline = Pipeline.get_by_sobject(asset) # TEST: switch this to using node name instead, if provided if node_name: instance_node = my.session.get_node(node_name) else: instance_node = my.session.get_node(instance) if instance_node is None: return if Xml.get_attribute(instance_node, "reference") == "true": is_ref = True else: is_ref = False namespace = Xml.get_attribute(instance_node, "namespace") if not namespace: namespace = instance asset_code = asset.get_code() is_set = False if asset.get_value('asset_type', no_exception=True) in ['set', 'section']: is_set = True tr = table.add_row() if is_set: tr.add_class("group") if publish and (allow_ref_checkin or not is_ref): checkbox = CheckboxWdg("asset_instances") if is_set: checkbox = CheckboxWdg("set_instances") checkbox.set_option("value", "%s|%s|%s" % \ (namespace, asset_code, instance) ) checkbox.set_persist_on_submit() td = table.add_cell(checkbox) else: td = table.add_blank_cell() # only one will be added even if there are multiple if handler_hidden: td.add(handler_hidden) # add the thumbnail thumb = ThumbWdg() thumb.set_name("images") thumb.set_sobject(asset) thumb.set_icon_size(60) table.add_cell(thumb) info_wdg = Widget() info_wdg.add(HtmlElement.b(instance)) if not node_name: node_name = '%s - %s' % (asset_code, asset.get_name()) info_div = DivWdg(node_name) info_div.add_style('font-size: 0.8em') info_wdg.add(info_div) info_div.add(HtmlElement.br(2)) if pipeline: info_div.add(pipeline.get_code()) table.add_cell(info_wdg) # by default can't checkin references if not allow_ref_checkin and is_ref: #icon = IconWdg("error", IconWdg.ERROR) #td = table.add_cell(icon) td = table.add_cell() td.add(HtmlElement.b("Ref. instance")) ''' import_button = ProdIconButtonWdg('import') import_button.add_event('onclick', "import_instance('%s')" %instance) td.add(import_button) ''' table.add_cell(my.get_save_wdg(my.current_sobject)) elif publish: textarea = TextAreaWdg() textarea.set_persist_on_submit() textarea.set_name("%s_description" % instance) textarea.set_attr("cols", "35") textarea.set_attr("rows", "2") table.add_cell(textarea) table.add_cell(my.get_save_wdg(my.current_sobject)) else: table.add_blank_cell() table.add_blank_cell()
def handle_instance(my, table, instance, asset, node_name='', publish=True, allow_ref_checkin=False): # handle the case where asset is not defined if not asset: table.add_row() table.add_blank_cell() table.add_blank_cell() # FIXME: Maya specific parts = instance.split(":") instance_name = parts[0] asset_code = parts[1] if instance_name == asset_code: table.add_cell(instance_name) else: table.add_cell(instance) td = table.add_cell() td.add("< %s node >" % my.session.get_node_type(instance_name)) table.add_blank_cell() return # get the pipeline for this asset and handlers for the pipeline process_name = my.process_select.get_value() handler_hidden = my.get_handler_input(asset, process_name) pipeline = Pipeline.get_by_sobject(asset) # TEST: switch this to using node name instead, if provided if node_name: instance_node = my.session.get_node(node_name) else: instance_node = my.session.get_node(instance) if instance_node is None: return if Xml.get_attribute(instance_node,"reference") == "true": is_ref = True else: is_ref = False namespace = Xml.get_attribute(instance_node, "namespace") if not namespace: namespace = instance asset_code = asset.get_code() is_set = False if asset.get_value('asset_type', no_exception=True) in ['set','section']: is_set = True tr = table.add_row() if is_set: tr.add_class("group") if publish and (allow_ref_checkin or not is_ref): checkbox = CheckboxWdg("asset_instances") if is_set: checkbox = CheckboxWdg("set_instances") checkbox.set_option("value", "%s|%s|%s" % \ (namespace, asset_code, instance) ) checkbox.set_persist_on_submit() td = table.add_cell(checkbox) else: td = table.add_blank_cell() # only one will be added even if there are multiple if handler_hidden: td.add(handler_hidden) # add the thumbnail thumb = ThumbWdg() thumb.set_name("images") thumb.set_sobject(asset) thumb.set_icon_size(60) table.add_cell(thumb) info_wdg = Widget() info_wdg.add(HtmlElement.b(instance)) if not node_name: node_name = '%s - %s' %(asset_code, asset.get_name()) info_div = DivWdg(node_name) info_div.add_style('font-size: 0.8em') info_wdg.add(info_div) info_div.add(HtmlElement.br(2)) if pipeline: info_div.add(pipeline.get_code()) table.add_cell(info_wdg) # by default can't checkin references if not allow_ref_checkin and is_ref: #icon = IconWdg("error", IconWdg.ERROR) #td = table.add_cell(icon) td = table.add_cell() td.add(HtmlElement.b("Ref. instance")) ''' import_button = ProdIconButtonWdg('import') import_button.add_event('onclick', "import_instance('%s')" %instance) td.add(import_button) ''' table.add_cell(my.get_save_wdg(my.current_sobject) ) elif publish: textarea = TextAreaWdg() textarea.set_persist_on_submit() textarea.set_name("%s_description" % instance) textarea.set_attr("cols", "35") textarea.set_attr("rows", "2") table.add_cell(textarea) table.add_cell(my.get_save_wdg(my.current_sobject) ) else: table.add_blank_cell() table.add_blank_cell()
def get_display(my): web = WebContainer.get_web() # this needs to be a BaseInputWdg since UserFilterWdg is hideable user_filter = FilterSelectWdg("user_filter") user_filter = user_filter.get_values() #login = Environment.get_security().get_login() #user = login.get_value("login") if my.is_refresh: widget = Widget() my.init_cgi() else: my.sobject = my.get_current_sobject() widget = DivWdg(id="task_elem_%s"% my.sobject.get_id()) widget.add_class('spt_task_panel') try: my.set_as_panel(widget) except: pass #TODO: remove this my.init_setup(widget) #my.set_ajax_top(widget) table = Table(css="minimal") table.add_style("width: 100%") # get all of the tasks related to this sobject search_type = my.sobject.get_search_type() search_id = my.sobject.get_id() if my.data: tasks = my.data.get("%s|%s" % (search_type,search_id) ) else: tasks = Task.get_by_sobject(my.sobject) my.data[my.sobject.get_search_key()] = tasks if not tasks: tasks = [] task_statuses_filter = web.get_form_values("task_status") show_sub_tasks = False if not task_statuses_filter: # NOTE: Not sure if this is correct!! # have to do this because it is impossible to tell if a checkbox # is empty or not there. This is used for pages that do not have # tasks_status checkboxes show_all_tasks = True else: cb = FilterCheckboxWdg('show_all_tasks') show_all_tasks = cb.is_checked(False) sub_cb = FilterCheckboxWdg('show_sub_tasks') show_sub_tasks = sub_cb.is_checked(False) # trim down the process list """ if not show_sub_tasks: process_list = [x for x in process_list if "/" not in x] """ pipeline = Pipeline.get_by_sobject(my.sobject) # retrieve the pipeline if not pipeline: td = table.add_cell("<br/><i>No pipeline</i>") td.add_style("text-align: center") return table # store completion per process first in a dict # reset it first my.process_completion_dict = {} for task in tasks: task_process = task.get_value("process") status_attr = task.get_attr('status') percent = status_attr.get_percent_completion() my.store_completion(task_process, percent) security = WebContainer.get_security() me = Environment.get_user_name() for task in tasks: has_valid_status = True task_pipeline = task.get_pipeline() task_statuses = task_pipeline.get_process_names() task_process = task.get_value("process") # Commenting this out. It is not very meaningful in 2.5 ... # we need a better mechanism. The end result of this code # is that "admin" never sees any tasks #if security.check_access("public_wdg", "SObjectTaskTableElement|unassigned", "deny", is_match=True): # assignee = task.get_value("assigned") # if assignee != me: # continue if not show_all_tasks: """ if process_list and task_process not in process_list: continue """ # skip sub tasks if not show_sub_tasks and '/' in task_process: continue task_status = task.get_value("status") if task_status not in task_statuses: has_valid_status = False if has_valid_status and task_status \ and task_status not in task_statuses_filter: continue # the first one shouldn't be empty if user_filter and user_filter[0] and task.get_value("assigned") not in user_filter: continue table.add_row() #link = "%s/Maya/?text_filter=%s&load_asset_process=%s" % (web.get_site_context_url().to_string(), my.sobject.get_code(), task_process) #icon = IconButtonWdg("Open Loader", IconWdg.LOAD, False) #table.add_cell( HtmlElement.href(icon, link, target='maya') ) td = table.add_cell(css='no_wrap') description = task.get_value("description") expand = ExpandableTextWdg() expand.set_max_length(50) expand.set_value(description) assigned = task.get_value("assigned").strip() status_wdg = SimpleStatusWdg() status_wdg.set_sobject(task) status_wdg.set_name("status") # refresh myself on execution of SimpleStatusCmd #post_scripts = my.get_refresh_script(show_progress=False) post_scripts = '''var panel = bvr.src_el.getParent('.spt_task_panel'); var search_top = spt.get_cousin(bvr.src_el, '.spt_view_panel','.spt_search'); var search_val = spt.dg_table.get_search_values(search_top); var values = spt.api.Utility.get_input_values(panel); values['json'] = search_val; spt.panel.refresh(panel, values);''' status_wdg.set_post_ajax_script(post_scripts) if assigned: user_info = UserExtraInfoWdg(assigned).get_buffer_display() else: user_info = HtmlElement.i(" unassigned").get_buffer_display() info_span = SpanWdg() info_span.add(TaskExtraInfoWdg(task)) info_span.add("- ") info_span.add(" [%s]" % user_info) if UserAssignWdg.has_access() and my.get_option('supe')=='true': my._add_user_assign_wdg(task, info_span, widget) td.add( info_span ) #-------------- my.calendar_bar.set_sobject(task) # set always recalculate since each task is set individually my.calendar_bar.set_always_recal(True) #--------------- td.add_color('color','color') td.add(HtmlElement.br()) if description: td.add(expand) td.add(HtmlElement.br()) td.add(status_wdg) if my.last_process_finished(pipeline, task_process): dot = IconWdg(icon=IconWdg.DOT_GREEN) dot.add_tip("All dependent processs complete") dot.add_style('float','left') dot.add_style('display','block') td.add(dot) else: dot = IconWdg(icon=IconWdg.DOT_RED) dot.add_tip("Dependent process in progress") dot.add_style('float','left') dot.add_style('display','block') td.add(dot) date_display = None if my.get_option('simple_date') == 'true': start_wdg = DateWdg() start_wdg.set_option("pattern", "%b %d") start_wdg.set_name('bid_start_date') start_wdg.set_sobject(task) end_wdg = DateWdg() end_wdg.set_name('bid_end_date') end_wdg.set_option("pattern", "%b %d") end_wdg.set_sobject(task) date_display = '%s - %s' %(start_wdg.get_buffer_display(), \ end_wdg.get_buffer_display()) else: my.calendar_bar.set_sobject(task) # set always recalculate since each task is set individuallly my.calendar_bar.set_always_recal(True) my.calendar_bar.set_option("width", "40") my.calendar_bar.set_option("bid_edit", my.get_option('bid_edit')) date_display = my.calendar_bar.get_buffer_display() #td = table.add_cell(date_display, css='smaller') td.add(FloatDivWdg(date_display, float='right', css='smaller')) #td.set_style("width: 120; padding-left: 15px") # This uses the parallel status widget to display status of # dependent tasks dependent_processes = pipeline.get_input_contexts(task_process) from parallel_status import ParallelStatusWdg dep_status_div = DivWdg() dep_status_div.add_style("padding-right: 10px") dep_status_wdg = ParallelStatusWdg() dep_status_wdg.set_process_names(dependent_processes) dep_status_wdg.set_label_format("abbr") dep_status_wdg.set_sobject(my.sobject) #dep_status_wdg.preprocess() dep_status_wdg.set_data(my.data) dep_status_div.add(dep_status_wdg) td.add(dep_status_div) #td.add_style("border-style: solid") #td.add_style("border-bottom: 1px") #td.add_style("border-color: #999") td.add_style("padding: 3px 0 3px 0") widget.add(table) return widget
def get_display(my): my.task_per_process_dict = {} # get the sobject and relevent parameters sobject = my.get_current_sobject() search_type = sobject.get_search_type() if my.pipeline_code: pipeline = Pipeline.get_by_code(my.pipeline_code) else: pipeline = Pipeline.get_by_sobject(sobject, allow_default=True) if not pipeline: # while default is auto-generated, an empty pipeline code will trigger this Environment.add_warning('missing pipeline code', \ "Pipeline code is empty for [%s]" %sobject.get_code()) return if my.include_sub_task_value: my.recurse = True processes = pipeline.get_processes(recurse=my.recurse) # filter out process names if my.process_names != None: filtered_processes = [] for process in processes: if process.get_name() in my.process_names: filtered_processes.append(process) processes = filtered_processes # draw the proceses top = DivWdg() action = DivWdg() action.add_style("float: right") top.add(action) table = Table() table.add_style("font-size: 11px") top.add(table) #if my.max_count: # percent_width = float(len(processes)) / float(my.max_count+1) * 100 #else: # percent_width = 100 # we want them more squeezed together when in abbr mode if my.label_select_value != 'abbr': percent_width = 100 table.add_style("width: %d%%" % percent_width) tr = table.add_row() for process in processes: completion_wdg = my.get_completion(sobject, process,\ len(processes)) if not completion_wdg: continue td = table.add_cell( completion_wdg ) td.add_style('border-width: 0px') tr = table.add_row(css='underline') tr.add_color("color", "color") label_format = my.get_option("label_format") if not label_format: label_format = my.label_select_value tup_list = my._get_labels(processes, label_format, show_sub_pipeline=my.is_ajax()) style = '' for i, tup in enumerate(tup_list): name, process = tup span = SpanWdg() child_pipeline = process.get_child_pipeline() if child_pipeline: title = SpanWdg() title.add("[%s]" % name) title.add_style("margin-left: -5px") swap = SwapDisplayWdg.get_triangle_wdg() content_id = '%s_%s' %(sobject.get_search_key(), child_pipeline.get_id()) content_id = my.generate_unique_id(content_id) content = DivWdg(id=content_id) SwapDisplayWdg.create_swap_title(title, swap, content) dyn_load = AjaxLoader(display_id=content_id) args_dict = {'search_type': sobject.get_search_type()} args_dict['search_id'] = sobject.get_id() args_dict['pipeline_skey'] = child_pipeline.get_search_key() dyn_load.set_load_method('_get_child_wdg') dyn_load.set_load_class('pyasm.widget.ParallelStatusWdg', load_args=args_dict) dyn_load.add_element_name('cal_sub_task') on_script = dyn_load.get_on_script(load_once=True) swap.add_action_script(on_script, "set_display_off('%s')" %content_id) script = "if ($(%s).getStyle('display')=='none') {%s}" \ %(swap.swap1_id, on_script) title.add_event('onclick', script) span.add(swap) span.add(title) span.add(HtmlElement.br()) span.add(HtmlElement.br()) span.add(content) else: span.add(name) if my.task_per_process_dict.get(process) == 0: span.add_class('unused') if label_format == 'small' or label_format == 'abbr': span.add_class('smaller') if not label_format == "none": table.add_cell(span) return top
def get_info_wdg(my): widget = Widget() table = Table() table.set_class("minimal") table.add_style("font-size: 0.8em") context_option = my.kwargs.get('context') context_expr_option = my.kwargs.get('context_expr') pipeline_option = my.kwargs.get('pipeline') in ['true', True, 'True'] setting_option = my.kwargs.get('setting') context_name = "%s|context" % my.get_input_name() text = None span1 = SpanWdg("Context", id='context_mode') span2 = SpanWdg("Context<br/>/Subcontext", id='subcontext_mode') span2.add_style('display', 'none') table.add_cell(span1) table.add_data(span2) if context_expr_option or context_option or setting_option: # add swap display for subcontext only if there is setting or context option swap = SwapDisplayWdg() table.add_data(SpanWdg(swap, css='small')) swap.set_display_widgets(StringWdg('[+]'), StringWdg('[-]')) subcontext_name = "%s|subcontext" % my.get_input_name() subcontext = SpanWdg('/ ', css='small') subcontext.add(TextWdg(subcontext_name)) subcontext.add_style('display', 'none') subcontext.set_id(subcontext_name) on_script = "set_display_on('%s');swap_display('subcontext_mode','context_mode')" % subcontext_name off_script = "set_display_off('%s');get_elements('%s').set_value(''); "\ "swap_display('context_mode','subcontext_mode')"%(subcontext_name, subcontext_name) swap.add_action_script(on_script, off_script) text = SelectWdg(context_name) if my.sobjects: text.set_sobject(my.sobjects[0]) if context_expr_option: text.set_option('values_expr', context_expr_option) elif context_option: text.set_option('values', context_option) elif setting_option: text.set_option('setting', setting_option) td = table.add_cell(text) table.add_data(subcontext) elif pipeline_option: from pyasm.biz import Pipeline sobject = my.sobjects[0] pipeline = Pipeline.get_by_sobject(sobject) context_names = [] process_names = pipeline.get_process_names(recurse=True) for process in process_names: context_names.append(pipeline.get_output_contexts(process)) text = SelectWdg(context_name) text.set_option('values', process_names) table.add_cell(text) else: text = TextWdg(context_name) table.add_cell(text) hint = HintWdg('If not specified, the default is [publish]') table.add_data(hint) revision_cb = CheckboxWdg('%s|is_revision' %my.get_input_name(),\ label='is revision', css='med') table.add_data(revision_cb) table.add_row() table.add_cell("Comment") textarea = TextAreaWdg("%s|description" % my.get_input_name()) table.add_cell(textarea) widget.add(table) return widget
def get_info_wdg(my): widget = Widget() table = Table() table.set_class("minimal") table.add_style("font-size: 0.8em") context_option = my.kwargs.get('context') context_expr_option = my.kwargs.get('context_expr') pipeline_option = my.kwargs.get('pipeline') in ['true', True, 'True'] setting_option = my.kwargs.get('setting') context_name = "%s|context" % my.get_input_name() text = None span1 = SpanWdg("Context", id='context_mode') span2 = SpanWdg("Context<br/>/Subcontext", id='subcontext_mode') span2.add_style('display','none') table.add_cell(span1) table.add_data(span2) if context_expr_option or context_option or setting_option: # add swap display for subcontext only if there is setting or context option swap = SwapDisplayWdg() table.add_data(SpanWdg(swap, css='small')) swap.set_display_widgets(StringWdg('[+]'), StringWdg('[-]')) subcontext_name = "%s|subcontext" % my.get_input_name() subcontext = SpanWdg('/ ', css='small') subcontext.add(TextWdg(subcontext_name)) subcontext.add_style('display','none') subcontext.set_id(subcontext_name) on_script = "set_display_on('%s');swap_display('subcontext_mode','context_mode')"%subcontext_name off_script = "set_display_off('%s');get_elements('%s').set_value(''); "\ "swap_display('context_mode','subcontext_mode')"%(subcontext_name, subcontext_name) swap.add_action_script(on_script, off_script) text = SelectWdg(context_name) if my.sobjects: text.set_sobject(my.sobjects[0]) if context_expr_option: text.set_option('values_expr', context_expr_option) elif context_option: text.set_option('values', context_option) elif setting_option: text.set_option('setting', setting_option) td = table.add_cell(text) table.add_data(subcontext) elif pipeline_option: from pyasm.biz import Pipeline sobject = my.sobjects[0] pipeline = Pipeline.get_by_sobject(sobject) context_names = [] process_names = pipeline.get_process_names(recurse=True) for process in process_names: context_names.append(pipeline.get_output_contexts(process)) text = SelectWdg(context_name) text.set_option('values', process_names) table.add_cell(text) else: text = TextWdg(context_name) table.add_cell(text) hint = HintWdg('If not specified, the default is [publish]') table.add_data(hint) revision_cb = CheckboxWdg('%s|is_revision' %my.get_input_name(),\ label='is revision', css='med') table.add_data(revision_cb) table.add_row() table.add_cell("Comment") textarea = TextAreaWdg("%s|description"% my.get_input_name()) table.add_cell(textarea) widget.add(table) return widget
def handle_action(my): my.log_message(my.sobject, my.process, "in_prgress") my.set_all_tasks(my.sobject, my.process, "in_progress") my.run_callback(my.pipeline, my.process, "action") pipeline = my.input.get("pipeline") process = my.input.get("process") sobject = my.input.get("sobject") process_obj = pipeline.get_process(process) related_search_type = process_obj.get_attribute("search_type") related_status = process_obj.get_attribute("status") related_process = process_obj.get_attribute("process") related_scope = process_obj.get_attribute("scope") # get the node's triggers if not related_search_type: search = Search("config/process") search.add_filter("process", process) search.add_filter("pipeline_code", pipeline.get_code()) process_sobj = search.get_sobject() workflow = process_sobj.get_json_value("workflow") related_search_type = workflow.get("search_type") related_proces = workflow.get("proces") related_status = workflow.get("status") related_scope = workflow.get("scope") if not related_search_type: print "WARNING: no related search_type found" return if not related_process: print "WARNING: no related process found" return if related_search_type.startswith("@"): expression = related_search_type else: expression = "@SOBJECT(%s)" % related_search_type if related_scope == "global": related_sobjects = Search.eval(expression) else: related_sobjects = Search.eval(expression, sobjects=[sobject]) if not related_sobjects: event = "process|complete" Trigger.call(my, event, my.input) return # log a message storing these related sobjects message = {} for related_sobject in related_sobjects: related_search_key = related_sobject.get_search_key() message[related_search_key] = False message = jsondumps(message) search_key = sobject.get_search_key() key = "%s|%s|dependent" % (sobject.get_search_key(), process) from tactic_client_lib import TacticServerStub server = TacticServerStub.get() server.log_message(key, message) for related_sobject in related_sobjects: # TEST: do this to grab from cache # This is for unittests which don't necessarily commit changes related_sobject = Search.get_by_search_key(related_sobject.get_search_key()) complete = True num_complete = 0 # look at the message key = "%s|%s|dependent" % (related_sobject.get_search_key(), related_process) message_sobj = Search.get_by_code("sthpw/message", key) if message_sobj: message = message_sobj.get_json_value("message") message[search_key] = True message_sobj.set_json_value("message", message) message_sobj.commit() # test for completeness for name, value in message.items(): if value == False: complete = False else: num_complete += 1 else: # TODO: # This means that the receiving related sobject has not cached print ("WARNING: No dependencies cached [%s]" % related_process) return #raise Exception("No dependendies casched") # FIXME: this should be handled by "multiple inputs" if complete: related_pipeline = Pipeline.get_by_sobject(related_sobject) if not related_process: # get the first one related_processes = related_pipeline.get_processes() related_process = related_processes[0] if related_status == "in_progress": event = "process|action" else: event = "process|%s" % related_status input = { 'sobject': related_sobject, 'pipeline': related_pipeline, 'process': related_process } Trigger.call(my, event, input) event = "process|complete" Trigger.call(my, event, my.input)
def execute(my): """ key = "enable_workflow_engine" from prod_setting import ProdSetting setting = ProdSetting.get_value_by_key(key) if setting not in [True, 'true']: return """ # find the node in the pipeline task = my.get_caller() sobject = task.get_parent() if not sobject: return pipeline = None process_code = task.get_value("process_code", no_exception=True) if process_code: process_sobj = Search.get_by_code("config/process", process_code) if process_sobj: pipeline_code = process_sobj.get_value("pipeline_code") pipeline = Pipeline.get_by_code("sthpw/pipeline", pipeline_code) if not pipeline: pipeline = Pipeline.get_by_sobject(sobject) if not pipeline: return if pipeline.get_value("use_workflow", no_exception=True) in [False, "false"]: return process_name = task.get_value("process") status = task.get_value("status") if status.lower() in PREDEFINED: status = status.lower() # handle the approve case (which really means complete) if status == "approved": status = "complete" process = pipeline.get_process(process_name) if not process: # we don't have enough info here return node_type = process.get_type() process_name = process.get_name() if status in PREDEFINED: event = "process|%s" % status else: event = "process|custom" output = { 'sobject': sobject, 'pipeline': pipeline, 'process': process_name, 'status': status } Trigger.call(task, event, output=output)
def get_display(self): web = WebContainer.get_web() # this needs to be a BaseInputWdg since UserFilterWdg is hideable user_filter = FilterSelectWdg("user_filter") user_filter = user_filter.get_values() #login = Environment.get_security().get_login() #user = login.get_value("login") if self.is_refresh: widget = Widget() self.init_cgi() else: self.sobject = self.get_current_sobject() widget = DivWdg(id="task_elem_%s"% self.sobject.get_id()) widget.add_class('spt_task_panel') try: self.set_as_panel(widget) except: pass #TODO: remove this self.init_setup(widget) #self.set_ajax_top(widget) table = Table(css="minimal") table.add_style("width: 100%") # get all of the tasks related to this sobject search_type = self.sobject.get_search_type() search_id = self.sobject.get_id() if self.data: tasks = self.data.get("%s|%s" % (search_type,search_id) ) else: tasks = Task.get_by_sobject(self.sobject) self.data[self.sobject.get_search_key()] = tasks if not tasks: tasks = [] task_statuses_filter = web.get_form_values("task_status") show_sub_tasks = False if not task_statuses_filter: # NOTE: Not sure if this is correct!! # have to do this because it is impossible to tell if a checkbox # is empty or not there. This is used for pages that do not have # tasks_status checkboxes show_all_tasks = True else: cb = FilterCheckboxWdg('show_all_tasks') show_all_tasks = cb.is_checked(False) sub_cb = FilterCheckboxWdg('show_sub_tasks') show_sub_tasks = sub_cb.is_checked(False) # trim down the process list """ if not show_sub_tasks: process_list = [x for x in process_list if "/" not in x] """ pipeline = Pipeline.get_by_sobject(self.sobject) # retrieve the pipeline if not pipeline: td = table.add_cell("<br/><i>No pipeline</i>") td.add_style("text-align: center") return table # store completion per process first in a dict # reset it first self.process_completion_dict = {} for task in tasks: task_process = task.get_value("process") status_attr = task.get_attr('status') percent = status_attr.get_percent_completion() self.store_completion(task_process, percent) security = WebContainer.get_security() me = Environment.get_user_name() for task in tasks: has_valid_status = True task_pipeline = task.get_pipeline() task_statuses = task_pipeline.get_process_names() task_process = task.get_value("process") # Commenting this out. It is not very meaningful in 2.5 ... # we need a better mechanism. The end result of this code # is that "admin" never sees any tasks #if security.check_access("public_wdg", "SObjectTaskTableElement|unassigned", "deny", is_match=True): # assignee = task.get_value("assigned") # if assignee != me: # continue if not show_all_tasks: """ if process_list and task_process not in process_list: continue """ # skip sub tasks if not show_sub_tasks and '/' in task_process: continue task_status = task.get_value("status") if task_status not in task_statuses: has_valid_status = False if has_valid_status and task_status \ and task_status not in task_statuses_filter: continue # the first one shouldn't be empty if user_filter and user_filter[0] and task.get_value("assigned") not in user_filter: continue table.add_row() #link = "%s/Maya/?text_filter=%s&load_asset_process=%s" % (web.get_site_context_url().to_string(), self.sobject.get_code(), task_process) #icon = IconButtonWdg("Open Loader", IconWdg.LOAD, False) #table.add_cell( HtmlElement.href(icon, link, target='maya') ) td = table.add_cell(css='no_wrap') description = task.get_value("description") expand = ExpandableTextWdg() expand.set_max_length(50) expand.set_value(description) assigned = task.get_value("assigned").strip() status_wdg = SimpleStatusWdg() status_wdg.set_sobject(task) status_wdg.set_name("status") # refresh myself on execution of SimpleStatusCmd #post_scripts = self.get_refresh_script(show_progress=False) post_scripts = '''var panel = bvr.src_el.getParent('.spt_task_panel'); var search_top = spt.get_cousin(bvr.src_el, '.spt_view_panel','.spt_search'); var search_val = spt.dg_table.get_search_values(search_top); var values = spt.api.Utility.get_input_values(panel); values['json'] = search_val; spt.panel.refresh(panel, values);''' status_wdg.set_post_ajax_script(post_scripts) if assigned: user_info = UserExtraInfoWdg(assigned).get_buffer_display() else: user_info = HtmlElement.i(" unassigned").get_buffer_display() info_span = SpanWdg() info_span.add(TaskExtraInfoWdg(task)) info_span.add("- ") info_span.add(" [%s]" % user_info) if UserAssignWdg.has_access() and self.get_option('supe')=='true': self._add_user_assign_wdg(task, info_span, widget) td.add( info_span ) #-------------- self.calendar_bar.set_sobject(task) # set always recalculate since each task is set individually self.calendar_bar.set_always_recal(True) #--------------- td.add_color('color','color') td.add(HtmlElement.br()) if description: td.add(expand) td.add(HtmlElement.br()) td.add(status_wdg) if self.last_process_finished(pipeline, task_process): dot = IconWdg(icon=IconWdg.DOT_GREEN) dot.add_tip("All dependent processs complete") dot.add_style('float','left') dot.add_style('display','block') td.add(dot) else: dot = IconWdg(icon=IconWdg.DOT_RED) dot.add_tip("Dependent process in progress") dot.add_style('float','left') dot.add_style('display','block') td.add(dot) date_display = None if self.get_option('simple_date') == 'true': start_wdg = DateWdg() start_wdg.set_option("pattern", "%b %d") start_wdg.set_name('bid_start_date') start_wdg.set_sobject(task) end_wdg = DateWdg() end_wdg.set_name('bid_end_date') end_wdg.set_option("pattern", "%b %d") end_wdg.set_sobject(task) date_display = '%s - %s' %(start_wdg.get_buffer_display(), \ end_wdg.get_buffer_display()) else: self.calendar_bar.set_sobject(task) # set always recalculate since each task is set individuallly self.calendar_bar.set_always_recal(True) self.calendar_bar.set_option("width", "40") self.calendar_bar.set_option("bid_edit", self.get_option('bid_edit')) date_display = self.calendar_bar.get_buffer_display() #td = table.add_cell(date_display, css='smaller') td.add(FloatDivWdg(date_display, float='right', css='smaller')) #td.set_style("width: 120; padding-left: 15px") # This uses the parallel status widget to display status of # dependent tasks dependent_processes = pipeline.get_input_contexts(task_process) from parallel_status import ParallelStatusWdg dep_status_div = DivWdg() dep_status_div.add_style("padding-right: 10px") dep_status_wdg = ParallelStatusWdg() dep_status_wdg.set_process_names(dependent_processes) dep_status_wdg.set_label_format("abbr") dep_status_wdg.set_sobject(self.sobject) #dep_status_wdg.preprocess() dep_status_wdg.set_data(self.data) dep_status_div.add(dep_status_wdg) td.add(dep_status_div) #td.add_style("border-style: solid") #td.add_style("border-bottom: 1px") #td.add_style("border-color: #999") td.add_style("padding: 3px 0 3px 0") widget.add(table) return widget