def run(code, kwargs): code = jsondumps(code) kwargs = jsondumps(kwargs) install_dir = tacticenv.get_install_dir() cmd = '%s/src/tactic/command/js_cmd.py' % install_dir python_exec = Config.get_value("services", "python") cmd_list = [python_exec, cmd, code, kwargs] import subprocess program = subprocess.Popen(cmd_list, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE) ret_val, error = program.communicate() lines = [] start = False for line in ret_val.split("\n") : if line.startswith("~"*20): start = True continue if not start: continue lines.append(line) value = jsonloads("\n".join(lines)) return value
def add(command, kwargs, queue_type, priority, description, message_code=None): queue = SearchType.create("sthpw/queue") queue.set_value("project_code", Project.get_project_code()) #queue.set_sobject_value(sobject) if not queue_type: queue_type = "default" queue.set_value("queue", queue_type) queue.set_value("state", "pending") queue.set_value("login", Environment.get_user_name()) queue.set_value("command", command) data = jsondumps(kwargs) queue.set_value("data", data) if message_code: queue.set_value("message_code", message_code) if not priority: priority = 9999 queue.set_value("priority", priority) if description: queue.set_value("description", description) queue.set_user() queue.commit() return queue
def handle_layout_behaviors(my, layout): my.layout = layout # FIXME: not needed ... but need a way to make calling this twice safe #SwapDisplayWdg.handle_top(my.layout) class_name = my.get_option("dynamic_class") if not class_name: class_name = "tactic.ui.panel.table_layout_wdg.FastTableLayoutWdg" kwargs = jsondumps(my.kwargs) name = my.get_name() my.layout.add_relay_behavior( { 'type': 'click', 'col_name': name, 'bvr_match_class': 'spt_hidden_row_%s' % name, 'class_name': class_name, 'cbjs_action': ''' var swap_top = bvr.src_el.getElement(".spt_swap_top"); var state = swap_top.getAttribute("spt_state"); var row = bvr.src_el.getParent(".spt_table_row"); var search_key = row.getAttribute("spt_search_key"); search_key = search_key.replace(/\\&/, "\\&"); var class_name = '%s'; eval("var kwargs = " + %s); kwargs['search_key'] = search_key; kwargs['__hidden__'] = true; kwargs['src_el'] = bvr.src_el; if (state == 'on') { spt.table.remove_hidden_row(row, bvr.col_name); } else { //spt.table.add_hidden_row(row, bvr.class_name, bvr.kwargs); spt.table.add_hidden_row(row, class_name, kwargs); } ''' % (class_name, jsondumps(kwargs)) } )
def dumps(self, sobjects): sobject_list = [] for sobject in sobjects: data = sobject.get_data() sobject_list.append(data) sobjects_str = jsondumps(sobject_list) return sobjects_str
def get_custom_layout_wdg(my, layout_view): content_div = DivWdg() from tactic.ui.panel import CustomLayoutWdg layout = CustomLayoutWdg(view=layout_view) content_div.add(layout) for widget in my.widgets: name = widget.get_name() if my.input_prefix: widget.set_input_prefix(my.input_prefix) layout.add_widget(widget, name) search_key = SearchKey.get_by_sobject(my.sobjects[0], use_id=True) search_type = my.sobjects[0].get_base_search_type() element_names = my.element_names[:] for element_name in my.skipped_element_names: element_names.remove(element_name) config_xml = my.kwargs.get("config_xml") bvr = { 'type': 'click_up', 'mode': my.mode, 'element_names': element_names, 'search_key': search_key, 'input_prefix': my.input_prefix, 'view': my.view, 'config_xml': config_xml } if my.mode == 'insert': bvr['refresh'] = 'true' # for adding parent relationship in EditCmd if my.parent_key: bvr['parent_key'] = my.parent_key hidden_div = DivWdg() hidden_div.add_style("display: none") content_div.add(hidden_div) hidden = TextAreaWdg("__data__") hidden_div.add(hidden) hidden.set_value( jsondumps(bvr) ) show_action = my.kwargs.get("show_action") if show_action in [True, 'true']: content_div.add( my.get_action_html() ) return content_div
def execute(my): input_data = my.get_input_data() data = my.data # input data for the handler if my.mode == 'separate process,blocking': input_data_str = jsondumps(input_data) data_str = jsondumps(data) file = __file__ py_exec = Config.get_value("services", "python") if not py_exec: py_exec = "python" retcode = subprocess.call([py_exec, file, data_str, input_data_str]) elif my.mode == 'separate process,non-blocking': input_data_str = jsondumps(input_data) data_str = jsondumps(data) file = __file__ py_exec = Config.get_value("services", "python") if not py_exec: py_exec = "python" retcode = subprocess.Popen([py_exec, file, data_str, input_data_str]) elif my.mode == 'same process,new transaction': # run it inline trigger = ScriptTrigger() trigger.set_data(data) trigger.set_input(input_data) trigger.execute() # DEPRECATED MMS mode elif my.mode == 'MMS': # run it inline trigger = MMSScriptTrigger() trigger.set_data(data) trigger.set_input(input_data) trigger.execute()
def get_json_string(dict, use_cache=True): '''given a dictionary, return a javascript friendly json string as a js string''' dict_str = None if use_cache: data = Container.get("Html:json_str") if not data: data = {} Container.put("Html:json_str", data) key = str(dict) dict_str = data.get(key) if dict_str == None: try: dict_str = jsondumps(dict) except UnicodeDecodeError, e: if isinstance(dict, basestring): dict = dict.decode('iso-8859-1') dict_str = jsondumps(dict) dict_str = dict_str.replace('"', '"') if use_cache: data[key] = dict_str
def _test_csv_export(self): from tactic.ui.widget import CsvExportWdg view = 'table' search_type ='sthpw/task' search_view = 'auto_search:table' #search_view = '' simple_search_view = 'simple_search' search_class ='' mode = 'export_matched' element_name= 'project_tasks' filter = [{"prefix":"main_body","main_body_enabled":"on","main_body_column":"project_code","main_body_relation":"is","main_body_value":"{$PROJECT}"}, {"prefix":"main_body","main_body_enabled":"on","main_body_column":"search_type","main_body_relation":"is not","main_body_value":"sthpw/project"}] from pyasm.common import jsondumps, jsonloads values = {'json': jsondumps(filter)} element_names = ['code','id','description'] server = TacticServerStub(protocol='xmlrpc') current_project = 'vfx' server.set_project(current_project) rtn = server.get_widget('tactic.ui.widget.CsvExportWdg', args={'search_type':search_type, 'view':view,\ 'filter': filter, 'element_name': element_name, 'show_search_limit':'false', 'search_limit':-1, 'search_view':search_view, \ 'element_names': element_names, 'mode':mode, 'search_class':search_class, 'simple_search_view':simple_search_view,\ 'init_load_num':-1, 'test':True}, values=values ) expected_columns = ['code','id','description'] expected_sql = '''SELECT "sthpw"."public"."task".* FROM "sthpw"."public"."task" WHERE ( "task"."project_code" = \'%s\' AND ( "task"."search_type" != \'sthpw/project\' OR "task"."search_type" is NULL ) ) AND ("task"."s_status" != \'retired\' or "task"."s_status" is NULL) AND ("task"."s_status" != \'retired\' or "task"."s_status" is NULL) AND ("task"."s_status" != \'retired\' or "task"."s_status" is NULL) ORDER BY "task"."search_type", "task"."search_code"'''%current_project expr = "@COUNT(sthpw/task['project_code','%s']['search_type','!=','sthpw/project])"%current_project expected_count = Search.eval(expr, single=True) rtn = jsonloads(rtn) self.assertEquals(expected_columns, rtn.get('columns')) self.assertEquals(expected_sql, rtn.get('sql')) self.assertEquals(expected_count, rtn.get('count')) mode = 'export_displayed' selected_search_keys = ['sthpw/task?id=4385','sthpw/task?id=4386','sthpw/task?id=4387'] rtn = server.get_widget('tactic.ui.widget.CsvExportWdg', args={'search_type':search_type, 'view':view,\ 'filter': filter, 'element_name': element_name, 'show_search_limit':'false', 'search_limit':-1, 'search_view':search_view, \ 'element_names': element_names, 'mode':mode, 'search_class':search_class, 'simple_search_view':simple_search_view,\ 'init_load_num':-1, 'test':True, 'selected_search_keys': selected_search_keys}, values=values ) expected_count = 3 rtn = jsonloads(rtn) self.assertEquals(expected_columns, rtn.get('columns')) self.assertEquals(expected_count, rtn.get('count'))
def get_instance_wdg(self, instance_type): sorted_instances = self._get_sorted_instances() content_div = Widget() for instance in sorted_instances: item_div = self.get_item_div(instance) item_div.add_attr( "spt_search_key", SearchKey.get_by_sobject(instance) ) item_div.add_class("spt_drop_item") # no need for that #item_div.add(' ') content_div.add(item_div) value_wdg = self.get_value_wdg() json = jsondumps(self.values) json = json.replace('"', '"') value_wdg.set_value(json) return content_div
def handle_manifest(self, share): import datetime sync_folder = self.get_value("sync_folder") if not os.path.exists(sync_folder): os.makedirs(sync_folder) manifest_path = "%s/tactic.txt" % sync_folder """ # find the last transaction for this project project_code = self.get_value("projects") search = Search("sthpw/transaction_log") search.add_filter("namespace", project_code) search.add_order_by("timestamp desc") last_transaction = search.get_sobject() if last_transaction: transaction_code = last_transaction.get_code() # get rid of the unicode because pprint doesn't remove it transaction_code = str(transaction_code) else: transaction_code = "" """ f = open(manifest_path, 'wb') manifest = { "code": str(share.get_code()), "description": share.get_value('description'), #"last_transaction": transaction_code, "is_encrypted": "true", "date_created": datetime.datetime.now(), "created_by": self.server_prefix, "project": self.project_code } from pyasm.common import jsondumps #f.write(Common.get_pretty_print(manifest)) f.write(jsondumps(manifest)) f.close()
def execute(self): # check to see the status of this job """ job = self.kwargs.get('job') job_code = job.get_code() search = Search("sthpw/queue") search.add_filter("code", job_code) self.kwargs['job'] = search.get_sobject() if not job: print("Cancelling ...") return state = job.get_value("state") if state == "cancel": print("Cancelling 2 ....") return """ subprocess_kwargs = { 'login': login, 'project_code': project_code, 'command': command, 'kwargs': kwargs } subprocess_kwargs_str = jsondumps(subprocess_kwargs) install_dir = Environment.get_install_dir() python = Config.get_value("services", "python") if not python: python = 'python' args = ['%s' % python, '%s/src/tactic/command/queue.py' % install_dir] args.append(subprocess_kwargs_str) import subprocess p = subprocess.Popen(args) DbContainer.close_thread_sql() return
def execute(self): rule_code = self.kwargs.get("rule_code") if rule_code: search = Search("config/ingest_rule") search.add_filter("code", rule_code) rule = search.get_sobject() else: rule = SearchType.create("config/ingest_rule") # explicitly save the columns columns = ['base_dir', 'rule', 'title'] for column in columns: rule.set_value(column, self.kwargs.get(column) ) # not sure if we want to save the entire kwargs?? kwargs_str = jsondumps(self.kwargs) rule.set_value("data", kwargs_str) rule.commit() return
def get_behavior(cls, sobject): '''it takes sobject as an argument and turn it into a dictionary to pass to NotificationTestCmd''' pal = WebContainer.get_web().get_palette() bg_color = pal.color('background') sobj_dict = SObject.get_sobject_dict(sobject) sobj_json = jsondumps(sobj_dict) bvr = {'type': 'click_up', 'cbjs_action': ''' var server = TacticServerStub.get(); var rtn = {}; var msg = ''; try { spt.app_busy.show( 'Email Test', 'Waiting for email server response...' ); rtn = server.execute_cmd('tactic.command.NotificationTestCmd', args={'sobject_dict': %s}); msg = rtn.description; msg += '\\nYou can also review the notification in the Notification Log.' } catch(e) { msg = 'Error found in this notification:\\n\\n' + spt.exception.handler(e); } //console.log(msg) spt.app_busy.hide(); var popup_id = 'Notification test result'; var class_name = 'tactic.ui.panel.CustomLayoutWdg'; msg= msg.replace(/\\n/g, '<br/>'); var options = { 'html': '<div><div style="background:%s; padding: 5px">' + msg + '</div></div>'}; var kwargs = {'width':'600px'}; spt.panel.load_popup(popup_id, class_name, options, kwargs); ''' %(sobj_json, bg_color)} return bvr
def handle_manifest(self, base_dir, project_code, version): import datetime manifest_path = "%s/%s-manifest-%s.txt" % (base_dir, project_code, version) # find the last transaction for this project search = Search("sthpw/transaction_log") search.add_filter("namespace", project_code) search.add_order_by("timestamp desc") last_transaction = search.get_sobject() if last_transaction: transaction_code = last_transaction.get_code() # get rid of the unicode because pprint doesn't remove it transaction_code = str(transaction_code) else: transaction_code = "" f = open(manifest_path, 'wb') manifest = { "code": project_code, "description": "???", "version": version, "last_transaction": transaction_code, "is_encrypted": "true", "date_created": datetime.datetime.now(), "created_by": "???" } from pyasm.common import jsondumps #f.write(Common.get_pretty_print(manifest)) f.write(jsondumps(manifest)) f.close()
def serialize(my): '''serialize the data into a string''' value = jsondumps(my.data) return value
def get_display(my): web = WebContainer.get_web() widget = Widget() html = HtmlElement("html") is_xhtml = False if is_xhtml: web.set_content_type("application/xhtml+xml") widget.add('''<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> ''') html.add_attr("xmlns", "http://www.w3.org/1999/xhtml") #html.add_attr("xmlns:svg", "http://www.w3.org/2000/svg") # add the copyright widget.add(my.get_copyright_wdg()) widget.add(html) # create the header head = HtmlElement("head") html.add(head) head.add( '<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>\n' ) head.add('<meta http-equiv="X-UA-Compatible" content="IE=edge"/>\n') # Add the tactic favicon head.add( '<link rel="shortcut icon" href="/context/favicon.ico" type="image/x-icon"/>' ) # add the css styling head.add(my.get_css_wdg()) # add the title in the header project = Project.get() project_code = project.get_code() project_title = project.get_value("title") if web.is_admin_page(): is_admin = " - Admin" else: is_admin = "" if project_code == 'admin': head.add("<title>TACTIC Site Admin</title>\n") else: head.add("<title>%s%s</title>\n" % (project_title, is_admin)) # add the javascript libraries head.add(JavascriptImportWdg()) # add the body body = my.body html.add(body) body.add_event('onload', 'spt.onload_startup(this)') top = my.top # Add a NOSCRIPT tag block here to provide a warning message on browsers where 'Enable JavaScript' # is not checked ... TODO: clean up and re-style to make look nicer top.add(""" <NOSCRIPT> <div style="border: 2px solid black; background-color: #FFFF99; color: black; width: 600px; height: 70px; padding: 20px;"> <img src="%s" style="border: none;" /> <b>Javascript is not enabled on your browser!</b> <p>This TACTIC powered, web-based application requires JavaScript to be enabled in order to function. In your browser's options/preferences, please make sure that the 'Enable JavaScript' option is checked on, click OK to accept the settings change, and then refresh this web page.</p> </div> </NOSCRIPT> """ % (IconWdg.get_icon_path("ERROR"))) # add the content content_div = DivWdg() top.add(content_div) Container.put("TopWdg::content", content_div) # add a dummy button for global behaviors from tactic.ui.widget import ButtonNewWdg, IconButtonWdg ButtonNewWdg(title="DUMMY", icon=IconWdg.FILM) IconButtonWdg(title="DUMMY", icon=IconWdg.FILM) # NOTE: it does not need to be in the DOM. Just needs to be # instantiated #content_div.add(button) if my.widgets: content_wdg = my.get_widget('content') else: content_wdg = Widget() my.add(content_wdg) content_div.add(content_wdg) # add a calendar wdg from tactic.ui.widget import CalendarWdg cal_wdg = CalendarWdg(css_class='spt_calendar_template_top') cal_wdg.top.add_style('display: none') content_div.add(cal_wdg) if web.is_admin_page(): from tactic_branding_wdg import TacticCopyrightNoticeWdg branding = TacticCopyrightNoticeWdg(show_license_info=True) top.add(branding) # add the admin bar security = Environment.get_security() if not web.is_admin_page() and security.check_access( "builtin", "view_site_admin", "allow"): div = DivWdg() top.add(div) top.add_style("padding-top: 21px") div.add_class("spt_admin_bar") # home icon_div = DivWdg() div.add(icon_div) icon_div.add_style("float: left") icon_div.add_style("margin-right: 10px") icon_div.add_style("margin-top: -3px") icon_button = IconButtonWdg(title="Home", icon="BS_HOME") icon_div.add(icon_button) icon_button.add_behavior({ 'type': 'click_up', 'cbjs_action': ''' window.location.href="/"; ''' }) div.add_style("height: 15px") div.add_style("padding: 3px 0px 3px 15px") #div.add_style("margin-bottom: -5px") div.add_style("position: fixed") div.add_style("top: 0px") div.add_style("left: 0px") div.add_style("opacity: 0.7") div.add_style("width: 100%") #div.add_gradient("background", "background2", 20, 10) div.add_style("background-color", "#000") div.add_style("color", "#FFF") div.add_style("z-index", "1000") div.add_class("hand") div.set_box_shadow("0px 5px 5px") # remove icon_div = DivWdg() div.add(icon_div) icon_div.add_style("float: right") icon_div.add_style("margin-right: 10px") icon_div.add_style("margin-top: -3px") icon_button = IconButtonWdg(title="Remove Admin Bar", icon="BS_REMOVE") icon_div.add(icon_button) icon_button.add_behavior({ 'type': 'click_up', 'cbjs_action': ''' var parent = bvr.src_el.getParent(".spt_admin_bar"); bvr.src_el.getParent(".spt_top").setStyle("padding-top", "0px"); spt.behavior.destroy_element(parent); ''' }) # sign-out icon_div = DivWdg() div.add(icon_div) icon_div.add_style("float: right") icon_div.add_style("margin-right: 5px") icon_div.add_style("margin-top: -3px") icon_button = IconButtonWdg(title="Sign Out", icon="BS_LOG_OUT") icon_div.add(icon_button) icon_button.add_behavior({ 'type': 'click_up', 'cbjs_action': ''' var ok = function(){ var server = TacticServerStub.get(); server.execute_cmd("SignOutCmd", {login: bvr.login} ); window.location.href="/"; } spt.confirm("Are you sure you wish to sign out?", ok ) ''' }) div.add("<b>ADMIN >></b>") div.add_behavior({ 'type': 'listen', 'event_name': 'close_admin_bar', 'cbjs_action': ''' bvr.src_el.getParent(".spt_top").setStyle("padding-top", "0px"); spt.behavior.destroy_element(bvr.src_el); ''' }) div.add_behavior({ 'type': 'mouseover', 'cbjs_action': ''' bvr.src_el.setStyle("opacity", 0.85) //new Fx.Tween(bvr.src_el).start('height', "30px"); ''' }) div.add_behavior({ 'type': 'mouseout', 'cbjs_action': ''' bvr.src_el.setStyle("opacity", 0.7) //new Fx.Tween(bvr.src_el).start('height', "15px"); ''' }) project_code = Project.get_project_code() site_root = web.get_site_root() div.add_behavior({ 'type': 'click_up', 'site_root': site_root, 'project_code': project_code, 'cbjs_action': ''' var url = "/"+bvr.site_root+"/"+bvr.project_code+"/admin/link/_startup"; window.open(url); ''' }) # Add the script editor listener load_div = DivWdg() top.add(load_div) load_div.add_behavior({ 'type': 'listen', 'event_name': 'show_script_editor', 'cbjs_action': ''' var js_popup_id = "TACTIC Script Editor"; var js_popup = $(js_popup_id); if( js_popup ) { spt.popup.toggle_display( js_popup_id, false ); } else { spt.panel.load_popup(js_popup_id, "tactic.ui.app.ShelfEditWdg", {}, {"load_once": true} ); } ''' }) # deal with the palette defined in /index which can override the palette if my.kwargs.get("hash") == (): key = "index" search = Search("config/url") search.add_filter("url", "/%s/%%" % key, "like") search.add_filter("url", "/%s" % key) search.add_where("or") url = search.get_sobject() if url: xml = url.get_xml_value("widget") palette_key = xml.get_value("element/@palette") # look up palette the expression for index from pyasm.web import Palette palette = Palette.get() palette.set_palette(palette_key) colors = palette.get_colors() colors = jsondumps(colors) script = HtmlElement.script(''' var env = spt.Environment.get(); env.set_colors(%s); env.set_palette('%s'); ''' % (colors, palette_key)) top.add(script) env = Environment.get() client_handoff_dir = env.get_client_handoff_dir(include_ticket=False, no_exception=True) client_asset_dir = env.get_client_repo_dir() login = Environment.get_login() user_name = login.get_value("login") user_id = login.get_id() login_groups = Environment.get_group_names() from pyasm.security import Site site = Site.get_site() kiosk_mode = Config.get_value("look", "kiosk_mode") if not kiosk_mode: kiosk_mode = 'false' # add environment information script = HtmlElement.script(''' var env = spt.Environment.get(); env.set_site('%s'); env.set_project('%s'); env.set_user('%s'); env.set_user_id('%s'); var login_groups = '%s'.split('|'); env.set_login_groups(login_groups); env.set_client_handoff_dir('%s'); env.set_client_repo_dir('%s'); env.set_kiosk_mode('%s'); ''' % (site, Project.get_project_code(), user_name, user_id, '|'.join(login_groups), client_handoff_dir, client_asset_dir, kiosk_mode)) top.add(script) # add a global container for commonly used widgets div = DivWdg() top.add(div) div.set_id("global_container") # add in the app busy widget # find out if there is an override for this search = Search("config/url") search.add_filter("url", "/app_busy") url = search.get_sobject() if url: busy_div = DivWdg() div.add(busy_div) busy_div.add_class("SPT_PUW") busy_div.add_styles( "display: none; position: absolute; z-index: 1000") busy_div.add_class("app_busy_msg_block") busy_div.add_style("width: 300px") busy_div.add_style("height: 100px") busy_div.add_style("padding: 20px") busy_div.add_color("background", "background3") busy_div.add_border() busy_div.set_box_shadow() busy_div.set_round_corners(20) busy_div.set_attr("id", "app_busy_msg_block") # put the custom url here title_wdg = DivWdg() busy_div.add(title_wdg) title_wdg.add_style("font-size: 20px") title_wdg.add_class("spt_app_busy_title") busy_div.add("<hr/>") msg_div = DivWdg() busy_div.add(msg_div) msg_div.add_class("spt_app_busy_msg") else: from page_header_wdg import AppBusyWdg div.add(AppBusyWdg()) # popup parent popup = DivWdg() popup.set_id("popup") div.add(popup) # create another general popup popup_div = DivWdg() popup_div.set_id("popup_container") popup_div.add_class("spt_panel") popup = PopupWdg(id="popup_template", destroy_on_close=True) popup_div.add(popup) div.add(popup_div) inner_html_div = DivWdg() inner_html_div.set_id("inner_html") div.add(inner_html_div) # add in a global color from tactic.ui.input import ColorWdg color = ColorWdg() div.add(color) # add in a global notify wdg from notify_wdg import NotifyWdg widget.add(NotifyWdg()) from tactic.ui.app import DynamicUpdateWdg widget.add(DynamicUpdateWdg()) return widget
def get_display(self): top = self.top sources = self.kwargs.get("sources") if sources and isinstance(sources, basestring): sources = sources.split("|") source_types = self.kwargs.get("source_types") if not source_types: source_types = [] poster = self.kwargs.get("poster") width = self.kwargs.get("width") height = self.kwargs.get("height") preload = self.kwargs.get("preload") controls = self.kwargs.get("controls") autoplay = self.kwargs.get("autoplay") is_test = self.kwargs.get("is_test") is_test = False if is_test in [True, 'true']: poster = "http://video-js.zencoder.com/oceans-clip.png" sources = ["http://video-js.zencoder.com/oceans-clip.mp4"] sources = ["http://video-js.zencoder.com/oceans-clip.mp4"] sources = ["http://techslides.com/demos/sample-videos/small.ogv"] video = self.video video.add_class("video-js") video.add_class("vjs-default-skin") top.add(video) self.video_id = self.kwargs.get("video_id") if not self.video_id: self.video_id = video.set_unique_id() else: video.set_attr("id", self.video_id) # FIXME: this has refereneces to the Gallery ....! if self.index == 0: overlay = DivWdg() overlay.add_class('video_overlay') overlay.add_styles( 'background: transparent; z-index: 300; position: fixed; top: 38%; left: 12%;\ margin-left: auto; margin-right: auto; width: 75%; height: 45%' ) overlay.add_behavior({ 'type': 'click_up', 'cbjs_action': ''' var overlay = bvr.src_el; var idx = spt.gallery.index; var video_id = spt.gallery.videos[idx]; if (!video_id) return; var player = videojs(video_id, {"nativeControlsForTouch": false}); if (player.paused()) { player.play(); //console.log("play " + video_id) } else player.pause(); ''' }) top.add(overlay) top.add_behavior({'type': 'load', 'cbjs_action': self.get_onload_js()}) top.add_behavior({ 'type': 'load', 'index': self.index, 'video_id': self.video_id, 'cbjs_action': ''' if (!bvr.index) bvr.index = 0; var video_id = bvr.video_id; spt.video.init_videojs(video_id); if (spt.gallery) { spt.gallery.videos[bvr.index] = video_id; if (!spt.gallery.portrait) { var overlay = bvr.src_el.getElement('.video_overlay'); if (overlay) overlay.setStyles({'top': '4%', 'left': '5%', 'width': '90%', 'height':'87%'}); } } ''' }) #video.add_attr("data-setup", "{}") if width: video.add_attr("width", width) if height: video.add_attr("height", height) if poster: video.add_attr("poster", poster) if preload == None: preload = "none" if controls == None: controls = True autoplay = False # videojs uses a json data structre data = {'preload': preload, 'controls': controls, 'autoplay': autoplay} from pyasm.common import jsondumps data_str = jsondumps(data) video.add_attr("data-setup", data_str) for i, src in enumerate(sources): source = HtmlElement(type="source") source.add_attr("src", src) if len(source_types) > i: source_type = source_types[i] source.add_attr("type", source_type) video.add(source) #print top.get_buffer_display() return top
def get_display(my): top = my.top sources = my.kwargs.get("sources") if sources and isinstance(sources, basestring): sources = sources.split("|") source_types = my.kwargs.get("source_types") if not source_types: source_types = [] poster = my.kwargs.get("poster") width = my.kwargs.get("width") height = my.kwargs.get("height") preload = my.kwargs.get("preload") controls = my.kwargs.get("controls") autoplay = my.kwargs.get("autoplay") is_test = my.kwargs.get("is_test") is_test = False if is_test in [True, 'true']: poster = "http://video-js.zencoder.com/oceans-clip.png" sources = ["http://video-js.zencoder.com/oceans-clip.mp4"] sources = ["http://video-js.zencoder.com/oceans-clip.mp4"] sources = ["http://techslides.com/demos/sample-videos/small.ogv"] video = my.video video.add_class("video-js") video.add_class("vjs-default-skin") top.add(video) my.video_id = my.kwargs.get("video_id") if not my.video_id: my.video_id = video.set_unique_id() else: video.set_attr("id", my.video_id) # FIXME: this has refereneces to the Gallery ....! if my.index == 0: overlay = DivWdg() overlay.add_class('video_overlay') overlay.add_styles('background: transparent; z-index: 300; position: fixed; top: 38%; left: 12%;\ margin-left: auto; margin-right: auto; width: 75%; height: 45%' ) overlay.add_behavior({'type':'click_up', 'cbjs_action': ''' var overlay = bvr.src_el; var idx = spt.gallery.index; var video_id = spt.gallery.videos[idx]; if (!video_id) return; var player = videojs(video_id, {"nativeControlsForTouch": false}); if (player.paused()) { player.play(); //console.log("play " + video_id) } else player.pause(); ''' }) top.add(overlay) top.add_behavior( { 'type': 'load', 'cbjs_action': my.get_onload_js() } ) top.add_behavior( { 'type': 'load', 'index' : my.index, 'video_id': my.video_id, 'cbjs_action': ''' if (!bvr.index) bvr.index = 0; var video_id = bvr.video_id; spt.video.init_videojs(video_id); if (spt.gallery) { spt.gallery.videos[bvr.index] = video_id; if (!spt.gallery.portrait) { var overlay = bvr.src_el.getElement('.video_overlay'); if (overlay) overlay.setStyles({'top': '4%', 'left': '5%', 'width': '90%', 'height':'87%'}); } } ''' } ) #video.add_attr("data-setup", "{}") if width: video.add_attr("width", width) if height: video.add_attr("height", height) if poster: video.add_attr("poster", poster) if preload == None: preload = "none" if controls == None: controls = True autoplay = False # videojs uses a json data structre data = { 'preload': preload, 'controls': controls, 'autoplay': autoplay } from pyasm.common import jsondumps data_str = jsondumps(data) video.add_attr("data-setup", data_str) for i, src in enumerate(sources): source = HtmlElement(type="source") source.add_attr("src", src) if len(source_types) > i: source_type = source_types[i] source.add_attr("type", source_type) video.add(source) #print top.get_buffer_display() return top
def get_display(my): # Custom URLs have the ability to send out different content types url = my.kwargs.get("url") web = WebContainer.get_web() #content_type = my.kwargs.get("content_type") #print "content_type: ", content_type hash = my.kwargs.get("hash") ticket = web.get_form_value("ticket") method = web.get_request_method() headers = web.get_request_headers() accept = headers.get("Accept") expression = url.get_value("url") kwargs = Common.extract_dict(hash, expression) # Does the URL listen to specific Accept values? # or does it enforce a return content type ... and how does one # know what exactly is supported? Accept is kind of complicated. # Easier to put in as a paramenter ... but should accept both # get the widget designated for hash kwargs['Accept'] = accept kwargs['Method'] = method from tactic.ui.panel import HashPanelWdg hash_widget = HashPanelWdg.get_widget_from_hash(hash, kwargs=kwargs) # Really, the hash widget should determine what is returned, but # should take the Accept into account. It is not up to this # class to determine what is or isn't implemented, not is it the # responsibility of this class to convert the data. So, it # returns whatever is given. widget = Widget() # We need to to get the content-type from the widget ... however # it decides to make use of the "Accept" type #widget.get_content_type() # # Example implementation of custom script, run by hash_widget # if accept == "application/json": value = hash_widget.get_display() value = jsondumps(value) web.set_content_type(accept) elif accept == "application/xml": from pyasm.common import Xml value = hash_widget.get_display() if isinstance(value, basestring): xml = Xml(value) value = xml.to_string() elif isinstance(value, Xml): value = value.to_string() web.set_content_type(accept) elif accept == "plain/text": from pyasm.common import Xml value = hash_widget.get_display() value = str(value) web.set_content_type(accept) else: # return text/html value = DivWdg() if isinstance(hash_widget, basestring): value.add(hash_widget) else: value.add(hash_widget.get_display()) web.set_content_type("text/html") widget.add(value) return widget
def get_import_wdg(self): div = DivWdg() if self.data: div.add("<br/>"*2) div.add("The following TACTIC share was found: ") div.add("<br/>"*2) data_input = TextAreaWdg("data") data_input.add_style("display: none") div.add(data_input) #print "xxxx: ", self.data data_str = jsondumps(self.data) #data_str = data_str.replace('"', "'") print "data: ", data_str data_input.set_value(data_str) table = Table() div.add(table) table.set_max_width() table.add_style("margin-left: 20px") table.add_style("margin-right: 20px") for name, value in self.data.items(): name = Common.get_display_title(name) table.add_row() table.add_cell(name) table.add_cell(value) div.add("<br/>"*2) div.add( self.get_versions_wdg() ) div.add("<br/>"*2) # check to see if the project exists project_code = self.data.get("project_code") project_code = self.data.get("projects") project = Project.get_by_code(project_code) #if project: if False: msg_div = DivWdg() div.add(msg_div) msg_div.add_style("padding: 20px") msg_div.add_color("background", "background3") msg_div.add_color("color", "color") msg_div.add_border() icon = IconWdg("WARNING", IconWdg.WARNING) msg_div.add(icon) icon.add_style("float: left") msg_div.add("The project with code [%s] already exists. You must remove the installed project before trying to import this one." % project_code) return div if self.data.get("is_encrypted") == "true": div.add("The transactions in this share is encrypted. Please provide an encryption key to decrypt the transactions<br/><br/>") div.add("Encryption Key: ") text = TextWdg("encryption_key") div.add(text) div.add("<br/>"*2) button = ActionButtonWdg(title="Import >>") button.add_style("float: right") div.add(button) div.add("<br/>"*2) button.add_behavior( { 'type': 'click_up', 'project_code': project_code, 'cbjs_action': ''' spt.app_busy.show("Importing Project "+bvr.project_code+"..."); var top = bvr.src_el.getParent(".spt_sync_import_top"); var values = spt.api.Utility.get_input_values(top, null, false); var cmd = "tactic.ui.sync.SyncImportCmd"; var server = TacticServerStub.get(); server.execute_cmd(cmd, values, {}, {use_transaction: false}); spt.notify.show_message("Finished importing project"); spt.app_busy.hide(); document.location = '/tactic/'+bvr.project_code; ''' } ) return div
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 apply_pattern(self, base_dir, pattern, checkin_type, depth=1, ignore=[], filter=[]): # remove the trailing / if base_dir.endswith("/"): base_dir = base_dir.rstrip("/") self.paths_not_matched = [] self.paths_matched = [] self.paths_irregular = [] self.paths_invalid = [] self.tags = {} self.data = {} # if checkin mode if checkin_type == "directory": self.sobject_tags = {} self.snapshot_tags = {} self.process_path(base_dir, pattern, checkin_type) # if paths are passed in, then process them files = self.kwargs.get("files") if files: root = base_dir if checkin_type == "file": start_depth = len(pattern.split("/")) for file in files: #path = "%s/%s" % (root, file) path = file skip = False for p in ignore: if file.endswith(p): skip = True break for p in filter: if file.find(p) == -1: skip = True break if skip: self.paths_not_matched.append(path) continue self.sobject_tags = {} self.snapshot_tags = {} self.process_path(path, pattern, checkin_type) self.tags[path] = { 'sobject': self.sobject_tags, 'snapshot': self.snapshot_tags } # else look through the file system else: count = 0 # find all of the paths in here for root, dirs, files in os.walk(unicode(base_dir)): if checkin_type == "directory": start_depth = len(pattern.split("/")) for dir in dirs: path = "%s/%s/" % (root, dir) parts_depth = len(path.split("/")) #print path, parts_depth if not parts_depth - start_depth == depth: self.paths_not_matched.append(path) continue self.sobject_tags = {} self.snapshot_tags = {} self.process_path(path, pattern, checkin_type) self.tags[path] = { 'sobject': self.sobject_tags, 'snapshot': self.snapshot_tags } else: for file in files: count += 1 limit = 100000 if count > limit: break path = "%s/%s" % (root, file) self.check_irregular(path) skip = False for p in ignore: if file.endswith(p): skip = True break for p in filter: if p.startswith("/") and p.endswith("/"): import re p = p.strip("/") p = re.compile(p) if p.match(file): skip = False break elif file.find(p) != -1: skip = False break else: if not filter: skip = False else: skip = True if skip: self.paths_not_matched.append(path) continue #xx = "scan" xx = "xx" if xx == 'scan': self.scan_path(path, pattern) else: self.sobject_tags = {} self.snapshot_tags = {} self.process_path(path, pattern, checkin_type) self.tags[path] = { 'sobject': self.sobject_tags, 'snapshot': self.snapshot_tags, } print "length: ", len(self.data.keys()) self.info["paths_matched"] = self.paths_matched self.info["paths_not_matched"] = self.paths_not_matched self.info["paths_invalid"] = self.paths_invalid self.info["paths_irregular"] = self.paths_irregular self.info["tags"] = self.tags self.info["data"] = self.data import codecs scan_path = "/tmp/scan" if os.path.exists(scan_path): f = codecs.open(scan_path, 'r', 'utf-8') data = jsonloads( f.read() ) f.close() data.update(self.data) else: data = self.data f = codecs.open(scan_path, 'w', 'utf-8') f.write( jsondumps( data ) ) f.close() return
def get_action_html(my): search_key = SearchKey.get_by_sobject(my.sobjects[0], use_id=True) search_type = my.sobjects[0].get_base_search_type() div = DivWdg(css='centered') # construct the bvr element_names = my.element_names[:] for element_name in my.skipped_element_names: element_names.remove(element_name) bvr = { 'type': 'click_up', 'mode': my.mode, 'element_names': element_names, 'search_key': search_key, 'input_prefix': my.input_prefix, 'view': my.view } if my.mode == 'insert': bvr['refresh'] = 'true' # for adding parent relationship in EditCmd if my.parent_key: bvr['parent_key'] = my.parent_key hidden_div = DivWdg() hidden_div.add_style("display: none") div.add(hidden_div) hidden = TextAreaWdg("__data__") hidden_div.add(hidden) hidden.set_value( jsondumps(bvr) ) show_action = my.kwargs.get("show_action") if show_action in [False, 'false']: return div div.add_styles('height: 35px; margin-top: 5px;') div.add_named_listener('close_EditWdg', ''' var popup = spt.popup.get_popup( $('edit_popup') ); if (popup != null) { spt.popup.destroy(popup); } ''') # custom callbacks cbjs_cancel = my.kwargs.get('cbjs_cancel') if not cbjs_cancel: cbjs_cancel = ''' spt.named_events.fire_event('preclose_edit_popup', {}); spt.named_events.fire_event('close_EditWdg', {}) ''' # custom callbacks cbjs_insert_path = my.kwargs.get('cbjs_%s_path' % my.mode) cbjs_insert = None if cbjs_insert_path: script_obj = CustomScript.get_by_path(cbjs_insert_path) if script_obj: cbjs_insert = script_obj.get_value("script") # get it inline if not cbjs_insert: cbjs_insert = my.kwargs.get('cbjs_%s' % my.mode) # use a default if not cbjs_insert: mode_label = my.mode.capitalize() cbjs_insert = ''' spt.app_busy.show("%sing items", ""); spt.edit.edit_form_cbk(evt, bvr); spt.app_busy.hide(); '''%mode_label save_event = my.kwargs.get('save_event') if not save_event: save_event = div.get_unique_event("save") bvr['save_event'] = save_event bvr['named_event'] = 'edit_pressed' bvr['cbjs_action'] = cbjs_insert ok_btn_label = my.mode.capitalize() if ok_btn_label == 'Edit': ok_btn_label = 'Save' if ok_btn_label == 'Insert': ok_btn_label = 'Add' if my.kwargs.get('ok_btn_label'): ok_btn_label = my.kwargs.get('ok_btn_label') ok_btn_tip = ok_btn_label if my.kwargs.get('ok_btn_tip'): ok_btn_tip = my.kwargs.get('ok_btn_tip') cancel_btn_label = 'Cancel' if my.kwargs.get('cancel_btn_label'): cancel_btn_label = my.kwargs.get('cancel_btn_label') cancel_btn_tip = cancel_btn_label if my.kwargs.get('cancel_btn_tip'): cancel_btn_tip = my.kwargs.get('cancel_btn_tip') # create the buttons insert_button = ActionButtonWdg(title=ok_btn_label, tip=ok_btn_tip) insert_button.add_behavior(bvr) cancel_button = ActionButtonWdg(title=cancel_btn_label, tip=cancel_btn_tip) cancel_button.add_behavior({ 'type': 'click_up', 'cbjs_action': cbjs_cancel }) table = Table() table.add_style("margin-left: auto") table.add_style("margin-right: auto") table.add_style("margin-top: 15px") table.add_style("margin-bottom: 15px") table.add_row() table.add_cell(insert_button) table.add_cell(cancel_button) div.add(table) #div.add(SpanWdg(edit, css='med')) #div.add(SpanWdg(edit_close, css='med')) #div.add(SpanWdg(cancel, css='med')) return div
def get_data_wdg(my): div = DivWdg() from pyasm.biz import Pipeline from pyasm.widget import SelectWdg search_type_obj = SearchType.get(my.search_type) base_type = search_type_obj.get_base_key() search = Search("sthpw/pipeline") search.add_filter("search_type", base_type) pipelines = search.get_sobjects() if pipelines: pipeline = pipelines[0] process_names = pipeline.get_process_names() if process_names: table = Table() div.add(table) table.add_row() table.add_cell("Process: ") select = SelectWdg("process") table.add_cell(select) process_names.append("---") process_names.append("publish") process_names.append("icon") select.set_option("values", process_names) #### buttons = Table() div.add(buttons) buttons.add_row() button = IconButtonWdg(title="Add Data", icon=IconWdg.FOLDER) buttons.add_cell(button) dialog = DialogWdg(display="false", show_title=False) div.add(dialog) dialog.set_as_activator(button, offset={'x':-10,'y':10}) dialog_data_div = DivWdg() dialog_data_div.add_color("background", "background") dialog_data_div.add_style("padding", "20px") dialog.add(dialog_data_div) # Order folders by date name_div = DivWdg() dialog_data_div.add(name_div) name_div.add_style("margin: 15px 0px") if SearchType.column_exists(my.search_type, "relative_dir"): category_div = DivWdg() name_div.add(category_div) checkbox = RadioWdg("category") checkbox.set_option("value", "none") category_div.add(checkbox) category_div.add(" No categories") category_div.add_style("margin-bottom: 5px") checkbox.set_option("checked", "true") category_div = DivWdg() name_div.add(category_div) checkbox = RadioWdg("category") checkbox.set_option("value", "by_day") category_div.add(checkbox) category_div.add(" Categorize files by Day") category_div.add_style("margin-bottom: 5px") category_div = DivWdg() name_div.add(category_div) checkbox = RadioWdg("category") checkbox.set_option("value", "by_week") category_div.add(checkbox) category_div.add(" Categorize files by Week") category_div.add_style("margin-bottom: 5px") category_div = DivWdg() name_div.add(category_div) checkbox = RadioWdg("category") checkbox.set_option("value", "by_year") category_div.add(checkbox) category_div.add(" Categorize files by Year") category_div.add_style("margin-bottom: 5px") """ checkbox = RadioWdg("category") checkbox.set_option("value", "custom") name_div.add(checkbox) name_div.add(" Custom") """ name_div.add("<br/>") hidden = HiddenWdg(name="parent_key") dialog_data_div.add(hidden) hidden.add_class("spt_parent_key") parent_key = my.kwargs.get("parent_key") or "" if parent_key: hidden.set_value(parent_key) dialog_data_div.add("Keywords:<br/>") dialog.add(dialog_data_div) text = TextAreaWdg(name="keywords") dialog_data_div.add(text) text.add_class("spt_keywords") text.add_style("padding: 1px") dialog_data_div.add("<br/>"*2) extra_data = my.kwargs.get("extra_data") if not isinstance(extra_data, basestring): extra_data = jsondumps(extra_data) dialog_data_div.add("Extra Data (JSON):<br/>") text = TextAreaWdg(name="extra_data") dialog_data_div.add(text) if extra_data != "null": text.set_value(extra_data) text.add_class("spt_extra_data") text.add_style("padding: 1px") #### TEST Image options """ button = IconButtonWdg(title="Resize", icon=IconWdg.FILM) buttons.add_cell(button) dialog = DialogWdg(display="false", show_title=False) div.add(dialog) dialog.set_as_activator(button, offset={'x':-10,'y':10}) try: from spt.tools.convert import ConvertOptionsWdg convert_div = DivWdg() dialog.add(convert_div) convert_div.add_style("padding: 20px") convert_div.add_color("background", "background") convert_div.add_class("spt_image_convert") convert = ConvertOptionsWdg() convert_div.add(convert) except: pass """ # use base name for name """ name_div = DivWdg() dialog_data_div.add(name_div) name_div.add_style("margin: 15px 0px") checkbox = CheckboxWdg("use_file_name") name_div.add(checkbox) name_div.add(" Use name of file for name") name_div.add("<br/>") checkbox = CheckboxWdg("use_base_name") name_div.add(checkbox) name_div.add(" Remove extension") name_div.add("<br/>") checkbox = CheckboxWdg("file_keywords") name_div.add(checkbox) name_div.add(" Use file name for keywords") """ return div
def serialize(self): '''serialize the data into a string''' value = jsondumps(self.data) return value
def execute(self): input_data = self.get_input_data() data = self.data # add site info to the data object site = Site.get_site() if site and not data.get("site"): data['site'] = site result = True # input data for the handler if self.mode == 'separate process,blocking': input_data_str = jsondumps(input_data) data_str = jsondumps(data) file = __file__ py_exec = Config.get_value("services", "python") if not py_exec: py_exec = "python" retcode = subprocess.call([py_exec, file, data_str, input_data_str]) elif self.mode == 'separate process,non-blocking': input_data_str = jsondumps(input_data) data_str = jsondumps(data) file = __file__ py_exec = Config.get_value("services", "python") if not py_exec: py_exec = "python" retcode = subprocess.Popen([py_exec, file, data_str, input_data_str]) result = "wait" elif self.mode == 'separate process,queued': kwargs = data.get("kwargs") priority = kwargs.get("priority") or 99999 description = kwargs.get("description") or "Trigger" queue_type = kwargs.get("trigger") or "trigger" class_name = "pyasm.command.QueueTrigger" kwargs = { 'input_data': input_data, 'data': data, } from tactic.command import Queue queue_item = Queue.add(class_name, kwargs, queue_type=queue_type, priority=priority, description=description) result = "wait" elif self.mode == 'same process,new transaction': # run it inline trigger = ScriptTrigger() trigger.set_data(data) trigger.set_input(input_data) trigger.execute() # if it was not overridden by the trigger, the return default for the mode if not self.info.has_key("result"): self.info['result'] = result
def get_data_wdg(my): div = DivWdg() from pyasm.biz import Pipeline from pyasm.widget import SelectWdg search_type_obj = SearchType.get(my.search_type) base_type = search_type_obj.get_base_key() search = Search("sthpw/pipeline") search.add_filter("search_type", base_type) pipelines = search.get_sobjects() if pipelines: pipeline = pipelines[0] process_names = pipeline.get_process_names() if process_names: table = Table() div.add(table) table.add_row() table.add_cell("Process: ") select = SelectWdg("process") table.add_cell(select) process_names.append("---") process_names.append("publish") process_names.append("icon") select.set_option("values", process_names) #### buttons = Table() div.add(buttons) buttons.add_row() #button = IconButtonWdg(title="Fill in Data", icon=IconWdg.EDIT) button = ActionButtonWdg(title="Metadata") button.add_style("float: left") button.add_style("margin-top: -3px") buttons.add_cell(button) select_label = DivWdg("Update mode") select_label.add_style("float: left") select_label.add_style("margin-top: -3px") select_label.add_style("margin-left: 20px") buttons.add_cell(select_label) update_mode_option = my.kwargs.get("update_mode") if not update_mode_option: update_mode_option = "true" update_mode = SelectWdg(name="update mode") update_mode.add_class("spt_update_mode_select") update_mode.set_option("values", ["false", "true", "sequence"]) update_mode.set_option("labels", ["Off", "On", "Sequence"]) update_mode.set_option("default", update_mode_option) update_mode.add_style("float: left") update_mode.add_style("margin-top: -3px") update_mode.add_style("margin-left: 5px") update_mode.add_style("margin-right: 5px") buttons.add_cell(update_mode) update_info = DivWdg() update_info.add_class("glyphicon") update_info.add_class("glyphicon-info-sign") update_info.add_style("float: left") update_info.add_style("margin-top: -3px") update_info.add_style("margin-left: 10px") update_info.add_behavior({ 'type': 'click_up', 'cbjs_action': ''' spt.info("When update mode is on, if a file shares the name of one other file in the asset library, the file will update on ingest. If more than one file shares the name of an ingested asset, a new asset is created.<br> If sequence mode is selected, the system will update the sobject on ingest if a file sequence sharing the same name already exists.", {type: 'html'}); ''' }) buttons.add_cell(update_info) dialog = DialogWdg(display="false", show_title=False) div.add(dialog) dialog.set_as_activator(button, offset={'x': -10, 'y': 10}) dialog_data_div = DivWdg() dialog_data_div.add_color("background", "background") dialog_data_div.add_style("padding", "20px") dialog.add(dialog_data_div) # Order folders by date name_div = DivWdg() dialog_data_div.add(name_div) name_div.add_style("margin: 15px 0px") if SearchType.column_exists(my.search_type, "relative_dir"): category_div = DivWdg() name_div.add(category_div) checkbox = RadioWdg("category") checkbox.set_option("value", "none") category_div.add(checkbox) category_div.add(" No categories") category_div.add_style("margin-bottom: 5px") checkbox.set_option("checked", "true") category_div = DivWdg() name_div.add(category_div) checkbox = RadioWdg("category") checkbox.set_option("value", "by_day") category_div.add(checkbox) category_div.add(" Categorize files by Day") category_div.add_style("margin-bottom: 5px") category_div = DivWdg() name_div.add(category_div) checkbox = RadioWdg("category") checkbox.set_option("value", "by_week") category_div.add(checkbox) category_div.add(" Categorize files by Week") category_div.add_style("margin-bottom: 5px") category_div = DivWdg() name_div.add(category_div) checkbox = RadioWdg("category") checkbox.set_option("value", "by_year") category_div.add(checkbox) category_div.add(" Categorize files by Year") category_div.add_style("margin-bottom: 5px") """ checkbox = RadioWdg("category") checkbox.set_option("value", "custom") name_div.add(checkbox) name_div.add(" Custom") """ name_div.add("<br/>") ingest_data_view = my.kwargs.get('ingest_data_view') from tactic.ui.panel import EditWdg sobject = SearchType.create(my.search_type) edit = EditWdg(search_key=sobject.get_search_key(), mode='view', view=ingest_data_view) dialog_data_div.add(edit) hidden = HiddenWdg(name="parent_key") dialog_data_div.add(hidden) hidden.add_class("spt_parent_key") parent_key = my.kwargs.get("parent_key") or "" if parent_key: hidden.set_value(parent_key) extra_data = my.kwargs.get("extra_data") if not isinstance(extra_data, basestring): extra_data = jsondumps(extra_data) if extra_data and extra_data != "null": # it needs a TextArea instead of Hidden because of JSON data text = TextAreaWdg(name="extra_data") text.add_style('display: none') text.set_value(extra_data) dialog_data_div.add(text) """ dialog_data_div.add("Keywords:<br/>") dialog.add(dialog_data_div) text = TextAreaWdg(name="keywords") dialog_data_div.add(text) text.add_class("spt_keywords") text.add_style("padding: 1px") dialog_data_div.add("<br/>"*2) text.add_class("spt_extra_data") text.add_style("padding: 1px") """ #### TEST Image options """ button = IconButtonWdg(title="Resize", icon=IconWdg.FILM) buttons.add_cell(button) dialog = DialogWdg(display="false", show_title=False) div.add(dialog) dialog.set_as_activator(button, offset={'x':-10,'y':10}) try: from spt.tools.convert import ConvertOptionsWdg convert_div = DivWdg() dialog.add(convert_div) convert_div.add_style("padding: 20px") convert_div.add_color("background", "background") convert_div.add_class("spt_image_convert") convert = ConvertOptionsWdg() convert_div.add(convert) except: pass """ # use base name for name """ name_div = DivWdg() dialog_data_div.add(name_div) name_div.add_style("margin: 15px 0px") checkbox = CheckboxWdg("use_file_name") name_div.add(checkbox) name_div.add(" Use name of file for name") name_div.add("<br/>") checkbox = CheckboxWdg("use_base_name") name_div.add(checkbox) name_div.add(" Remove extension") name_div.add("<br/>") checkbox = CheckboxWdg("file_keywords") name_div.add(checkbox) name_div.add(" Use file name for keywords") """ return div
def set_to_cgi(my): web = WebContainer.get_web() data = jsondumps(my.data) web.set_form_value('json', data) Container.put("FilterData", my)
def get_display(my): # Custom URLs have the ability to send out different content types url = my.kwargs.get("url") web = WebContainer.get_web() #content_type = my.kwargs.get("content_type") #print "content_type: ", content_type hash = my.kwargs.get("hash") ticket = web.get_form_value("ticket") method = web.get_request_method() headers = web.get_request_headers() accept = headers.get("Accept") expression = url.get_value("url") kwargs = Common.extract_dict(hash, expression) # Does the URL listen to specific Accept values? # or does it enforce a return content type ... and how does one # know what exactly is supported? Accept is kind of complicated. # Easier to put in as a paramenter ... but should accept both # get the widget designated for hash kwargs['Accept'] = accept kwargs['Method'] = method from tactic.ui.panel import HashPanelWdg hash_widget = HashPanelWdg.get_widget_from_hash(hash, kwargs=kwargs) # Really, the hash widget should determine what is returned, but # should take the Accept into account. It is not up to this # class to determine what is or isn't implemented, not is it the # responsibility of this class to convert the data. So, it # returns whatever is given. widget = Widget() # We need to to get the content-type from the widget ... however # it decides to make use of the "Accept" type #widget.get_content_type() # # Example implementation of custom script, run by hash_widget # if accept == "application/json": value = hash_widget.get_display() value = jsondumps(value) web.set_content_type(accept) elif accept == "application/xml": from pyasm.common import Xml value = hash_widget.get_display() if isinstance(value, basestring): xml = Xml(value) value = xml.to_string() elif isinstance(value, Xml): value = value.to_string() web.set_content_type(accept) elif accept == "plain/text": from pyasm.common import Xml value = hash_widget.get_display() value = str(value) web.set_content_type(accept) else: # return text/html value = DivWdg() if isinstance(hash_widget, basestring): value.add(hash_widget) else: value.add(hash_widget.get_display()) current_type = web.get_content_type() if not current_type: web.set_content_type("text/html") widget.add(value) return widget
def add_behaviors(my, widget, xml): behavior_nodes = xml.get_nodes("config/%s/behavior" % my.view) if behavior_nodes: hidden_div = DivWdg() hidden_div.add_styles("display: none"); hidden_div.add_class("spt_customlayoutwdg_handoffs") widget.add( hidden_div ) widget.add_behavior({ 'type': 'load', 'cbjs_action': ''' // handle embedded load behaviors! var el_load_list = bvr.src_el.getElements(".SPT_BVR_LOAD_PENDING"); spt.behavior.process_load_behaviors( el_load_list ); ''' }) # remove objects that cannot be json marshalled view_kwargs = my.kwargs.copy() for key, value in view_kwargs.items(): try: test = jsondumps(value) except Exception, e: del(view_kwargs[key]) for behavior_node in behavior_nodes: bvr_div = DivWdg() hidden_div.add( bvr_div ) css_class = Xml.get_attribute(behavior_node, 'class') behavior_str = Xml.get_node_value(behavior_node) behavior_str = behavior_str.strip() # if the event is specified in the xml, then use that event = Xml.get_attribute(behavior_node, 'event') modkeys = Xml.get_attribute(behavior_node, 'modkeys') relay_class = Xml.get_attribute(behavior_node, 'relay_class') if not behavior_str: continue try: try: bvr = eval(behavior_str) except: # try it as a string bvr_str = eval("'''\n%s\n'''" % behavior_str) if bvr_str: bvr = {} bvr['cbjs_action'] = bvr_str if event: bvr['type'] = event if modkeys: bvr['modkeys'] = modkeys # add the kwargs to this so behaviors have access bvr['kwargs'] = view_kwargs bvr['class_name'] = Common.get_full_class_name(my) if relay_class: bvr['bvr_match_class'] = relay_class if not bvr.get("type"): bvr['type'] = 'mouseup' my.content.add_relay_behavior( bvr ) elif bvr.get("type") == "smart_drag": bvr['bvr_match_class'] = css_class my.content.add_behavior(bvr) elif bvr.get("type") == "listen": bvr['event_name'] = Xml.get_attribute(behavior_node,'event_name') my.content.add_behavior(bvr) else: bvr['_handoff_'] = '@.getParent(".spt_custom_content").getElements(".%s")' % css_class if not bvr.get("type"): bvr['type'] = 'click_up' bvr_div.add_behavior( bvr ) except Exception, e: print "Error: ", e raise TacticException("Error parsing behavior [%s]" % behavior_str)
def execute(self): input_data = self.get_input_data() data = self.data # add site info to the data object site = Site.get_site() if site and not data.get("site"): data['site'] = site result = True # input data for the handler if self.mode == 'separate process,blocking': input_data_str = jsondumps(input_data) data_str = jsondumps(data) file = __file__ py_exec = Config.get_value("services", "python") if not py_exec: py_exec = "python" retcode = subprocess.call( [py_exec, file, data_str, input_data_str]) elif self.mode == 'separate process,non-blocking': input_data_str = jsondumps(input_data) data_str = jsondumps(data) file = __file__ py_exec = Config.get_value("services", "python") if not py_exec: py_exec = "python" retcode = subprocess.Popen( [py_exec, file, data_str, input_data_str]) result = "wait" elif self.mode == 'separate process,queued': kwargs = data.get("kwargs") priority = kwargs.get("priority") or 99999 description = kwargs.get("description") or "Trigger" queue_type = kwargs.get("trigger") or "trigger" class_name = "pyasm.command.QueueTrigger" kwargs = { 'input_data': input_data, 'data': data, } from tactic.command import Queue queue_item = Queue.add(class_name, kwargs, queue_type=queue_type, priority=priority, description=description) result = "wait" elif self.mode == 'same process,new transaction': # run it inline trigger = ScriptTrigger() trigger.set_data(data) trigger.set_input(input_data) trigger.execute() # if it was not overridden by the trigger, the return default for the mode if not self.info.has_key("result"): self.info['result'] = result
########################################################### # # Copyright (c) 2012, Southpaw Technology # All Rights Reserved # # PROPRIETARY INFORMATION. This software is proprietary to # Southpaw Technology, and is not to be reproduced, transmitted, # or disclosed in any way without written permission. # # # import tacticenv from pyasm.common import jsonloads, jsondumps print "function: ", function print "kwargs: ", kwargs, type(kwargs) print "protocol: ", protocol print "server: ", server kwargs = jsonloads(kwargs) # convert the args to a dict method = eval('''server.%s''' % function) ret_val = method(**kwargs) ret_val = jsondumps(ret_val)
def get_display(my): top = my.top top.add_color("background", "background") top.add_color("color", "color") top.add_style("padding: 10px") top.add_style("min-width: 400px") from tactic.ui.app import HelpButtonWdg help_wdg = HelpButtonWdg(alias="exporting-csv-data") top.add(help_wdg) help_wdg.add_style("float: right") help_wdg.add_style("margin-top: -3px") if not my.check(): top.add(DivWdg('Error: %s' %my.error_msg)) top.add(HtmlElement.br(2)) return super(CsvExportWdg, my).get_display() if my.search_type_list and my.search_type_list[0] != my.search_type: st = SearchType.get(my.search_type_list[0]) title_div =DivWdg('Exporting related items [%s]' % st.get_title()) top.add(title_div) top.add(HtmlElement.br()) my.search_type = my.search_type_list[0] my.view = my.related_view if my.mode != 'export_all': num = len(my.selected_search_keys) else: search = Search(my.search_type) num = search.get_count() msg_div = DivWdg('Total: %s items to export'% num) msg_div.add_style("font-size: 12px") msg_div.add_style("font-weight: bold") msg_div.add_style('margin-left: 4px') top.add(msg_div) if num > 300: msg_div.add_behavior({'type':'load', 'cbjs_action': "spt.alert('%s items are about to be exported. It may take a while.')" %num}) top.add(HtmlElement.br()) div = DivWdg(css='spt_csv_export', id='csv_export_action') div.add_color("background", "background", -10) div.add_style("padding: 10px") div.add_style("margin: 5px") div.add_styles('max-height: 350px; overflow: auto') table = Table( css='minimal') table.add_color("color", "color") div.add(table) table.set_id('csv_export_table') table.center() cb_name = 'csv_column_name' master_cb = CheckboxWdg('master_control') master_cb.set_checked() master_cb.add_behavior({'type': 'click_up', 'propagate_evt': True, 'cbjs_action': ''' var inputs = spt.api.Utility.get_inputs(bvr.src_el.getParent('.spt_csv_export'),'%s'); for (var i = 0; i < inputs.length; i++) inputs[i].checked = !inputs[i].checked; ''' %cb_name}) span = SpanWdg('Select Columns To Export') span.add_style('font-weight','600') table.add_row_cell(span) table.add_row_cell(HtmlElement.br()) tr = table.add_row() tr.add_style('border-bottom: 1px groove #777') td = table.add_cell(master_cb) label = HtmlElement.i('toggle all') label.add_style('color: #888') table.add_cell(label) col1 = table.add_col() col1.add_style('width: 35px') col2 = table.add_col() if not my.search_type or not my.view: return table # use overriding element names and derived titles if available config = WidgetConfigView.get_by_search_type(my.search_type, my.view) if my.element_names and config: filtered_columns = my.element_names titles = [] for name in my.element_names: title = config.get_element_title(name) titles.append(title) else: # excluding FunctionalTableElement filtered_columns = [] titles = [] if not config: columns = search.get_columns() filtered_columns = columns titles = ['n/a'] * len(filtered_columns) else: columns = config.get_element_names() filtered_columns = columns titles = config.get_element_titles() """ # commented out until it is decided 2.5 widgets will # use this class to differentiate between reg and functional element from pyasm.widget import FunctionalTableElement for column in columns: widget = config.get_display_widget(column) if isinstance(widget, FunctionalTableElement): continue filtered_columns.append(column) """ for idx, column in enumerate(filtered_columns): table.add_row() cb = CheckboxWdg(cb_name) cb.set_option('value', column) cb.set_checked() table.add_cell(cb) title = titles[idx] table.add_cell('<b>%s</b> (%s) '%(title, column)) action_div = DivWdg() widget = DivWdg() table.add_row_cell(widget) widget.add_style("margin: 20px 0 10px 0px") cb = CheckboxWdg('include_id', label=" Include ID") cb.set_default_checked() widget.add(cb) hint = HintWdg('To update entries with specific ID later, please check this option. For new inserts in this or other table later on, uncheck this option.') widget.add(hint) label = string.capwords(my.mode.replace('_', ' ')) button = ActionButtonWdg(title=label, size='l') is_export_all = my.mode == 'export_all' button.add_behavior({ 'type': "click_up", 'cbfn_action': 'spt.dg_table_action.csv_export', 'element': 'csv_export', 'column_names': 'csv_column_name', 'search_type': my.search_type, 'view': my.view, 'search_keys' : my.selected_search_keys, 'is_export_all' : is_export_all }) my.close_action = "var popup = bvr.src_el.getParent('.spt_popup');spt.popup.close(popup)" if my.close_action: close_button = ActionButtonWdg(title='Close') close_button.add_behavior({ 'type': "click", 'cbjs_action': my.close_action }) table = Table() action_div.add(table) table.center() table.add_row() td = table.add_cell(button) td.add_style("width: 130px") table.add_cell(close_button) action_div.add("<br clear='all'/>") top.add(div) top.add(HtmlElement.br()) top.add(action_div) if my.is_test: rtn_data = {'columns': my.element_names, 'count': len(my.selected_search_keys)} if my.mode == 'export_matched': rtn_data['sql'] = my.table.search_wdg.search.get_statement() from pyasm.common import jsondumps rtn_data = jsondumps(rtn_data) return rtn_data return top
def get_data_wdg(my): div = DivWdg() from pyasm.biz import Pipeline from pyasm.widget import SelectWdg search_type_obj = SearchType.get(my.search_type) base_type = search_type_obj.get_base_key() search = Search("sthpw/pipeline") search.add_filter("search_type", base_type) pipelines = search.get_sobjects() if pipelines: pipeline = pipelines[0] process_names = pipeline.get_process_names() if process_names: table = Table() div.add(table) table.add_row() table.add_cell("Process: ") select = SelectWdg("process") table.add_cell(select) process_names.append("---") process_names.append("publish") process_names.append("icon") select.set_option("values", process_names) #### buttons = Table() div.add(buttons) buttons.add_row() button = IconButtonWdg(title="Fill in Data", icon=IconWdg.EDIT) buttons.add_cell(button) dialog = DialogWdg(display="false", show_title=False) div.add(dialog) dialog.set_as_activator(button, offset={'x': -10, 'y': 10}) dialog_data_div = DivWdg() dialog_data_div.add_color("background", "background") dialog_data_div.add_style("padding", "20px") dialog.add(dialog_data_div) # Order folders by date name_div = DivWdg() dialog_data_div.add(name_div) name_div.add_style("margin: 15px 0px") if SearchType.column_exists(my.search_type, "relative_dir"): category_div = DivWdg() name_div.add(category_div) checkbox = RadioWdg("category") checkbox.set_option("value", "none") category_div.add(checkbox) category_div.add(" No categories") category_div.add_style("margin-bottom: 5px") checkbox.set_option("checked", "true") category_div = DivWdg() name_div.add(category_div) checkbox = RadioWdg("category") checkbox.set_option("value", "by_day") category_div.add(checkbox) category_div.add(" Categorize files by Day") category_div.add_style("margin-bottom: 5px") category_div = DivWdg() name_div.add(category_div) checkbox = RadioWdg("category") checkbox.set_option("value", "by_week") category_div.add(checkbox) category_div.add(" Categorize files by Week") category_div.add_style("margin-bottom: 5px") category_div = DivWdg() name_div.add(category_div) checkbox = RadioWdg("category") checkbox.set_option("value", "by_year") category_div.add(checkbox) category_div.add(" Categorize files by Year") category_div.add_style("margin-bottom: 5px") """ checkbox = RadioWdg("category") checkbox.set_option("value", "custom") name_div.add(checkbox) name_div.add(" Custom") """ name_div.add("<br/>") ingest_data_view = my.kwargs.get('ingest_data_view') from tactic.ui.panel import EditWdg sobject = SearchType.create(my.search_type) edit = EditWdg(search_key=sobject.get_search_key(), mode='view', view=ingest_data_view) dialog_data_div.add(edit) hidden = HiddenWdg(name="parent_key") dialog_data_div.add(hidden) hidden.add_class("spt_parent_key") parent_key = my.kwargs.get("parent_key") or "" if parent_key: hidden.set_value(parent_key) extra_data = my.kwargs.get("extra_data") if not isinstance(extra_data, basestring): extra_data = jsondumps(extra_data) if extra_data and extra_data != "null": # it needs a TextArea instead of Hidden because of JSON data text = TextAreaWdg(name="extra_data") text.add_style('display: none') text.set_value(extra_data) dialog_data_div.add(text) """ dialog_data_div.add("Keywords:<br/>") dialog.add(dialog_data_div) text = TextAreaWdg(name="keywords") dialog_data_div.add(text) text.add_class("spt_keywords") text.add_style("padding: 1px") dialog_data_div.add("<br/>"*2) text.add_class("spt_extra_data") text.add_style("padding: 1px") """ #### TEST Image options """ button = IconButtonWdg(title="Resize", icon=IconWdg.FILM) buttons.add_cell(button) dialog = DialogWdg(display="false", show_title=False) div.add(dialog) dialog.set_as_activator(button, offset={'x':-10,'y':10}) try: from spt.tools.convert import ConvertOptionsWdg convert_div = DivWdg() dialog.add(convert_div) convert_div.add_style("padding: 20px") convert_div.add_color("background", "background") convert_div.add_class("spt_image_convert") convert = ConvertOptionsWdg() convert_div.add(convert) except: pass """ # use base name for name """ name_div = DivWdg() dialog_data_div.add(name_div) name_div.add_style("margin: 15px 0px") checkbox = CheckboxWdg("use_file_name") name_div.add(checkbox) name_div.add(" Use name of file for name") name_div.add("<br/>") checkbox = CheckboxWdg("use_base_name") name_div.add(checkbox) name_div.add(" Remove extension") name_div.add("<br/>") checkbox = CheckboxWdg("file_keywords") name_div.add(checkbox) name_div.add(" Use file name for keywords") """ return div
def get_display(my): if not my.preprocessed: my.preprocess() if my.is_refresh: top = Widget() else: top = DivWdg() top.add_class("spt_work_hours_top") hidden = HiddenWdg('workhour_data') hidden.add_class('spt_workhour_data') header_data = {'start_date': str(my.start_date)} header_data = jsondumps(header_data).replace('"', """) hidden.set_value(header_data, set_form_value=False) top.add(hidden) days = [] for date in my.dates: days.append(date.strftime("%Y_%m_%d")) today = my.today.strftime("%Y_%m_%d") task = my.get_current_sobject() if not my.is_refresh: my.set_as_panel(top) entries = my.entries.get(task.get_code()) if isinstance(task, Task): parent = task.get_parent() if not parent: disabled = True else: disabled = False else: disabled = False if not entries: entries = {} table = Table() top.add(table) if my.use_straight_time: row_list = [my.ST_ROW] if my.show_overtime: row_list.append(my.OT_ROW) prefix_list = ['', 'ot'] else: row_list = [my.STT_ROW, my.ENT_ROW] prefix_list = ['stt', 'ent'] text = HiddenWdg(my.get_name()) text.add_class("spt_data") table.add_color("color", "color") table.add_styles("width: %spx; float: left" % my.table_width) for row_to_draw in row_list: tr = table.add_row() tr.add_style('line-height', '8px') td = table.add_blank_cell() offset_width = my.MONTH_WIDTH + my.LEFT_WIDTH + 8 td.add_style("min-width: %spx" % offset_width) td.add(text) # go through each day and draw an input for overtime total_hours_st = 0 total_hours_ot = 0 search_key = task.get_search_key() # Add a label to indicate if the row is straight time or overtime time_prefix = '' if row_to_draw == my.OT_ROW: time_prefix = 'ot' div = DivWdg() div.add("OT") div.add_styles('text-align: right; margin-right: 4px') td.add(div) elif row_to_draw == my.STT_ROW: time_prefix = 'stt' div = DivWdg() div.add("ST") div.add_styles('text-align: right; margin: 0 4px 4px 0') td.add(div) elif row_to_draw == my.ENT_ROW: time_prefix = 'ent' div = DivWdg() div.add("ET") div.add_styles('text-align: right; margin: 0 4px 4px 0') td.add(div) for idx, day in enumerate(days): day_wdg = DivWdg() day_wdg.add(day) td = table.add_cell() td.add_style("width: %spx" % my.day_width) text = TextWdg('%sday_%s' % (time_prefix, day)) if disabled: text.set_option('read_only', 'true') text.set_attr('disabled', 'disabled') td.add(text) text.add_class('spt_day%s' % (time_prefix)) text.add_styles( "width: %spx;text-align: right;padding-left: 2px" % (my.day_width - 2)) #text.add_styles("width: 100%;text-align: right;padding-left: 2px") if day == today: text.add_style("border: solid 1px black") week_day = my.weekday_dict[idx] if week_day in ['Sat', 'Sun']: # MAIN: Overtime, weekend if row_to_draw == my.OT_ROW: text.add_color("background", "background2", modifier=[-15, 0, 5]) else: text.add_color("background", "background2", modifier=[0, 15, 20]) if row_to_draw == my.OT_ROW: text.add_attr('input_field_type', 'ot') else: text.add_attr('input_field_type', 'st') if my.kwargs.get('show_all_users') == 'false': pass else: text.set_option('read_only', 'true') #TODO: while we may have multiple entries per task, we will only use the latest one here # for now, making the UI cleaner # if a corresponding entry exists, display its value entry_list_dict = entries.get(day) daily_sum = 0 value = 0 entry_list = [] if entry_list_dict: row_key = my.ROW_DICT.get(row_to_draw) entry_list = entry_list_dict.get(row_key) if entry_list: for entry in entry_list: # Check if there is something in the category column. category = entry.get_value("category") if row_to_draw == my.OT_ROW: # Skip if the category field does not have a 'ot' indicated. if not category: print "Warning this work_hour entry has no category [%s]" % entry.get_code( ) continue # Check if there exist a value in the straight_time column value, delta = my.get_time_value(entry, row_to_draw) if value: text.set_value(value) text.add_attr('orig_input_value', value) if row_to_draw == my.OT_ROW: total_hours_ot += float(delta) else: total_hours_st += float(delta) daily_sum += delta # we only use value instead of the sum "daily_sum" for now if row_to_draw == my.OT_ROW: my.summary_ot[idx].update({search_key: daily_sum}) else: my.summary_st[idx].update({search_key: daily_sum}) script = ''' var orig_value = bvr.src_el.getAttribute("orig_input_value"); var input_field_type = bvr.src_el.getAttribute("input_field_type"); bvr.src_el.value = bvr.src_el.value.strip(); if (bvr.src_el.value == '') { if (orig_value) { bvr.src_el.value = 0; } else { return; } } else if (bvr.src_el.value == orig_value) { return; } bvr.prefix_list.splice( bvr.prefix_list.indexOf(bvr.time_prefix),1) var other_time_prefix = bvr.prefix_list[0]; spt.work_hour.update_total(bvr, '.spt_day' + bvr.time_prefix); // register this as changed item var all_top_el = bvr.src_el.getParent(".spt_work_hours_top"); var values1 = spt.api.Utility.get_input_values(all_top_el, '.spt_day'+ bvr.time_prefix, false); var values2 = spt.api.Utility.get_input_values(all_top_el, '.spt_day'+ other_time_prefix, false); // Merge values from straight time and overtime fields in values variable. for (var attr in values2) { values1[attr] = values2[attr]; } for (val in values1) { if (values1[val] && isNaN(values1[val])) { spt.error('You have non-numeric values in your work hours. Please correct it: ' + values[val]); return; } } delete values1.data; var value_wdg = all_top_el.getElement(".spt_data"); var value = JSON.stringify(values1); value_wdg.value = value; var layout = bvr.src_el.getParent(".spt_layout"); var version = layout.getAttribute("spt_version"); if (version == "2") { spt.table.set_layout(layout); spt.table.accept_edit(all_top_el, value, false); } else { var cached_data = {}; spt.dg_table.edit.widget = all_top_el; spt.dg_table.inline_edit_cell_cbk( value_wdg, cached_data ); } ''' # accept on pressing Enter behavior = { 'type': 'keydown', 'time_prefix': time_prefix, 'prefix_list': prefix_list, 'cbjs_action': ''' if (evt.key=='enter') { %s } ''' % script } text.add_behavior(behavior) behavior = { 'type': 'blur', 'time_prefix': time_prefix, 'prefix_list': prefix_list, 'cbjs_action': ''' %s ''' % script } text.add_behavior(behavior) text = TextWdg("total") td = table.add_cell(text) td.add_style("width: 35px") text.add_attr('spt_total', '.spt_total%s' % (time_prefix)) text.add_class('spt_total%s' % (time_prefix)) text.add_styles( "width: %spx; text-align: right; padding-right: 3px" % my.day_width) text.set_attr("readonly", "readonly") # MAIN: Overtime, total. if row_to_draw == my.OT_ROW: text.add_color("background", "background2", modifier=[5, -15, 0]) if total_hours_ot: text.set_value("%0.1f" % total_hours_ot) my.summary_ot[7].update({search_key: total_hours_ot}) else: text.add_color("background", "background2", modifier=[20, 0, 15]) if total_hours_st: text.set_value("%0.1f" % total_hours_st) my.summary_st[7].update({search_key: total_hours_st}) td = table.add_blank_cell() td.add_style('width: 100%') return top
def get_display(my): if not my.preprocessed: my.preprocess() if my.is_refresh: top = Widget() else: top = DivWdg() top.add_class("spt_work_hours_top") hidden = HiddenWdg('workhour_data') hidden.add_class('spt_workhour_data') header_data = {'start_date': str(my.start_date)} header_data = jsondumps(header_data).replace('"', """) hidden.set_value(header_data, set_form_value=False ) top.add(hidden) days = [] for date in my.dates: days.append( date.strftime("%Y_%m_%d") ) today = my.today.strftime("%Y_%m_%d") task = my.get_current_sobject() if not my.is_refresh: my.set_as_panel(top) entries = my.entries.get(task.get_code()) if isinstance(task, Task): parent = task.get_parent() if not parent: disabled = True else: disabled = False else: disabled = False if not entries: entries = {} table = Table() top.add(table) if my.use_straight_time: row_list = [my.ST_ROW] if my.show_overtime: row_list.append(my.OT_ROW) prefix_list = ['','ot'] else: row_list = [my.STT_ROW, my.ENT_ROW] prefix_list = ['stt','ent'] text = HiddenWdg(my.get_name() ) text.add_class("spt_data") table.add_color("color", "color") table.add_styles("width: %spx; float: left"%my.table_width) for row_to_draw in row_list: tr = table.add_row() tr.add_style('line-height','8px') td = table.add_blank_cell() offset_width = my.MONTH_WIDTH + my.LEFT_WIDTH+8 td.add_style("min-width: %spx" % offset_width) td.add(text) # go through each day and draw an input for overtime total_hours_st = 0 total_hours_ot = 0 search_key = task.get_search_key() # Add a label to indicate if the row is straight time or overtime time_prefix = '' if row_to_draw == my.OT_ROW: time_prefix = 'ot' div = DivWdg() div.add("OT") div.add_styles('text-align: right; margin-right: 4px') td.add(div) elif row_to_draw == my.STT_ROW: time_prefix = 'stt' div = DivWdg() div.add("ST") div.add_styles('text-align: right; margin: 0 4px 4px 0') td.add(div) elif row_to_draw == my.ENT_ROW: time_prefix = 'ent' div = DivWdg() div.add("ET") div.add_styles('text-align: right; margin: 0 4px 4px 0') td.add(div) for idx, day in enumerate(days): day_wdg = DivWdg() day_wdg.add(day) td = table.add_cell() td.add_style("width: %spx" % my.day_width) text = TextWdg('%sday_%s' % (time_prefix, day)) if disabled: text.set_option('read_only','true') text.set_attr('disabled','disabled') td.add(text) text.add_class('spt_day%s' % (time_prefix)) text.add_styles("width: %spx;text-align: right;padding-left: 2px" %(my.day_width-2)) #text.add_styles("width: 100%;text-align: right;padding-left: 2px") if day == today: text.add_style("border: solid 1px black") else: text.add_border() week_day = my.weekday_dict[idx] if week_day in ['Sat','Sun']: # MAIN: Overtime, weekend if row_to_draw == my.OT_ROW: text.add_color("background", "background2", modifier=[-15,0,5]) else: text.add_color("background", "background2", modifier= [0,15,20]) text.add_style("margin: 0px 1px") if row_to_draw == my.OT_ROW: text.add_attr('input_field_type', 'ot') else: text.add_attr('input_field_type', 'st') if my.kwargs.get('show_all_users')=='true': text.set_option('read_only','true') #TODO: while we may have multiple entries per task, we will only use the latest one here # for now, making the UI cleaner # if a corresponding entry exists, display its value entry_list_dict = entries.get(day) daily_sum = 0 value = 0 entry_list = [] if entry_list_dict: row_key = my.ROW_DICT.get(row_to_draw) entry_list = entry_list_dict.get(row_key) if entry_list: for entry in entry_list: # Check if there is something in the category column. category = entry.get_value("category") if row_to_draw == my.OT_ROW: # Skip if the category field does not have a 'ot' indicated. if not category: print "Warning this work_hour entry has no category [%s]" % entry.get_code() continue # Check if there exist a value in the straight_time column value, delta = my.get_time_value(entry, row_to_draw) if value: text.set_value(value) text.add_attr('orig_input_value', value) if row_to_draw == my.OT_ROW: total_hours_ot += float(delta) else: total_hours_st += float(delta) daily_sum += delta # we only use value instead of the sum "daily_sum" for now if row_to_draw == my.OT_ROW: my.summary_ot[idx].update({search_key: daily_sum}) else: my.summary_st[idx].update({search_key: daily_sum}) script = ''' var orig_value = bvr.src_el.getAttribute("orig_input_value"); var input_field_type = bvr.src_el.getAttribute("input_field_type"); bvr.src_el.value = bvr.src_el.value.strip(); if (bvr.src_el.value == '') { if (orig_value) { bvr.src_el.value = 0; } else { return; } } else if (bvr.src_el.value == orig_value) { return; } bvr.prefix_list.splice( bvr.prefix_list.indexOf(bvr.time_prefix),1) var other_time_prefix = bvr.prefix_list[0]; spt.work_hour.update_total(bvr, '.spt_day' + bvr.time_prefix); // register this as changed item var all_top_el = bvr.src_el.getParent(".spt_work_hours_top"); var values1 = spt.api.Utility.get_input_values(all_top_el, '.spt_day'+ bvr.time_prefix, false); var values2 = spt.api.Utility.get_input_values(all_top_el, '.spt_day'+ other_time_prefix, false); // Merge values from straight time and overtime fields in values variable. for (var attr in values2) { values1[attr] = values2[attr]; } for (val in values1) { if (values1[val] && isNaN(values1[val])) { spt.error('You have non-numeric values in your work hours. Please correct it: ' + values[val]); return; } } delete values1.data; var value_wdg = all_top_el.getElement(".spt_data"); var value = JSON.stringify(values1); value_wdg.value = value; var layout = bvr.src_el.getParent(".spt_layout"); var version = layout.getAttribute("spt_version"); if (version == "2") { spt.table.set_layout(layout); spt.table.accept_edit(all_top_el, value, false); } else { var cached_data = {}; spt.dg_table.edit.widget = all_top_el; spt.dg_table.inline_edit_cell_cbk( value_wdg, cached_data ); } ''' # accept on pressing Enter behavior = { 'type': 'keydown', 'time_prefix': time_prefix, 'prefix_list': prefix_list, 'cbjs_action': ''' if (evt.key=='enter') { %s } '''%script} text.add_behavior(behavior) behavior = { 'type': 'blur', 'time_prefix': time_prefix, 'prefix_list': prefix_list, 'cbjs_action': ''' %s '''%script} text.add_behavior(behavior) text = TextWdg("total") td = table.add_cell(text) td.add_style("width: 35px") text.add_border() text.add_attr('spt_total', '.spt_total%s' % (time_prefix)) text.add_class('spt_total%s' % (time_prefix)) text.add_styles("width: %spx; text-align: right; padding-right: 3px"%my.day_width) text.set_attr("readonly", "readonly") # MAIN: Overtime, total. if row_to_draw == my.OT_ROW: text.add_color("background", "background2", modifier=[5,-15,0]) if total_hours_ot: text.set_value("%0.1f" % total_hours_ot) my.summary_ot[7].update({search_key: total_hours_ot}) else: text.add_color("background", "background2", modifier=[20,0,15]) if total_hours_st: text.set_value("%0.1f" % total_hours_st) my.summary_st[7].update({search_key: total_hours_st}) td = table.add_blank_cell() td.add_style('width: 100%') return top
def get_display(my): web = WebContainer.get_web() widget = Widget() html = HtmlElement("html") is_xhtml = False if is_xhtml: web.set_content_type("application/xhtml+xml") widget.add('''<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> ''') html.add_attr("xmlns", "http://www.w3.org/1999/xhtml") #html.add_attr("xmlns:svg", "http://www.w3.org/2000/svg") # add the copyright widget.add( my.get_copyright_wdg() ) widget.add(html) # create the header head = HtmlElement("head") html.add(head) head.add('<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>\n') head.add('<meta http-equiv="X-UA-Compatible" content="IE=edge"/>\n') # Add the tactic favicon head.add('<link rel="shortcut icon" href="/context/favicon.ico" type="image/x-icon"/>') # add the css styling head.add(my.get_css_wdg()) # add the title in the header project = Project.get() project_code = project.get_code() project_title = project.get_value("title") if web.is_admin_page(): is_admin = " - Admin" else: is_admin = "" if project_code == 'admin': head.add("<title>TACTIC Site Admin</title>\n" ) else: head.add("<title>%s%s</title>\n" % (project_title, is_admin) ) # add the javascript libraries head.add( JavascriptImportWdg() ) # add the body body = my.body html.add( body ) # Add a NOSCRIPT tag block here to provide a warning message on browsers where 'Enable JavaScript' # is not checked ... TODO: clean up and re-style to make look nicer body.add( """ <NOSCRIPT> <div style="border: 2px solid black; background-color: #FFFF99; color: black; width: 600px; height: 70px; padding: 20px;"> <img src="%s" style="border: none;" /> <b>Javascript is not enabled on your browser!</b> <p>This TACTIC powered, web-based application requires JavaScript to be enabled in order to function. In your browser's options/preferences, please make sure that the 'Enable JavaScript' option is checked on, click OK to accept the settings change, and then refresh this web page.</p> </div> </NOSCRIPT> """ % ( IconWdg.get_icon_path("ERROR") ) ) # add the content if my.widgets: content_wdg = my.get_widget('content') else: content_wdg = Widget() my.add(content_wdg) body.add( content_wdg ) body.add_event('onload', 'spt.onload_startup(this)') if web.is_admin_page(): from tactic_branding_wdg import TacticCopyrightNoticeWdg branding = TacticCopyrightNoticeWdg(show_license_info=True) body.add(branding) # add the admin bar security = Environment.get_security() if not web.is_admin_page() and security.check_access("builtin", "view_site_admin", "allow"): div = DivWdg() body.add(div) body.add_style("padding-top: 21px") div.add_class("spt_admin_bar") div.add_style("height: 15px") div.add_style("padding: 3px 0px 3px 15px") #div.add_style("margin-bottom: -5px") div.add_style("position: fixed") div.add_style("top: 0px") div.add_style("left: 0px") div.add_style("opacity: 0.7") div.add_style("width: 100%") #div.add_gradient("background", "background2", 20, 10) div.add_style("background-color", "#000") div.add_style("color", "#FFF") div.add_style("z-index", "1000") div.add_class("hand") div.set_box_shadow("0px 5px 5px") # remove icon_div = DivWdg() div.add(icon_div) icon_div.add_style("float: right") icon_div.add_style("margin-right: 10px") icon_div.add_style("margin-top: -3px") icon_button = IconButtonWdg(title="Remove Admin Bar", icon=IconWdg.POPUP_WIN_CLOSE) icon_div.add(icon_button) icon_button.add_behavior( { 'type': 'click_up', 'cbjs_action': ''' var parent = bvr.src_el.getParent(".spt_admin_bar"); spt.behavior.destroy_element(parent); $(document.body).setStyle("padding-top", "0px"); ''' } ) div.add("<b>ADMIN >></b>") div.add_behavior( { 'type': 'listen', 'event_name': 'close_admin_bar', 'cbjs_action': ''' spt.behavior.destroy_element(bvr.src_el); $(document.body).setStyle("padding-top", "0px"); ''' } ) div.add_behavior( { 'type': 'mouseover', 'cbjs_action': ''' bvr.src_el.setStyle("opacity", 0.85) //new Fx.Tween(bvr.src_el).start('height', "30px"); ''' } ) div.add_behavior( { 'type': 'mouseout', 'cbjs_action': ''' bvr.src_el.setStyle("opacity", 0.7) //new Fx.Tween(bvr.src_el).start('height', "15px"); ''' } ) project_code = Project.get_project_code() div.add_behavior( { 'type': 'click_up', 'cbjs_action': ''' var url = "/tactic/%s/link/_startup"; window.open(url); ''' % project_code } ) # Add the script editor listener load_div = DivWdg() body.add(load_div) load_div.add_behavior( { 'type': 'listen', 'event_name': 'show_script_editor', 'cbjs_action': ''' var js_popup_id = "TACTIC Script Editor"; var js_popup = $(js_popup_id); if( js_popup ) { spt.popup.toggle_display( js_popup_id, false ); } else { spt.panel.load_popup(js_popup_id, "tactic.ui.app.ShelfEditWdg", {}, {"load_once": true} ); } '''} ) # deal with the palette defined in /index which can override the palette if my.kwargs.get("hash") == (): key = "index" search = Search("config/url") search.add_filter("url", "/%s/%%"%key, "like") search.add_filter("url", "/%s"%key) search.add_where("or") url = search.get_sobject() if url: xml = url.get_xml_value("widget") palette_key = xml.get_value("element/@palette") # look up palette the expression for index from pyasm.web import Palette palette = Palette.get() palette.set_palette(palette_key) colors = palette.get_colors() colors = jsondumps(colors) script = HtmlElement.script(''' var env = spt.Environment.get(); env.set_colors(%s); env.set_palette('%s'); ''' % (colors, palette_key) ) body.add(script) env = Environment.get() client_handoff_dir = env.get_client_handoff_dir(include_ticket=False, no_exception=True) client_asset_dir = env.get_client_repo_dir() login = Environment.get_login() user_name = login.get_value("login") user_id = login.get_id() login_groups = Environment.get_group_names() # add environment information script = HtmlElement.script(''' var env = spt.Environment.get(); env.set_project('%s'); env.set_user('%s'); env.set_user_id('%s'); var login_groups = '%s'.split('|'); env.set_login_groups(login_groups); env.set_client_handoff_dir('%s'); env.set_client_repo_dir('%s'); ''' % (Project.get_project_code(), user_name, user_id, '|'.join(login_groups), client_handoff_dir,client_asset_dir)) body.add(script) # add a global container for commonly used widgets div = DivWdg() body.add(div) div.set_id("global_container") # add in the app busy widget # find out if there is an override for this search = Search("config/url") search.add_filter("url", "/app_busy") url = search.get_sobject() if url: busy_div = DivWdg() div.add(busy_div) busy_div.add_class( "SPT_PUW" ) busy_div.add_styles( "display: none; position: absolute; z-index: 1000" ) busy_div.add_class("app_busy_msg_block") busy_div.add_style("width: 300px") busy_div.add_style("height: 100px") busy_div.add_style("padding: 20px") busy_div.add_color("background", "background3") busy_div.add_border() busy_div.set_box_shadow() busy_div.set_round_corners(20) busy_div.set_attr("id","app_busy_msg_block") # put the custom url here title_wdg = DivWdg() busy_div.add(title_wdg) title_wdg.add_style("font-size: 20px") title_wdg.add_class("spt_app_busy_title") busy_div.add("<hr/>") msg_div = DivWdg() busy_div.add(msg_div) msg_div.add_class("spt_app_busy_msg") else: from page_header_wdg import AppBusyWdg div.add( AppBusyWdg() ) # popup parent popup = DivWdg() popup.set_id("popup") div.add(popup) # create another general popup popup_div = DivWdg() popup_div.set_id("popup_container") popup_div.add_class("spt_panel") popup = PopupWdg(id="popup_template",destroy_on_close=True) popup_div.add(popup) div.add(popup_div) # popup parent inner_html_div = DivWdg() inner_html_div.set_id("inner_html") div.add(inner_html_div) # add in a global color from tactic.ui.input import ColorWdg color = ColorWdg() div.add(color) # add in a global notify wdg from notify_wdg import NotifyWdg widget.add(NotifyWdg()) return widget
def set_to_cgi(self): web = WebContainer.get_web() data = jsondumps(self.data) web.set_form_value('json', data) Container.put("FilterData", self)
# or disclosed in any way without written permission. # # # import tacticenv from pyasm.common import jsonloads, jsondumps from tactic_client_lib import TacticServerStub from pyasm.biz import Project # The variables "function" and "kwargs" are autofilled by Jepp print "function: ", function print "kwargs: ", kwargs kwargs_dict = jsonloads(kwargs) # remap keys so that they are strings kwargs = {} for key,value in kwargs_dict.items(): kwargs[key.encode('utf-8')] = value #server = TacticServerStub.get(protocol='xmlrpc') server = TacticServerStub.get() # convert the args to a dict method = eval('''server.%s''' % function) ret_val = method(**kwargs) ret_val = jsondumps(ret_val)
def get_import_wdg(my): div = DivWdg() if my.data: div.add("<br/>" * 2) div.add("The following TACTIC share was found: ") div.add("<br/>" * 2) data_input = TextAreaWdg("data") data_input.add_style("display: none") div.add(data_input) #print "xxxx: ", my.data data_str = jsondumps(my.data) #data_str = data_str.replace('"', "'") print "data: ", data_str data_input.set_value(data_str) table = Table() div.add(table) table.set_max_width() table.add_style("margin-left: 20px") table.add_style("margin-right: 20px") for name, value in my.data.items(): name = Common.get_display_title(name) table.add_row() table.add_cell(name) table.add_cell(value) div.add("<br/>" * 2) div.add(my.get_versions_wdg()) div.add("<br/>" * 2) # check to see if the project exists project_code = my.data.get("project_code") project_code = my.data.get("projects") project = Project.get_by_code(project_code) #if project: if False: msg_div = DivWdg() div.add(msg_div) msg_div.add_style("padding: 20px") msg_div.add_color("background", "background3") msg_div.add_color("color", "color") msg_div.add_border() icon = IconWdg("WARNING", IconWdg.WARNING) msg_div.add(icon) icon.add_style("float: left") msg_div.add( "The project with code [%s] already exists. You must remove the installed project before trying to import this one." % project_code) return div if my.data.get("is_encrypted") == "true": div.add( "The transactions in this share is encrypted. Please provide an encryption key to decrypt the transactions<br/><br/>" ) div.add("Encryption Key: ") text = TextWdg("encryption_key") div.add(text) div.add("<br/>" * 2) button = ActionButtonWdg(title="Import >>") button.add_style("float: right") div.add(button) div.add("<br/>" * 2) button.add_behavior({ 'type': 'click_up', 'project_code': project_code, 'cbjs_action': ''' spt.app_busy.show("Importing Project "+bvr.project_code+"..."); var top = bvr.src_el.getParent(".spt_sync_import_top"); var values = spt.api.Utility.get_input_values(top, null, false); var cmd = "tactic.ui.sync.SyncImportCmd"; var server = TacticServerStub.get(); server.execute_cmd(cmd, values, {}, {use_transaction: false}); spt.notify.show_message("Finished importing project"); spt.app_busy.hide(); document.location = '/tactic/'+bvr.project_code; ''' }) return div