def _test_cache(self): from pyasm.common import Config Config.set_value("security", "mode", "cache", no_exception=True) #Config.set_value("security", "authenticate_class", "pyasm.security.authenticate_test.AutocreateAuthenticate", no_exception=True) Config.set_value("security", "authenticate_class", "pyasm.security.mms_authenticate.MMSAuthenticate", no_exception=True) mode = Config.get_value("security", "authenticate_class", use_cache=False) mode = Config.get_value("security", "mode", use_cache=False) self.assertEquals(mode, "cache") # verify that the user exists in the database search = Search("sthpw/login") search.add_filter("login", "foofoo") login = search.get_sobject() self.assertEquals(None, login) from pyasm.search import Transaction transaction = Transaction.get(create=True) transaction.start() self.security.login_user("foofoo", "wow") # verify that the user exists in the database search = Search("sthpw/login") search.add_filter("login", "foofoo") login = search.get_sobject() self.assertNotEquals(None, login)
def update_related(self, login_group, prev_login_group): '''Update related table login_in_group''' search = Search('sthpw/login_in_group') search.add_filter('login_group', prev_login_group) login_in_groups = search.get_sobjects() if login_in_groups: server = TacticServerStub.get() login_in_group_dict = {} data = { "login_group": login_group } for login_in_group in login_in_groups: login_in_group_code = login_in_group.get("code") login_in_group_sk = server.build_search_key("sthpw/login_in_group", login_in_group_code) login_in_group_dict[login_in_group_sk] = data try: server.update_multiple(login_in_group_dict) except Exception, e: raise TacticException('Error updating login_in_group %s' % e.str())
def execute(my): assert my.db_resource assert my.table database = my.db_resource.get_database() from pyasm.search import Insert, Select, DbContainer, Search, Sql # get the data if not my.sobjects: search = Search("sthpw/search_object") # BAD assumption #search.add_filter("table", my.table) # create a search_type. This is bad assumption cuz it assumes project-specific search_type # should call set_search_type() if not my.search_type: my.search_type = "%s/%s" % (my.database, my.table) search.add_filter("search_type", my.search_type) my.search_type_obj = search.get_sobject() if not my.search_type_obj: if my.no_exception == False: raise SqlException("Table [%s] does not have a corresponding search_type" % my.table) else: return search_type = my.search_type_obj.get_base_key() search = Search(my.search_type) search.set_show_retired(True) my.sobjects = search.get_sobjects() # get the info for the table column_info = SearchType.get_column_info(my.search_type) for sobject in my.sobjects: print my.delimiter insert = Insert() insert.set_database(my.database) insert.set_table(my.table) data = sobject.data for name, value in data.items(): if name in my.ignore_columns: continue if not my.include_id and name == "id": insert.set_value("id", '"%s_id_seq".nextval' % table, quoted=False) #insert.set_value(name, value, quoted=False) elif value == None: continue else: # replace all of the \ with double \\ insert.set_value(name, value) print "%s" % insert.get_statement() print my.end_delimiter print
def _get_sobject_history_wdg(my): ''' this method is called thru ajax ''' args = WebContainer.get_web().get_form_args() # get the args in the URL search_type = args['search_type'] search_id = args['search_id'] #sobject = Search.get_by_id(search_type, search_id) div = Widget() search = Search("sthpw/sobject_log") search.add_filter("search_type", search_type) search.add_filter("search_id", search_id) sobjects = search.get_sobjects() search = Search("sthpw/transaction_log") search.add_filters("id", [x.get_value("transaction_log_id") for x in sobjects] ) sobjects = search.get_sobjects() table = TableWdg("sthpw/transaction_log", "table", css='table') table.set_show_property(False) table.set_sobjects(sobjects) div.add(table) div.add(HtmlElement.br(2)) return div div.add(assigned_shot_wdg) div.add(HtmlElement.br(2)) return div
def main(server=None, input_data=None): if not input_data: input_data = {} if not server: server = TacticServerStub.get() input_sobject = input_data.get('sobject') order_code = input_sobject.get('code') priority = input_sobject.get('priority') component_search = Search('twog/component') component_search.add_filter('order_code', order_code) component_sobjects = component_search.get_sobjects() for component_sobject in component_sobjects: tasks = get_task_sobjects_from_component_sobject(component_sobject) data_to_insert = {} for task in tasks: task_search_key = server.build_search_key('sthpw/task', task.get_code(), project_code='twog') data_to_insert[task_search_key] = {'priority': priority} server.update_multiple(data_to_insert)
def get_def_config(my, def_xml=None): def_confg = None my.def_view = my.kwargs.get('definition') if my.def_view: #raise TacticException("No definition view defined in custom layout with view [%s]" % my.view) my.search_type = "CustomLayoutWdg" search = Search("config/widget_config") search.add_filter("search_type", my.search_type) search.add_filter("view", my.def_view) def_db_config = search.get_sobject() if not def_db_config: raise TacticException("Definition config [%s] not defined" % my.def_view) def_xml = def_db_config.get_xml() def_config = WidgetConfig.get("definition", xml=def_xml) # also look inline to see if there are any definitions if def_xml: # just use the passed in xml for a definition def_config = WidgetConfig.get(my.view, xml=def_xml) return def_config
def get_client_img(client_code): img_path = '' client_search = Search("twog/client") client_search.add_filter('code', client_code) client_search_object = client_search.get_sobject() if client_search_object: client_id = client_search_object.get_id() snaps_s = Search("sthpw/snapshot") snaps_s.add_filter('search_id', client_id) snaps_s.add_filter('search_type', 'twog/client?project=twog') snaps_s.add_filter('is_current', '1') snaps_s.add_filter('version', '0', op='>') snaps_s.add_where("\"context\" in ('publish','icon','MISC')") snaps_s.add_order_by('timestamp desc') snaps = snaps_s.get_sobjects() if len(snaps) > 0: server = TacticServerStub.get() snap = snaps[0] img_path = server.get_path_from_snapshot(snap.get_code(), mode="web") if img_path: img_path = 'http://' + server.get_server_name() + img_path return img_path else: return None
def handle_nodes(my, nodes): for node in nodes: node_name = my.xml.get_node_name(node) if node_name == 'search_type': my.remove_search_type(node) elif node_name == 'sobject': my.remove_sobjects(node) elif node_name == 'include': my.handle_include(node) elif node_name == 'python': my.handle_python(node) # remove plugin contents search = Search("config/plugin_content") search.add_filter("plugin_code", my.code) plugin_contents = search.get_sobjects() for plugin_content in plugin_contents: plugin_content.delete() # deregister the plugin plugin = Search.eval("@SOBJECT(config/plugin['code','%s'])" % my.code, single=True) if plugin: plugin.delete()
def execute(my): view = my.kwargs.get("view") content = my.kwargs.get("content") search = Search("config/widget_config") search.add_filter("category", "HelpWdg") search.add_filter("view", view) config = search.get_sobject() if not config: config = SearchType.create("config/widget_config") config.set_value("category", "HelpWdg") config.set_value("view", view) config_xml = ''' <config> <%s> <html><div><![CDATA[ %s ]]></div></html> </%s> </config> ''' % (view, content, view) config.set_value("config", config_xml) config.commit()
def execute(my): my.add_description("Set task's context to match process if empty") search = Search('sthpw/task') search.add_filter('context', None) tasks = search.get_sobjects() if tasks and len(tasks) > 700: print "More than 700 tasks are found. Exiting as a precaution." sys.exit(0) if not tasks: print "All tasks have context attribute filled in. Exiting." sys.exit(0) ctr = 0 for task in tasks: context = task.get_value('context') process = task.get_value('process') search_type = task.get_value('search_type') # delete dangling task if not search_type: task.delete() continue if not context and process: task.set_value('context', process) task.commit(triggers=False) ctr += 1 print "%s tasks have been processed. Their context are matched with their process." %ctr
def get_by_search_type(cls, search_type, project_code=''): # make sure this is a be search type assert search_type search_type_obj = SearchType.get(search_type) if not search_type_obj: return [] search_type = search_type_obj.get_base_key() cache_key = "%s|%s" % (search_type, project_code) # commenting out until we have a full implementation of # project pipelines """ search = Search("config/pipeline") if search_type: search.add_filter("search_type", search_type) search.add_project_filter(project_code) pipelines = cls.get_by_search(search, cache_key, is_multi=True) """ search = Search("sthpw/pipeline") if search_type: search.add_filter("search_type", search_type) search.add_project_filter(project_code) pipelines = cls.get_by_search(search, cache_key, is_multi=True) if not pipelines: return [] for pipe in pipelines: code = pipe.get_code() cls.cache_sobject('sthpw/pipeline|%s' %code, pipe) return pipelines
def get_input_snapshots(my, sobject, process_name, input_name, version='latest'): '''gets the snapshots of the input''' assert version in ['latest', 'current'] process_node = my.xml.get_node( "pipeline/process[@name='%s']/input[@name='%s']" % (process_name, input_name)) search_type = Xml.get_attribute(process_node, "search_type") context = Xml.get_attribute(process_node, "context") filter = Xml.get_attribute(process_node, "filter") # get the sobjects sobjects = sobject.get_all_children(search_type) # get the snapshots search = Search("sthpw/snapshot") search.add_filter('context', context) #if version == 'latest': # search.add_filter("is_latest", 1) #elif version == 'current': # search.add_filter("is_current", 1) # build filters for search_type, search_id combinations filters = [] for sobject in sobjects: filter = "(\"search_type\" = '%s' and \"search_id\" = %s)" % (sobject.get_search_type(), sobject.get_id() ) filters.append(filter) search.add_where( "( %s )" % " or ".join(filters) ) snapshots = search.get_sobjects() return snapshots
def _test_task(my): project = Project.get() # create a new task task = SearchType.create("sthpw/task") task.set_parent(project) task.set_value("code", "XXX001") task.set_value("process", "unittest") task.set_value("description", "unittest") # set a time with no timezone. A timestamp with no timezone should # assume GMT. test_time = '2011-11-11 00:00:00' task.set_value("timestamp", test_time) # asset that the time has not changed timestamp = task.get_value("timestamp") my.assertEquals(timestamp, test_time) task.commit() # get the task back from the databse search = Search("sthpw/task") search.add_filter("code", "XXX001") task = search.get_sobject() # make sure the time has not changed. This value should is assumed # to be in GMT timestamp = task.get_value("timestamp") my.assertEquals(timestamp, test_time) task.delete()
def get_art_reference(self): widget = Widget() help = HelpItemWdg('References', 'References tab lets the user organize art references. Each reference can be [related] to one or more assets defined in TACTIC. It can be set up when you [Edit] the reference.') self.add(help) div = DivWdg(css="filter_box") widget.add(div) columns = ['description','keywords'] search_filter = SearchFilterWdg("art_ref_search", columns=columns,\ has_persistence=False) div.add(search_filter) select = FilterSelectWdg("art_ref_category", label='Category: ', css='snall') select.set_option("setting", "art_reference_category") select.add_empty_option('-- Any --') div.add( select ) table = TableWdg("prod/art_reference") search = Search("prod/art_reference") search_filter.alter_search(search) value = select.get_value() if value != "": search.add_filter("category", value) table.set_search(search) widget.add(table) return widget
def check_existing_jobs(self): self.keep_jobs = [] for job in self.jobs: job_code = job.get_code() search = Search(self.get_job_search_type()) search.add_filter("code", job_code) job = search.get_sobject() if not job: print("Cancel ....") scheduler = Scheduler.get() scheduler.cancel_task(job_code) continue state = job.get_value("state") if state == 'cancel': print("Cancel task [%s] ...." % job_code) scheduler = Scheduler.get() scheduler.cancel_task(job_code) job.set_value("state", "terminated") job.commit() continue self.keep_jobs.append(job) self.jobs = self.keep_jobs
def get_display(my): widget = DivWdg(id='link_view_select') widget.add_class("link_view_select") if my.refresh: widget = Widget() else: my.set_as_panel(widget) views = [] if my.search_type: from pyasm.search import WidgetDbConfig search = Search( WidgetDbConfig.SEARCH_TYPE ) search.add_filter("search_type", my.search_type) search.add_regex_filter("view", "link_search:|saved_search:", op="NEQI") search.add_order_by('view') widget_dbs = search.get_sobjects() views = SObject.get_values(widget_dbs, 'view') labels = [view for view in views] views.insert(0, 'table') labels.insert(0, 'table (Default)') st_select = SelectWdg('new_link_view', label='View: ') st_select.set_option('values', views) st_select.set_option('labels', labels) widget.add(st_select) return widget
def execute(my): my.collection_key = my.kwargs.get("collection_key") collection = Search.get_by_search_key(my.collection_key) collection_code = collection.get("code") search_type = collection.get_base_search_type() parts = search_type.split("/") collection_type = "%s/%s_in_%s" % (parts[0], parts[1], parts[1]) search = Search(collection_type) search.add_filter("parent_code", collection.get_code()) items = search.get_sobjects() for item in items: item.delete() # Also need to delete the asset_in_asset relationships in its parent collections parent_search = Search(collection_type) parent_search.add_filter("search_code", collection.get_code()) parent_items = parent_search.get_sobjects() for parent_item in parent_items: parent_item.delete() collection.delete() my.add_description("Remove Collection [%s]" % collection_code)
def init(my): from pyasm.common import Environment from pyasm.search import Search my.login = Environment.get_login() my.user = my.login.get_login() my.sk = '' my.seen_groups = [] my.bigdict = {} my.indi_pct = 0.0 my.stat_colors = {'Pending':'#d7d7d7','In Progress':'#f5f3a4','In_Progress':'#f5f3a4','On Hold':'#e8b2b8','On_Hold':'#e8b2b8','Client Response': '#ddd5b8', 'Completed':'#b7e0a5','Need Buddy Check':'#e3701a','Ready':'#b2cee8','Internal Rejection':'#ff0000','External Rejection':'#ff0000','Fix Needed':'#c466a1','Failed QC':'#ff0000','Rejected': '#ff0000','DR In_Progress': '#d6e0a4', 'DR In Progress': '#d6e0a4','Amberfin01_In_Progress':'#D8F1A8', 'Amberfin01 In Progress':'#D8F1A8','Amberfin02_In_Progress':'#F3D291', 'Amberfin02 In Progress':'#F3D291','BATON In_Progress': '#c6e0a4', 'BATON In Progress': '#c6e0a4','Export In_Progress': '#796999','Export In Progress': '#796999', 'Buddy Check In_Progress': '#1aade3','Buddy Check In Progress': '#1aade3'} my.stat_relevance = {'Pending': 0,'In Progress': 4,'In_Progress': 4,'On Hold': 1,'On_Hold': 1,'Client Response': 2, 'Completed': -1,'Need Buddy Check': 10, 'Buddy Check In_Progress': 11, 'Buddy Check In Progress': 11, 'Ready': 3,'Internal Rejection': 12,'External Rejection': 13,'Failed QC': 14,'Fix Needed': 16,'Rejected': 15,'DR In_Progress': 5, 'DR In Progress': 5,'BATON In_Progress': 8, 'BATON In Progress': 8,'Export In_Progress': 9, 'Export In Progress': 9,'Amberfin01_In_Progress': 6, 'Amberfin01 In Progress': 6, 'Amberfin02_In_Progress':7, 'Amberfin02 In Progress':7 } my.timestamp = my.make_timestamp() my.date = my.timestamp.split(' ')[0] my.real_date = datetime.datetime.strptime(my.date, '%Y-%m-%d') my.all_groups = [] my.big_user = False users_s = Search('sthpw/login') users_s.add_filter('location','internal') users = users_s.get_sobjects() my.username_lookup = {'': '', None: '', 'NOTHING': ''} for user in users: login_name = user.get_value('login') fname = user.get_value('first_name') lname = user.get_value('last_name') my.username_lookup[login_name] = '%s %s' % (fname, lname)
def execute(self): web = WebContainer.get_web() if web.get_form_value("update") != "true": return self.element_name = self.kwargs.get("element_name") security_groups = web.get_form_values("security") from pyasm.security import AccessRuleBuilder, AccessManager rule_group = "side_bar" for security_group in security_groups: if not security_group: continue search = Search("sthpw/login_group") search.add_filter("login_group", security_group) login_group = search.get_sobject() assert login_group access_rules = login_group.get_xml_value("access_rules") # add the rule to each group builder = AccessRuleBuilder(access_rules) builder.add_rule(rule_group, self.element_name, "deny") login_group.set_value("access_rules", builder.to_string()) login_group.commit()
def setUp(my): # start batch environment Batch() from pyasm.web.web_init import WebInit WebInit().execute() my.sample3d_env = Sample3dEnvironment(project_code='sample3d') my.sample3d_env.create() my.test_env = UnittestEnvironment() my.test_env.create() # set up the proper project_type, with the use the ProdDirNaming and ProdFileNaming search = Search('sthpw/project') search.add_filter('code', 'unittest') my.sobj = search.get_sobject() # store the original setting in your database my.original_proj_type_dict = {'dir_naming_cls': my.sobj.get_value('dir_naming_cls'), 'file_naming_cls': my.sobj.get_value('file_naming_cls') } #my.transaction = Transaction.get(create=True) if my.sobj: my.sobj.set_value('dir_naming_cls', 'pyasm.prod.biz.ProdDirNaming') my.sobj.set_value('file_naming_cls', 'pyasm.prod.biz.ProdFileNaming') my.sobj.commit() else: my.sobj = SearchType.create('sthpw/project_type') my.sobj.set_value('dir_naming_cls', 'pyasm.prod.biz.ProdDirNaming') my.sobj.set_value('file_naming_cls', 'pyasm.prod.biz.ProdFileNaming') my.sobj.set_value('code', 'unittest') my.sobj.commit()
def delete_sobject(my, sobject): search_type = sobject.get_base_search_type() # this is used by API method delete_sobject auto_discover = my.kwargs.get("auto_discover") values = my.kwargs.get("values") if values: related_types = values.get("related_types") elif auto_discover: related_types = SearchType.get_related_types(search_type, direction="children") else: related_types = None # always delete notes and task and snapshot #if not related_types: # related_types = ['sthpw/note', 'sthpw/task', 'sthpw/snapshot'] #related_types = my.schema.get_related_search_types(search_type) if related_types: for related_type in related_types: if not related_type or related_type == search_type: continue # snapshots take care of sthpw/file in the proper manner, so # skip them here if related_type == 'sthpw/file': continue related_sobjects = sobject.get_related_sobjects(related_type) for related_sobject in related_sobjects: if related_type == 'sthpw/snapshot': my.delete_snapshot(related_sobject) else: related_sobject.delete() # implicitly remove "directory" files associated with the sobject search = Search("sthpw/file") search.add_op("begin") search.add_filter("file_name", "") search.add_null_filter("file_name") search.add_op("or") search.add_parent_filter(sobject) file_objects = search.get_sobjects() for file_object in file_objects: base_dir = Environment.get_asset_dir() relative_dir = file_object.get("relative_dir") lib_dir = "%s/%s" % (base_dir, relative_dir) print "removing: ", lib_dir FileUndo.rmdir(lib_dir) file_object.delete() # finally delete the sobject print "deleting: ", sobject.get_search_key() if search_type == 'sthpw/snapshot': my.delete_snapshot(sobject) else: sobject.delete()
def get_deliverable_files_in_order(order_sobject): """ Given an order sobject, return all the deliverable files associated with it. :param order_sobject: twog/order sobject :return: List of twog/file sobjects """ files_in_order_search = Search('twog/file_in_order') files_in_order_search.add_filter('order_code', order_sobject.get_code()) files_in_order = files_in_order_search.get_sobjects() if files_in_order: files_in_order_string = ','.join( ["'{0}'".format(files_in_order.get('file_code')) for files_in_order in files_in_order] ) deliverable_files_search = Search('twog/file') deliverable_files_search.add_where('\"code\" in ({0})'.format(files_in_order_string)) deliverable_files_search.add_filter('classification', 'deliverable') deliverable_files = deliverable_files_search.get_sobjects() return deliverable_files else: return []
def get_task_estimated_hours_from_package_task_code(task_code): """ From a sthpw/task sobject, assumed to be attached to a twog/package, get the estimated hours for the task. This is taken from the twog/platform_connection sobject related to the package. :param task_code: sthpw/task code (must be for a twog/package) :return: Float """ # Get the task sobject task = get_sobject_by_code('sthpw/task', task_code) # Get the package sobject package = task.get_parent() # Get the platform code, used for the platform_connection search platform_code = package.get('platform_code') # Get the division code, also for the platform_connection search division = get_client_division_sobject_from_order_code(package.get('order_code')) division_code = division.get_code() # Search for the platform_connection platform_connection_search = Search('twog/platform_connection') platform_connection_search.add_filter('platform_code', platform_code) platform_connection_search.add_filter('division_code', division_code) platform_connection = platform_connection_search.get_sobject() # Get the estimated hours, and convert to a float estimated_hours = float(platform_connection.get('estimated_hours')) return estimated_hours
def get_results(my): code = my.kwargs.get("code") script_path = my.kwargs.get("script_path") file_path = my.kwargs.get("file_path") # if a script path is specified, then get it from the custom_script # table if script_path: folder = os.path.dirname(script_path) title = os.path.basename(script_path) search = Search("config/custom_script") search.add_filter("folder", folder) search.add_filter("title", title) custom_script = search.get_sobject() if not custom_script: raise TacticException("Custom script with path [%s/%s] does not exist" % (folder, title) ) code = custom_script.get_value("script") elif file_path: f = open(file_path) code = f.read() f.close() wrapper = JsWrapper.get() results = wrapper.execute_func(code, my.kwargs) return results
def execute(my): my.collection_key = my.kwargs.get("collection_key") my.search_keys = my.kwargs.get("search_keys") collection = Search.get_by_search_key(my.collection_key) collection_code = collection.get("code") sobjects = Search.get_by_search_keys(my.search_keys) search_codes = [x.get_code() for x in sobjects] search_type = collection.get_base_search_type() parts = search_type.split("/") collection_type = "%s/%s_in_%s" % (parts[0], parts[1], parts[1]) search = Search(collection_type) search.add_filter("parent_code", collection.get_code()) search.add_filters("search_code", search_codes) items = search.get_sobjects() for item in items: item.delete() my.add_description("Remove [%s] item(s) from Collection [%s]" % (len(my.search_keys), collection_code))
def execute(my): my.init() # create the filters my.filters = [] """ for element_name in my.config.get_element_names(): filter = my.config.get_display_widget(element_name) my.filters.append(filter) # make sure there is at least one filter defined assert my.filters """ config = "<config>\n" config += "<filter>\n" # get all of the serialized versions of the filters """ for filter in my.filters: config += filter.serialize() + "\n" """ filter_data = FilterData.get() json = filter_data.serialize() value_type = "json" config += "<values type='%s'>%s</values>\n" % (value_type, json) config += "</filter>\n" config += "</config>\n" # format the xml xml = Xml() xml.read_string(config) if not my.view: saved_view = "saved_search:%s" % my.search_type else: saved_view = my.view # if my.view.startswith("saved_search:"): # saved_view = my.view # else: # saved_view = "saved_search:%s" % my.view # use widget config instead search = Search("config/widget_config") search.add_filter("view", saved_view) search.add_filter("search_type", my.search_type) if my.personal: search.add_user_filter() config = search.get_sobject() if not config: config = SearchType.create("config/widget_config") config.set_value("view", saved_view) config.set_value("search_type", my.search_type) if my.personal: config.set_user() config.set_value("config", xml.to_string()) config.commit()
def handle_config2(my): """for db column search config stuff, not used yet""" web = WebContainer.get_web() search_type = "SearchTypeSchema" view = "definition" config_search_type = "config/widget_config" search = Search(config_search_type) search.add_filter("search_type", search_type) search.add_filter("view", view) config = search.get_sobject() if not config: config = SearchType.create(config_search_type) config.set_value("search_type", search_type) config.set_value("view", view) xml = config.get_xml_value("config", "config") root = xml.get_root_node() # reinitialize config._init() # build a new config view_node = xml.create_element(view) root.appendChild(view_node) config_mode = web.get_form_value("config_mode") if config_mode == "advanced": config_string = web.get_form_value("config_xml") else: config_data_type = web.get_form_value("config_data_type") if config_data_type == "Other...": config_data_type = web.get_form_value("config_data_type_custom") config_nullable = web.get_form_value("config_nullable") # TAKEN FROM API: should be centralized or something from tactic.ui.panel import SideBarBookmarkMenuWdg config_view = SideBarBookmarkMenuWdg.get_config(search_type, view) node = config_view.get_element_node(my.element_name) if node: config_xml = config_view.get_xml() node = config_view.get_element_node(my.element_name) Xml.set_attribute(node, "data_type", config_data_type) Xml.set_attribute(node, "nullable", config_nullable) Xml.set_attribute(node, "new", "True") config_string = config_xml.to_string(node) else: config_string = """ <element name="%s" data_type="%s" nullable="%s" new="True"/> """ % ( my.element_name, config_data_type, config_nullable, ) config.append_xml_element(my.element_name, config_string) config.commit_config()
def get_audio_configuration_table(element_eval_sobject): audio_configuration_lines_search = Search('twog/audio_evaluation_line') audio_configuration_lines_search.add_filter('element_evaluation_code', element_eval_sobject.get_code()) audio_configuration_lines = audio_configuration_lines_search.get_sobjects() # If no audio configuration lines exist for this element evaluation, return None so that the PDF won't display # a table if not audio_configuration_lines: return None audio_configuration_table_data = [ [ get_paragraph('<strong>Channel</strong>'), get_paragraph('<strong>Content</strong>'), get_paragraph('<strong>Tone</strong>'), get_paragraph('<strong>Peak</strong>') ] ] for line in audio_configuration_lines: channel = line.get('channel') content = line.get('content') tone = line.get('tone') peak = line.get('peak') # If all the items in a row are blank, skip it if any([channel, content, tone, peak]): line_data = [channel, content, tone, peak] audio_configuration_table_data.append(line_data) audio_configuration_table = Table(audio_configuration_table_data, hAlign='LEFT', spaceBefore=5, spaceAfter=5) return audio_configuration_table
def get_display(self): self.order_sk = str(self.kwargs.get("order_sk")) self.title_code = str(self.kwargs.get("title_code")) full_title = str(self.kwargs.get("full_title")) delivs_search = Search("twog/work_order_deliverables") delivs_search.add_filter("title_code", self.title_code) delivs = delivs_search.get_sobjects() linked = [] for d in delivs: linked.append(d.get_value("satisfied")) satisfied = 0 unsatisfied = 0 for link in linked: if link == True: satisfied += 1 else: unsatisfied += 1 table = Table() table.add_row() deliverable_launcher = table.add_cell("<u>Delivs: (%s/%s)</u>" % (satisfied, satisfied + unsatisfied)) deliverable_launcher.add_attr("nowrap", "nowrap") deliverable_launcher.add_attr("valign", "bottom") deliverable_launcher.add_style("font-size: 80%;") deliverable_launcher.add_style("font-color: #2e2e2e;") deliverable_launcher.add_style("cursor: pointer;") deliverable_launcher.add_behavior(get_launch_deliverables_behavior(self.order_sk, self.title_code, full_title)) return table
def preprocess(self): sobjects = self.sobjects if not sobjects: return # find all of the instances in a shot sobject = sobjects[0] foreign_key = sobject.get_foreign_key() search_type = WebState.get().get_state("planner_search_type") search = Search( search_type ) search.add_column(foreign_key) if len(sobjects) == 1: search.add_filter(foreign_key, sobject.get_code()) else: search_codes = [x.get_code() for x in sobjects] search.add_filters(foreign_key, search_codes) search_type = sobject.get_search_type() search.add_order_by(foreign_key) children = search.get_sobjects() # convert to a dictionary for child in children: code = child.get_value(foreign_key) number = self.numbers.get(code) if not number: number = 0 number += 1 self.numbers[code] = number
def get_by_login(login): search = Search(RemoteRepo.SEARCH_TYPE) search.add_filter('login', login) repo = RemoteRepo.get_by_search(search, login) return repo
def get_project_db_resource(my, database=None): # get the db resource for attached to this particular project. # Not the db_resource for "sthpw/project" for which # project.get_db_resource() does key = "Project:db_resource_cache" resource_dict = Container.get(key) if resource_dict: resource = resource_dict.get(my.get_code()) if resource != None: return resource else: resource_dict = {} Container.put(key, resource_dict) # the project defines the resource if not database: database = my.get_database_name() assert database if database == 'sthpw': # get if from the config db_resource_code = None else: db_resource_code = my.get_value("db_resource", no_exception=True) if not db_resource_code: # this could be any project, not just sthpw # already looked at cache, so set use_cache to False db_resource = DbResource.get_default(database, use_cache=False) #Container.put(key, db_resource) resource_dict[key] = db_resource return db_resource #elif isinstance(db_resource_code, DbResource): elif DbResource.is_instance(db_resource_code): db_resource = db_resource_code #Container.put(key, db_resource) resource_dict[key] = db_resource return db_resource db_resource_code = db_resource_code.strip() search = Search("sthpw/db_resource") search.add_filter("code", db_resource_code) db_resource_sobj = search.get_sobject() if not db_resource_sobj: raise TacticException("Database Resource [%s] does not exist" % db_resource_code) host = db_resource_sobj.get_value("host") vendor = db_resource_sobj.get_value("vendor") host = db_resource_sobj.get_value("host") port = db_resource_sobj.get_value("port") user = db_resource_sobj.get_value("login") password = db_resource_sobj.get_value("password") db_resource = DbResource(user=user, database=database, host=host, port=port, vendor=vendor, password=password) #Container.put(key, db_resource) resource_dict[key] = db_resource return db_resource
def preprocess(my): '''determine if this is for EditWdg or EDIT ROW of a table''' # get the number of task pipelines needed for EditWdg, which is one # for the EDIT ROW , there could be more than 1 my.task_mapping = None from tactic.ui.panel import EditWdg if hasattr(my, 'parent_wdg') and isinstance(my.get_parent_wdg(), EditWdg): task = my.get_current_sobject() task_pipe_code = task.get_value('pipeline_code') # if the current task has no pipeline, then search for # any task pipeline if not task_pipe_code: # just use the default task_pipe_code = 'task' pipeline = Pipeline.get_by_code(task_pipe_code) if not pipeline: pipeline = Pipeline.get_by_code('task') my.task_pipelines = [pipeline] else: # get all of the pipelines for tasks search = Search('sthpw/pipeline') search.add_regex_filter('search_type', 'sthpw/task') my.task_pipelines = search.get_sobjects() # get all of the pipelines for the current search_type search_type = my.state.get("search_type") search = Search('sthpw/pipeline') if search_type: search.add_filter('search_type', search_type) my.sobject_pipelines = search.get_sobjects() # insert the default task pipeline if not overridden in the db default_task_found = False pipeline_codes = SObject.get_values(my.task_pipelines, 'code') if 'task' in pipeline_codes: default_task_found = True if not default_task_found: default_pipe = Pipeline.get_by_code('task') my.task_pipelines.append(default_pipe) my.task_mapping = {} # the following works for insert but on edit, it should read from pipeline_code attribute for pipeline in my.sobject_pipelines: processes = pipeline.get_process_names() for process in processes: attrs = pipeline.get_process_attrs(process) task_pipeline = attrs.get('task_pipeline') if task_pipeline: key = '%s|%s' % (pipeline.get_code(), process) my.task_mapping[key] = task_pipeline #my.task_mapping = "|".join(my.task_mapping) my.is_preprocess = True
def execute(my): data = my.kwargs.get("data") for pipeline_code, pipeline_data in data.items(): pipeline = Pipeline.get_by_code(pipeline_code) if not pipeline: pipeline = SearchType.create("sthpw/pipeline") pipeline.set_value("code", pipeline_code) # get the task_pipeline for this process prev_pipeline_xml = pipeline.get_value("pipeline") # get the input data processes = pipeline_data.get("process") statuses = pipeline_data.get("task_status") descriptions = pipeline_data.get("description") # go through each process and build up the xml pipeline_xml = my.create_pipeline_xml(processes) pipeline.set_value("pipeline", pipeline_xml) pipeline.set_pipeline(pipeline_xml) pipeline.on_insert() pipeline_xml = pipeline.get_xml_value("pipeline") # need to commit to get the pipeline code pipeline.commit() pipeline_code = pipeline.get_value("code") # this one doesn't call pipeline.update_process_table() since it adds additional description for i, process in enumerate(processes): if not process: continue description = descriptions[i] # create the process as well search = Search("config/process") search.add_filter("pipeline_code", pipeline_code) search.add_filter("process", process) process_obj = search.get_sobject() if process_obj: if description != process_obj.get_value("description"): process_obj.set_value("description", description) process_obj.commit() # handle the statuses for each process for process, status in zip(processes, statuses): if process == '': continue if status == '(default)': node = pipeline_xml.get_node( "/pipeline/process[@name='%s']" % process) pipeline_xml.del_attribute(node, "task_pipeline") default_pipeline = Pipeline.get_by_code('task') default_pipeline.update_process_table() continue status_list = status.split(",") status_xml = my.create_pipeline_xml(status_list) project_code = Project.get_project_code() status_code = "%s/%s" % (project_code, process) status_pipeline = Search.get_by_code("sthpw/pipeline", status_code) if not status_pipeline: status_pipeline = SearchType.create("sthpw/pipeline") status_pipeline.set_value( "description", 'Status pipeline for process [%s]' % process) status_pipeline.set_value("code", status_code) status_pipeline.set_value("search_type", "sthpw/task") # update_process_table relies on this status_pipeline.set_pipeline(status_xml) else: status_pipeline.set_pipeline(status_xml) status_pipeline.on_insert() status_pipeline.set_value("pipeline", status_xml) status_pipeline.commit() status_pipeline_code = status_pipeline.get_code() # get the process node node = pipeline_xml.get_node("/pipeline/process[@name='%s']" % process) pipeline_xml.set_attribute(node, "task_pipeline", status_pipeline_code) # commit the changes again to get the task pipelines pipeline.set_value("pipeline", pipeline_xml.to_string()) pipeline.commit()
def preprocess(my): # find out if there is a snapshot associated with this path #print "sobject: ", my.sobject #context = "design/%s" % basename #search = Search("sthpw/snapshot") #search.add_filter("context", context) #my.sobject = search.get_sobject() search_key = my.kwargs.get("search_key") my.sobject = Search.get_by_search_key(search_key) md5s = my.kwargs.get("md5s") sizes = my.kwargs.get("sizes") # bit of a hack get the file system paths spaths = [] my.md5s = {} my.sizes = {} for i, path in enumerate(my.paths): #path = Common.get_filesystem_name(path) #new_path = path.replace(" ", "_") new_path = path spaths.append(new_path) my.md5s[new_path] = md5s.get(path) my.sizes[new_path] = sizes.get(path) process = my.kwargs.get("process") # need to match up files search = Search("sthpw/file") search.add_sobject_filter(my.sobject) snapshots = [] if process: search2 = Search("sthpw/snapshot") search2.add_filter("process", process) search2.add_filter("is_latest", True) search2.add_sobject_filter(my.sobject) search2.order_by = False snapshots = search2.get_sobjects() search.add_relationship_search_filter(search2) #search.add_filters("source_path", spaths) sobjects = search.get_sobjects() my.snapshots_dict = {} for snapshot in snapshots: my.snapshots_dict[snapshot.get_code()] = snapshot my.base_dir = my.kwargs.get("base_dir") my.checked_in_paths = {} for sobject in sobjects: source_path = sobject.get_value("source_path") if not source_path: print "WARNING: source_path for file [%s] is empty" % sobject.get_code( ) continue my.checked_in_paths[source_path] = sobject relative_dir = sobject.get_value("relative_dir") file_name = sobject.get_value("file_name") file_name = os.path.basename(source_path) relative_path = "%s/%s" % (relative_dir, file_name) sandbox_dir = Environment.get_sandbox_dir() sandbox_path = "%s/%s" % (sandbox_dir, relative_path) my.checked_in_paths[sandbox_path] = sobject # this is advanced option my.context_options = my.kwargs.get("context_options") my.subcontext_options = my.kwargs.get("subcontext_options") if not my.subcontext_options: my.subcontext_options = [] my.preselected = my.kwargs.get("preselected") my.use_applet = my.kwargs.get("use_applet")
def get_order_priority_relative_to_all_orders(order_sobject): higher_priority_order_search = Search('twog/order') higher_priority_order_search.add_filter('priority', order_sobject.get('priority'), op='<') higher_priority_orders = higher_priority_order_search.get_sobjects() return len(higher_priority_orders) + 1
def get_category_wdg(my, category, mode="new"): subscriptions = my.get_subscriptions(category, mode) if not subscriptions: return div = DivWdg() div.add_style("width: 100%") title_div = DivWdg() div.add(title_div) title_div.add_style("padding: 10px") title_div.add_border() title_div.add_color("background", "background3") title = category or "Subscriptions" title_div.add("%s " % title) summary_div = SpanWdg() title_div.add(summary_div) summary_div.add_style("font-size: 0.8em") summary_div.add_style("opacity: 0.5") search_keys = [x.get_search_key() for x in subscriptions] button = ActionButtonWdg(title="Clear All") button.add_styles('float: right; padding: 2px') button_div = DivWdg(button) button_div.add_style('min-height: 26px') div.add(button_div) button.add_behavior( { 'type': 'click_up', 'search_keys': search_keys, 'cbjs_action': ''' var server = TacticServerStub.get(); for (var i = 0; i < bvr.search_keys.length; i++) { var search_key = bvr.search_keys[i]; server.update(search_key, {'last_cleared':'NOW'}); spt.panel.refresh(bvr.src_el); } ''' } ) # types of subscriptions table_div = DivWdg() table_div.add_styles('overflow-y: auto; max-height: 500px; width: 100%') div.add(table_div) table = Table() table.add_style('width: 100%') table.add_border() table.add_color("background", "background3") table_div.add(table) ss = [] for subscription in subscriptions: table.add_row() td = table.add_cell() message_code = subscription.get_value("message_code") search = Search("sthpw/message") search.add_filter("code", message_code) message = search.get_sobject() # show the thumb if not message: if mode == "all": td = table.add_cell(FormatMessageWdg.get_preview_wdg(subscription)) td = table.add_cell() td.add("No Messages") continue size = 60 show_preview = my.kwargs.get('show_preview') if show_preview in ['',None]: show_preview = True msg_element = FormatMessageWdg(subscription=subscription, short_format='true',show_preview=show_preview) # this is optional msg_element.set_sobject(message) description = msg_element.get_buffer_display() #td = table.add_cell() history_icon = IconButtonWdg(title="Subscription History", icon=IconWdg.HISTORY) #td.add(icon) message_code = subscription.get_value("message_code") history_icon.add_behavior( { 'type': 'click_up', 'message_code': message_code, 'cbjs_action': ''' var class_name = 'tactic.ui.panel.FastTableLayoutWdg'; var message_code = bvr.message_code; var kwargs = { search_type: 'sthpw/message_log', show_shelf: false, expression: "@SOBJECT(sthpw/message_log['message_code','"+message_code+"'])", view: 'history' }; spt.tab.set_main_body_tab(); spt.tab.add_new("Message History", "Message History", class_name, kwargs); ''' } ) # description can take up 70% td = table.add_cell() td.add_style("width: %spx"%(SubscriptionBarWdg.WIDTH*0.7)) desc_div = DivWdg() td.add(desc_div) desc_div.add(description) desc_div.add_style("padding: 0px 20px") td = table.add_cell() #td.add(message.get_value("status")) #td = table.add_cell() timestamp = message.get_datetime_value("timestamp") if timestamp: timestamp_str = timestamp.strftime("%b %d, %Y - %H:%M") else: timestamp_str = "" show_timestamp = my.kwargs.get('show_timestamp') if show_timestamp in ['',None]: show_timestamp = True if show_timestamp in ["True","true",True]: td.add(timestamp_str) #td = table.add_cell() #td.add(subscription.get_value("last_cleared")) td = table.add_cell() show_message_history = my.kwargs.get('show_message_history') if show_message_history in ['',None]: show_message_history = True if show_message_history in ["True","true",True]: td.add(history_icon) td.add(HtmlElement.br(2)) td.add_style('width: 30px') icon = IconButtonWdg(title="Unsubscribe", icon=IconWdg.DELETE) icon.add_style('bottom: 14px') subscription_key = subscription.get_search_key() icon.add_behavior( { 'type': 'click_up', 'search_key': subscription_key, 'message_code': message_code, 'cbjs_action': ''' if (!confirm("Unsubscribe from [" + bvr.message_code + "]?")) { return; } var top = bvr.src_el.getParent(".spt_subscription_top"); var server = TacticServerStub.get(); server.delete_sobject(bvr.search_key); spt.panel.refresh(top); ''' } ) show_unsubscribe = my.kwargs.get('show_unsubscribe') if show_unsubscribe in ['',None]: show_unsubscribe = False if show_unsubscribe in ["True","true",True]: td.add(icon) ss.append(subscription) num_sobjects = len(ss) if not num_sobjects: return None summary_div.add("(%s changes)" % num_sobjects) #from tactic.ui.panel import FastTableLayoutWdg #table = FastTableLayoutWdg(search_type="sthpw/subscription",show_shelf=False) #div.add(table) #table.set_sobjects(ss) return div
def get_chat_wdg(my, key, interval=False): div = DivWdg() div.add_class("spt_chat_session_top") div.add_color("background", "background") title_wdg = DivWdg() div.add(title_wdg) title_wdg.add_color("background", "background3") title_wdg.add_style("padding: 5px") title_wdg.add_style("font-weight: bold") title_wdg.add_border() icon = IconButtonWdg(title="Remove Chat", icon=IconWdg.DELETE) icon.add_style("float: right") icon.add_style("margin-top: -5px") title_wdg.add(icon) icon.add_behavior( { 'type': 'click_up', 'key': key, 'cbjs_action': ''' var server = TacticServerStub.get(); var top = bvr.src_el.getParent(".spt_chat_session_top"); spt.behavior.destroy_element(top); ''' } ) current_user = Environment.get_user_name() logins = Search.eval("@SOBJECT(sthpw/subscription['message_code','%s'].sthpw/login)" % key) for login in logins: if login.get_value("login") == current_user: continue thumb = ThumbWdg() thumb.set_icon_size(45) thumb.set_sobject(login) thumb.add_style("float: left") thumb.add_style("margin: -5px 10px 0px -5px") title_wdg.add(thumb) title_wdg.add(login.get_value("display_name")) title_wdg.add("<br clear='all'/>") history_div = DivWdg() div.add(history_div) history_div.add_class("spt_chat_history") history_div.add_style("width: auto") history_div.add_style("height: auto") history_div.add_style("max-height: 400px") history_div.add_style("padding: 5px") history_div.add_class("spt_resizable") history_div.add_border() history_div.add_style("overflow-y: auto") #history_div.add_style("font-size: 0.9em") search = Search("sthpw/message_log") search.add_filter("message_code", key) search.add_order_by("timestamp") message_logs = search.get_sobjects() last_login = None; last_date = None; for message_log in message_logs: login = message_log.get("login") message = message_log.get("message") timestamp = message_log.get_datetime_value("timestamp") #timestamp = timestamp.strftime("%b %d, %Y - %H:%M") timestamp_str = timestamp.strftime("%H:%M") date_str = timestamp.strftime("%b %d, %Y") if login != last_login: table = Table() history_div.add(table) table.add_row() table.add_style("width: 100%") table.add_style("margin-top: 15px") login_sobj = Search.get_by_code("sthpw/login", login) thumb_div = DivWdg() td = table.add_cell() td.add_style("vertical-align: top") td.add_style("width: 75px") thumb_div = DivWdg() td.add(thumb_div) thumb_div.add_style("overflow: hidden") thumb = ThumbWdg() thumb_div.add(thumb) thumb.set_sobject(login_sobj) thumb.set_icon_size(60) display_name = login_sobj.get("display_name") td = table.add_cell() td.add_style("padding-top: 3px") name_div = DivWdg() td.add(name_div) name_div.add_style("color", "#214e75") name_div.add_style("font-size", "1.3em") name_div.add(display_name) msg = ""; msg += "<table style='margin-top: 5px; font-size: 1.0em; width: 100%'>"; if date_str != last_date: msg += "<tr><td colspan='2' style='text-align: right'><br/><b style='font-size: 1.0em'>"+date_str+"</b></td></tr>"; last_login = None msg += "<tr><td>" msg += message.replace("\n",'<br/>') msg += "</td><td style='vertical-align: top; text-align: right; margin-bottom: 5px; width: 75px; vertical-align: top; opacity: 0.7;'>"; msg += timestamp_str; msg += "</td></tr></table>"; td.add(msg) last_login = login last_date = date_str history_div.add_behavior( { 'type': 'load', 'cbjs_action': ''' bvr.src_el.scrollTop = bvr.src_el.scrollHeight; ''' } ) if message_logs: last_message = message_logs[-1].get("message") last_login = message_logs[-1].get("login") else: last_message = "" last_login = "" div.add_attr("spt_last_message", last_message) div.add_attr("spt_last_login", last_login) if interval: div.add_behavior( { 'type': 'load', 'key': key, 'cbjs_action': r''' var text_el = bvr.src_el.getElement(".spt_chat_text"); var history_el = bvr.src_el.getElement(".spt_chat_history"); var callback = function(message) { //history_el.setStyle("background", "red"); var login = message.login; var timestamp = message.timestamp; if (timestamp) { var parts = timestamp.split(" "); parts = parts[1].split("."); timestamp = parts[0]; } else { timestamp = ""; } var tmp = message.message || ""; var last_message = bvr.src_el.getAttribute("spt_last_message"); var last_login = bvr.src_el.getAttribute("spt_last_login"); if (tmp == last_message && login == last_login) { return; } bvr.src_el.setAttribute("spt_last_message", tmp); bvr.src_el.setAttribute("spt_last_login", login); var msg = ""; msg += "<table style='margin-top: 5px; font-size: 1.0em; width: 100%'><tr><td>"; if (login != last_login) { msg += "<b>"+login+"</b><br/>"; } msg += tmp.replace(/\n/g,'<br/>'); msg += "</td><td style='text-align: right; margin-bottom: 5px; width: 75px; vertical-align: top'>"; msg += timestamp; msg += "</td></tr></table>"; if (msg == history_el.last_msg) { return; } history_el.innerHTML = history_el.innerHTML + msg; // remember last message history_el.last_msg = msg; history_el.scrollTop = history_el.scrollHeight; } spt.message.set_interval(bvr.key, callback, 3000, bvr.src_el); ''' } ) text = TextAreaWdg("chat") div.add(text) text.add_class("spt_chat_text") text.add_style("width: 100%") text.add_style("padding: 5px") #text.add_style("margin-top: -1px") text.add_style("margin-top: 5px") text.add_behavior( { 'type': 'load', 'cbjs_action': ''' bvr.src_el.addEvent("keydown", function(e) { var keys = ['tab','keys(control+enter)', 'enter']; var key = e.key; var input = bvr.src_el if (keys.indexOf(key) > -1) e.stop(); if (key == 'tab') { } else if (key == 'enter') { if (e.control == false) { pass; } else { // TODO: check if it's multi-line first //... use ctrl-ENTER for new-line, regular ENTER (RETURN) accepts value //var tvals = parse_selected_text(input); //input.value = tvals[0] + "\\n" + tvals[1]; //spt.set_cursor_position( input, tvals[0].length + 1 ); } } } ) ''' } ) button = ActionButtonWdg(title="Send") div.add(button) button.add_style("float: right") button.add_style("margin: 5px") button.add_behavior( { 'type': 'click_up', 'key': key, 'cbjs_action': ''' var top = bvr.src_el.getParent(".spt_chat_session_top"); var text_el = top.getElement(".spt_chat_text"); var message = text_el.value; if (!message) { return; } var history_el = top.getElement(".spt_chat_history"); var category = "chat"; var server = TacticServerStub.get(); var key = bvr.key; var last_message = server.log_message(key, message, {category:category, status:"in_progress"}); text_el.value = ""; ''' } ) div.add("<br clear='all'/>") return div
def get_display(my): top = my.top; my.set_as_panel(top) top.add_class("spt_chat_top") inner = DivWdg() top.add(inner) inner.add_behavior( { 'type': 'load', 'cbjs_action': MessageWdg.get_onload_js() } ) search = Search("sthpw/subscription") search.add_filter("category", "chat") search.add_user_filter() chats = search.get_sobjects() keys = [x.get_value("message_code") for x in chats] """ chat_list_div = DivWdg() inner.add(chat_list_div) for i, chat in enumerate(chats): chat_div = DivWdg() chat_list_div.add(chat_div) chat_div.add_style("padding: 5px") chat_div.add_class("hand") # find all the users with the same chat key = chat.get_value("message_code") #chat_div.add(key) chat_div.add("#%s: " % i) search = Search("sthpw/subscription") search.add_filter("message_code", key) subscriptions = search.get_sobjects() users = [x.get_value("login") for x in subscriptions] chat_div.add(", ".join(users)) chat_div.add_behavior( { 'type': 'click_up', 'key': key, 'cbjs_action': ''' var class_name = 'tactic.ui.app.ChatSessionWdg'; var kwargs = { 'key': bvr.key, } spt.panel.load_popup("Chat: " + bvr.key, class_name, kwargs); ''' } ) chat_div.add_behavior( { 'type': 'mouseover', 'cbjs_action': ''' bvr.src_el.setStyle("color", "#214e75"); ''' } ) chat_div.add_behavior( { 'type': 'mouseout', 'cbjs_action': ''' bvr.src_el.setStyle("color", ""); ''' } ) """ #keys = my.kwargs.get("keys") #if not keys: # return inner.add( my.get_add_chat_wdg() ) inner.add("<br/>") from tactic.ui.container import TabWdg tab = TabWdg( show_add=False, show_remove=False ) inner.add(tab) for key in keys: search = Search("sthpw/subscription") search.add_filter("message_code", key) subscriptions = search.get_sobjects() users = [x.get_value("login") for x in subscriptions] users = ", ".join(users) session_div = DivWdg() session_div.set_name(users) session_div.add_style("width: 100%") #inner.add(session_div) tab.add(session_div) session = ChatSessionWdg(key=key) session_div.add(session) inner.add("<br clear='all'/>") if my.kwargs.get("is_refresh") == 'true': return inner else: return top
def get_display(my): top = my.top top.add_color("background", "background") top.add_class("spt_pipelines_top") my.set_as_panel(top) inner = DivWdg() top.add(inner) search_type = my.kwargs.get("search_type") pipeline_code = my.kwargs.get("pipeline_code") if search_type: search = Search("sthpw/pipeline") search.add_filter("search_type", search_type) pipelines = search.get_sobjects() else: pipeline = Pipeline.get_by_code(pipeline_code) if pipeline: pipelines = [pipeline] else: pipelines = [] if not pipelines: div = DivWdg() inner.add(div) inner.add_style("padding: 50px") div.add_border() div.add_color("color", "color3") div.add_color("background", "background3") div.add_style("width: 400px") div.add_style("height: 100px") div.add_style("padding: 30px") icon = IconWdg("WARNING", IconWdg.WARNING) div.add(icon) div.add( "<b>This Searchable Type does not have pipelines defined.</b>") div.add("<br/>" * 2) div.add( "<b style='padding-left: 35px'>Click Create to add one...</b>") div.add("<br/>" * 2) button_div = DivWdg() div.add(button_div) button = ActionButtonWdg(title="Create", tip="Create pipeline") button_div.add(button) button.add_style("margin: auto") button.add_behavior({ 'type': 'click_up', 'search_type': search_type, 'cbjs_action': ''' var server = TacticServerStub.get(); var cmd = 'tactic.ui.startup.PipelineCreateCbk'; var kwargs = { search_type: bvr.search_type } server.execute_cmd(cmd, kwargs) var top = bvr.src_el.getParent(".spt_pipelines_top"); spt.panel.refresh(top); ''' }) return top # get the defalt task statuses task_pipeline = Pipeline.get_by_code("task") if task_pipeline: statuses = task_pipeline.get_process_names() else: statuses = ['Pending', 'In Progress', 'Complete'] statuses_str = ",".join(statuses) pipelines_div = DivWdg() inner.add(pipelines_div) pipelines_div.add_style("font-size: 12px") pipelines_div.add_style("padding: 10px") buttons_div = DivWdg() pipelines_div.add(buttons_div) #button = SingleButtonWdg( title="Save Pipelines", icon=IconWdg.SAVE ) button = ActionButtonWdg(title="Save") buttons_div.add(button) button.add_behavior({ 'type': 'click_up', 'default_statuses': statuses_str, 'cbjs_action': ''' spt.app_busy.show("Saving Pipeline...") setTimeout(function() { try { var top = bvr.src_el.getParent(".spt_pipelines_top"); // get all the pipeline divs var pipeline_els = top.getElements(".spt_pipeline_top"); var data = {}; for ( var i = 0; i < pipeline_els.length; i++) { var pipeline_code = pipeline_els[i].getAttribute("spt_pipeline_code"); var values = spt.api.Utility.get_input_values(pipeline_els[i]); data[pipeline_code] = values; } var class_name = 'tactic.ui.startup.PipelineEditCbk'; var kwargs = { data: data } var server = TacticServerStub.get(); server.execute_cmd(class_name, kwargs); } catch(e) { spt.alert(spt.exception.handler(e)); } spt.app_busy.hide(); } , 100); ''' }) buttons_div.add("<br clear='all'/>") buttons_div.add_style("margin-bottom: 5px") for pipeline in pipelines: pipeline_div = DivWdg() pipelines_div.add(pipeline_div) pipeline_div.add_class("spt_pipeline_top") code = pipeline.get_code() pipeline_div.add_attr("spt_pipeline_code", code) title = DivWdg() pipeline_div.add(title) title.add("Pipeline: ") title.add(code) title.add_style("padding: 8px 10px") title.add_color("background", "background3") title.add_style("font-weight: bold") title.add_style("margin: -10 -10 5 -10") header_wdg = DivWdg() pipeline_div.add(header_wdg) header_wdg.add_color("background", "background", -5) headers = ['Process', 'Description', 'Task Status'] widths = ['100px', '180px', '210px'] for header, width in zip(headers, widths): th = DivWdg() header_wdg.add(th) th.add("<b>%s</b>" % header) th.add_style("float: left") th.add_style("width: %s" % width) th.add_style("padding: 8px 3px") header_wdg.add("<br clear='all'/>") # get all of the process sobjects from this pipeline pipeline_code = pipeline.get_code() search = Search("config/process") search.add_filter("pipeline_code", pipeline.get_code()) process_sobjs = search.get_sobjects() process_sobj_dict = {} for process_sobj in process_sobjs: process = process_sobj.get_value("process") process_sobj_dict[process] = process_sobj from tactic.ui.container import DynamicListWdg dyn_list = DynamicListWdg() pipeline_div.add(dyn_list) pipeline_div.add_style("width: 725px") processes = pipeline.get_process_names() if not processes: processes.append("") processes.append("") processes.append("") processes.insert(0, "") for i, process in enumerate(processes): if process == '': process_name = '' description = '' else: process_sobj = process_sobj_dict.get(process) if process_sobj: process_name = process_sobj.get_value("process") description = process_sobj.get_value("description") else: if isinstance(process, basestring): process_name = process else: process_name = process.get_name() deccription = '' # get the task pipeline for this process if process_name: process = pipeline.get_process(process_name) task_pipeline_code = process.get_task_pipeline() if task_pipeline_code != "task": task_pipeline = Search.get_by_code( "sthpw/pipeline", task_pipeline_code) else: task_pipeline = None else: task_pipeline_code = "task" task_pipeline = None process_div = DivWdg() process_div.add_style("float: left") process_div.add_class("spt_process_top") if i == 0: dyn_list.add_template(process_div) else: dyn_list.add_item(process_div) #process_div.add_style("padding-left: 10px") #process_div.add_style("margin: 5px") table = Table() process_div.add(table) table.add_row() text = TextInputWdg(name="process") table.add_cell(text) text.add_style("width: 95px") text.add_style("margin: 5px") text.set_value(process_name) text.add_class("spt_process") # the template has a border if i == 0: text.add_style("border: solid 1px #AAA") text = TextInputWdg(name="description") table.add_cell(text) text.add_style("width: 175px") text.add_style("margin: 5px") text.set_value(description) # the template has a border if i == 0: text.add_style("border: solid 1px #AAA") text = TextInputWdg(name="task_status") table.add_cell(text) text.add_style("width: 325px") text.add_style("margin: 5px") #text.set_value(statuses_str) if task_pipeline: statuses = task_pipeline.get_process_names() text.set_value(",".join(statuses)) else: text.set_value("(default)") #text.add_style("opacity: 0.5") text.add_style("border-style: none") text.add_behavior({ 'type': 'click_up', 'statuses': statuses_str, 'cbjs_action': ''' if (bvr.src_el.value == '(default)') { bvr.src_el.value = bvr.statuses; } ''' }) table.add_cell(" " * 2) button = IconButtonWdg(tip="Trigger", icon=IconWdg.ARROW_OUT) table.add_cell(button) button.add_behavior({ 'type': 'click_up', 'search_type': search_type, 'pipeline_code': pipeline_code, 'cbjs_action': ''' var top = bvr.src_el.getParent(".spt_process_top"); var process_el = top.getElement(".spt_process"); var process = process_el.value; if (process == "") { alert("Process value is empty"); return; } var class_name = 'tactic.ui.tools.TriggerToolWdg'; var kwargs = { mode: "pipeline", process: process, pipeline_code: bvr.pipeline_code }; spt.panel.load_popup("Trigger", class_name, kwargs); ''' }) """ button = IconButtonWdg(tip="Edit", icon=IconWdg.EDIT) table.add_cell(button) button.add_behavior( { 'type': 'click_up', 'search_type': search_type, 'pipeline_code': pipeline_code, 'cbjs_action': ''' var top = bvr.src_el.getParent(".spt_process_top"); var process_el = top.getElement(".spt_process"); var process = process_el.value; if (process == "") { alert("Process value is empty"); return; } var class_name = 'tactic.ui.panel.EditWdg'; var kwargs = { expression: "@SOBJECT(config/process['process','"+process+"'])" } spt.panel.load_popup("Trigger", class_name, kwargs); ''' } ) """ table.add_cell(" " * 3) pipeline_div.add("<br clear='all'/>") pipeline_div.add("<br clear='all'/>") if my.kwargs.get("is_refresh"): return inner else: return top
def get_display(my): category = "FreeformWdg" search_type = my.get_value("search_type") if not search_type: search_type = "sthpw/login" view = my.get_value("view") if not view: view = 'freeform' search = Search("config/widget_config") search.add_filter("search_type", search_type) search.add_filter("view", view) config_sobj = search.get_sobject() if config_sobj: config_xml = config_sobj.get_value("config") else: config_xml = "<config/>" top = my.top my.set_as_panel(top) top.add_class("spt_freeform_top") inner = DivWdg() top.add(inner) table = ResizableTableWdg() table.add_color("background", "background") inner.add(table) table.add_row() table.set_max_width() td = table.add_cell() td.add_attr("colspan", "5") td.add_color("background", "background3") td.add_color("color", "color") td.add_style("padding", "10px") td.add("Search Type: ") select = SelectWdg("search_type") project = Project.get() search_types = project.get_search_types() values = [x.get_base_key() for x in search_types] labels = [ "%s (%s)" % (x.get_title(), x.get_base_key()) for x in search_types ] select.set_option("values", values) select.set_option("labels", labels) if search_type: select.set_value(search_type) td.add(select) td.add(" " * 10) td.add("View: ") text = TextWdg("view") td.add(text) if view: text.set_value(view) button = ActionButtonWdg(title="Load") button.add_style("float: left") td.add(button) button.add_behavior({ 'type': 'click_up', 'cbjs_action': ''' spt.app_busy.show("Loading View"); var top = bvr.src_el.getParent(".spt_freeform_top"); spt.panel.refresh(top); spt.app_busy.hide(); ''' }) table.add_row() left = table.add_cell() left.add_style("vertical-align: top") left.add_border() left.add_color("color", "color") left.add_color("background", "background") left.add_style("min-width: 150px") left_div = DivWdg() left.add(left_div) left_div.add_style("min-height: 300px") left_div.add_style("min-width: 150px") left_div.add_style("width: 150px") title = DivWdg() left_div.add(title) title.add_style("font-weight: bold") title.add_style("font-size: 14px") title.add_style("width: 100%") title.add("Elements") title.add_gradient("background", "background", -5) title.add_style("padding: 10px 5px 5px 5px") title.add_style("height: 25px") title.add_style("margin-bottom: 10px") left.add_behavior({ 'type': 'smart_click_up', 'bvr_match_class': 'SPT_ELEMENT_CLICK', 'cbjs_action': r''' var top = bvr.src_el.getParent(".spt_freeform_top"); var template_top = top.getElement(".spt_freeform_template_top"); var canvas_top = top.getElement(".spt_freeform_canvas_top"); var canvas = canvas_top.getElement(".spt_freeform_canvas"); var element_name = bvr.src_el.getAttribute("spt_element_name"); var template_els = template_top.getElements(".spt_element"); var els = canvas.getElements(".spt_element"); // get the highest number var number = 0; for ( var i = 0; i < els.length; i++) { var el = els[i]; var name = el.getAttribute("spt_element_name"); var num = name.match(/(\d+)/); if (!num) continue; num = parseInt(num); if (num > number) { number = num; } } number = number + 1; for ( var i = 0; i < template_els.length; i++) { var el = template_els[i]; if (el.getAttribute("spt_element_name") == element_name) { var clone = spt.behavior.clone(el); canvas.appendChild(clone); clone.setStyle("top", "30px"); clone.setStyle("left", "30px"); clone.setStyle("position", "absolute"); var new_name = element_name + number; clone.setAttribute("spt_element_name", new_name) clone.attrs = {}; var number = Math.floor(Math.random()*10001) clone.setAttribute("spt_element_id", "element"+number); spt.freeform.select(clone); break; } } ''' }) values = [ 'Label', 'Box', 'Text', 'TextArea', 'Button', 'Preview', 'Image', 'HTML', 'Table', 'Border', 'Custom Layout' ] names = [ 'label', 'box', 'text', 'textarea', 'button', 'preview', 'image', 'html', 'table', 'border', 'custom' ] icons = [IconWdg.VIEW] for name, value in zip(names, values): element_div = DivWdg() left_div.add(element_div) element_div.add_style("padding: 3px") element_div.add_class("SPT_DTS") element_div.add_class("hand") icon = IconWdg(name, IconWdg.VIEW) element_div.add(icon) element_div.add(value) element_div.add_class("SPT_ELEMENT_CLICK") element_div.add_attr("spt_element_name", name) element_div.add_style("padding-left: 10px") hover = element_div.get_color("background", -10) element_div.add_behavior({ 'type': 'hover', 'hover': hover, 'cbjs_action_over': '''bvr.src_el.setStyle("background", bvr.hover)''', 'cbjs_action_out': '''bvr.src_el.setStyle("background", "")''' }) element_div.add_class("hand") element_div.add_behavior({ 'type': 'drag', "drag_el": '@', "cb_set_prefix": 'spt.freeform.create_element_drag' }) """ button = ActionButtonWdg(title="Save") left_div.add(button) button.add_behavior( { 'type': 'click_up', 'cbjs_action': ''' var top = bvr.src_el.getParent(".spt_freeform_top"); var canvas_top = top.getElement(".spt_freeform_canvas_top"); var canvas = canvas_top.getElement(".spt_freeform_canvas"); spt.freeform.init(canvas); var xml = spt.freeform.export(); var search_type = canvas.getAttribute("spt_search_type"); var view = canvas.getAttribute("spt_view"); if (!search_type || !view) { alert("Cannot find search type or view"); return; } var server = TacticServerStub.get(); var sobject = server.get_unique_sobject("config/widget_config", {search_type: search_type, view: view} ); server.update(sobject, {config: xml} ); ''' } ) """ from tactic.ui.container import DialogWdg dialog = DialogWdg(display=False, show_pointer=False) dialog.add_title("Properties") my.dialog_id = dialog.get_id() left.add(dialog) attr_div = my.get_attr_wdg() dialog.add(attr_div) template_div = DivWdg() left.add(template_div) template_div.add_class("spt_freeform_template_top") template_div.add_style("display: none") template_config_xml = my.get_template_config_xml() freeform_layout = FreeFormCanvasWdg(search_type=search_type, view="freeform", config_xml=template_config_xml, dialog_id=my.dialog_id) template_div.add(freeform_layout) # handle the canvas canvas = table.add_cell(resize=False) canvas.add(my.get_action_wdg()) canvas.add_style("overflow: hidden") canvas.add_style("vertical-align: top") canvas.add_color("background", "background") canvas.add_color("color", "color") canvas_div = DivWdg() canvas_div.add_style("margin: 20px") canvas_div.add_style("width: 90%") canvas_div.add_style("min-width: 300px") canvas_div.add_style("padding: 10px") canvas_div.add_style("height: 100%") canvas_div.add_class("spt_freeform_canvas_top") canvas.add(canvas_div) freeform_layout = FreeFormCanvasWdg(search_type=search_type, view=view, config_xml=config_xml, dialog_id=my.dialog_id) canvas_div.add(freeform_layout) table.add_resize_row() if my.kwargs.get("is_refresh") in [True, "true"]: return inner else: return top
def get_prequal_eval_lines_table(prequal_eval_sobject): prequal_eval_lines_search = Search('twog/prequal_evaluation_line') prequal_eval_lines_search.add_filter('prequal_evaluation_code', prequal_eval_sobject.get_code()) prequal_eval_lines = prequal_eval_lines_search.get_sobjects() # If no prequal eval lines exist for this report, return None so that the PDF won't display a table if not prequal_eval_lines: return None style_sheet = getSampleStyleSheet() style_sheet.font_size = 10 prequal_eval_lines_table_data = [[ 'Timecode', 'F', 'Description', 'Code', 'Scale', 'Sector/Ch', 'In Source' ]] lines_with_values = [] lines_without_values = [] for line in prequal_eval_lines: if line.get_value('timecode'): lines_with_values.append(line) else: lines_without_values.append(line) prequal_eval_lines = sorted(lines_with_values, key=lambda x: x.get_value('timecode')) prequal_eval_lines.extend(lines_without_values) for line in prequal_eval_lines: timecode = line.get('timecode') field = line.get('field') prequal_line_description = line.get('prequal_line_description') type_code = line.get('type_code') scale = line.get('scale') sector_or_channel = line.get('sector_or_channel') in_source = line.get('in_source') if any([ timecode, field, prequal_line_description, type_code, scale, sector_or_channel, in_source ]): description_paragraph_style = ParagraphStyle( prequal_line_description) description_paragraph_style.fontSize = 8 description_paragraph = Paragraph(line.get('description'), description_paragraph_style) line_data = [ timecode, field, description_paragraph, type_code, scale, sector_or_channel, in_source ] prequal_eval_lines_table_data.append(line_data) prequal_eval_lines_table = Table(prequal_eval_lines_table_data, hAlign='LEFT', spaceBefore=5, spaceAfter=5, colWidths=[(.7 * inch), (.19 * inch), (inch * 2.6), (.4 * inch), (.82 * inch), (.19 * inch), (.75 * inch), (.3 * inch), (.55 * inch), (.55 * inch)]) prequal_eval_lines_table.setStyle([ ('BOX', (0, 0), (-1, -1), 0.2, colors.black), ('INNERGRID', (0, 0), (-1, -1), 0.2, colors.black), ('FONTSIZE', (0, 0), (-1, -1), 8), ('LEFTPADDING', (0, 0), (-1, -1), 1), ('RIGHTPADDING', (0, 0), (-1, -1), 1) ]) return prequal_eval_lines_table
if not is_forced: print "-f option must be used in this situation. " sys.exit(0) pass elif answer == 'n': sys.exit(0) else: print "Only y or n is accepted. Exiting..." sys.exit(0) # check if some projects are already in newer version Batch(site=site) search = Search("sthpw/project") if project_code: search.add_filter("code", project_code) else: search.add_enum_order_by( "type", ['sthpw', 'prod', 'flash', 'game', 'design', 'simple', 'unittest']) projects = search.get_sobjects() project_dict = {} for project in projects: last_version = project.get_value('last_version_update', no_exception=True) if last_version > version: project_dict[project.get_code()] = last_version if project_dict: data = [] for key, value in project_dict.items():
def get_widget_from_hash(cls, hash, return_none=False, force_no_index=False, kwargs={}): from pyasm.web import DivWdg if hash.startswith("//"): use_top = False hash = hash[1:] else: use_top = True import re p = re.compile("^/(\w+)") m = p.search(hash) if not m: if return_none: return None print "Cannot parse hash[%s]" % hash return DivWdg("Cannot parse hash [%s]" % hash) key = m.groups()[0] if key != 'login': security = Environment.get_security() login = security.get_user_name() # guest user should never be able to see admin site if login == "guest" and key == 'admin': #from pyasm.widget import Error403Wdg #return Error403Wdg().get_buffer_display() from pyasm.widget import WebLoginWdg # HACK: if the guest access is full, the the outer form # is not defined ... force it in here. This is because the # top used it TopWdg and not TitleTopWdg div = DivWdg() div.add("<form id='form' name='form' method='post' enctype='multipart/form-data'>\n") web_login_wdg = WebLoginWdg().get_buffer_display() div.add(web_login_wdg) div.add("</form>\n") return div sobject = cls._get_predefined_url(key, hash) # look up the url if not sobject: search = Search("config/url") search.add_filter("url", "/%s/%%"%key, "like") search.add_filter("url", "/%s"%key) search.add_where("or") sobject = search.get_sobject() if not sobject: if return_none: return None return DivWdg("No Widget found for hash [%s]" % hash) config = sobject.get_value("widget") config = config.replace('&','&') url = sobject.get_value("url") url = url.strip() # update the config value with expressions options = Common.extract_dict(hash, url) for name, value in options.items(): config = config.replace("{%s}" % name, value) xml = Xml() xml.read_string(config) use_index, use_admin, use_sidebar = cls._get_flags(xml, sobject, force_no_index, kwargs) if use_admin: # use admin from tactic.ui.app import PageNavContainerWdg top = PageNavContainerWdg( hash=hash, use_sidebar=use_sidebar ) return top.get_buffer_display() elif use_index: # check if there is an index search = Search("config/url") search.add_filter("url", "/index") index = search.get_sobject() # just use admin if no index page is found if not index: from tactic.ui.app import PageNavContainerWdg top = PageNavContainerWdg( hash=hash, use_sidebar=use_sidebar ) return top.get_buffer_display() config = index.get_value("widget") xml = Xml() xml.read_string(config) node = xml.get_node("element/display") options.update(xml.get_node_values_of_children(node)) class_name = xml.get_value("element/display/@class") if class_name: options['class_name'] = class_name # this passes the hash value to the index widget # which must handle it accordingly options['hash'] = hash top = cls.build_widget(options) return top.get_buffer_display() # process the options and then build the widget from the xml options = Common.extract_dict(hash, url) for name, value in kwargs.items(): options[name] = value node = xml.get_node("element/display") options.update(xml.get_node_values_of_children(node)) class_name = xml.get_value("element/display/@class") if class_name: options['class_name'] = class_name widget = cls.build_widget(options) name = hash.lstrip("/") name = name.replace("/", " ") widget.set_name(name) return widget
def execute(my): transaction_code = my.kwargs.get("transaction_code") job = my.kwargs.get("job") job_code = '' if job: job_code = job.get_code() print "Executing sync job [%s] ... " % job_code if not transaction_code: raise TacticException("WARNING: No transaction_code provided") server_code = my.kwargs.get("server") if not server_code: raise TacticException("WARNING: No server defined") server = Search.get_by_code("sthpw/sync_server", server_code) if not server: raise TacticException("ERROR: No server with code [%s] defined" % server_code) host = server.get_value("host") # file mode is usually determined by the server file_mode = my.kwargs.get("file_mode") if not file_mode: file_mode = server.get_value("file_mode", no_exception=True) if not file_mode: file_mode = 'upload' # sync mode is usually determined by the server sync_mode = my.kwargs.get("sync_mode") if not sync_mode: sync_mode = server.get_value("sync_mode", no_exception=True) if not sync_mode or sync_mode == 'default': # defautl is xmlrpc sync_mode = "xmlrpc" project_code = my.kwargs.get("project_code") #project_code = 'admin' if not project_code: raise TacticException("WARNING: Project code is not supplied") # get info for remote server definition ticket = server.get_value("ticket") if not ticket: raise TacticException( "ERROR: No authorization ticket specified for server [%s]" % server_code) user = None password = None # grab data passed into it search = Search("sthpw/transaction_log") search.add_filter("code", transaction_code) log = search.get_sobject() if not log: print "WARNING: No transaction_log [%s] exists" % transaction_code return # provide an opportunity to filter out the transaction log # If a server is a complete copy, then no filter is necessary message, transaction_xml = my.filter_transaction(log, server) if not transaction_xml.get_nodes("transaction/*"): print "No actions in transaction passed security ... skipping sync to [%s]" % server.get_code( ) job = my.kwargs.get("job") job.set_value("error_log", message) job.commit() return import zlib, binascii #transaction_data = Common.process_unicode_string(transaction_xml) transaction_data = transaction_xml.to_string() if isinstance(transaction_data, unicode): transaction_data = transaction_data.encode('utf-8') length_before = len(transaction_data) compressed = zlib.compress(transaction_data) ztransaction_data = binascii.hexlify(compressed) ztransaction_data = "zlib:%s" % ztransaction_data length_after = len(ztransaction_data) print "transaction log recompress: ", "%s%%" % int( float(length_after) / float(length_before) * 100), "[%s] to [%s]" % (length_before, length_after) # reset the transaction log sobject with the new xml. This # should be harmless because it is never commited log.set_value("transaction", ztransaction_data) # NOTE: not really a command. Just a set of actions cmd = TransactionFilesCmd(transaction_xml=transaction_xml) paths = cmd.execute() from pyasm.search import TableDataDumper # drop the transaction into a folder if sync_mode == 'file': base_dir = server.get_value("base_dir", no_exception=True) if not base_dir: base_dir = Config.get_value("checkin", "win32_dropbox_dir") if not base_dir: raise Exception("Must define a base_dir for sync_mode=file") ticket = server.get_value("ticket") my.handle_file_mode(base_dir, transaction_code, paths, log, transaction_xml, ticket) return # xmlrpc mode from tactic_client_lib import TacticServerStub remote_server = TacticServerStub(protocol='xmlrpc', server=host, project=project_code, user=user, password=password, ticket=ticket) # if the mode is undo, then execute an undo if sync_mode == 'undo': remote_server.undo(transaction_id=log.get_code(), is_sync=True) else: # upload all of the files try: if file_mode == 'upload': for path in paths: if os.path.isdir(path): print "upload dir: ", path remote_server.upload_directory(path) else: print "upload file: ", path remote_server.upload_file(path) #print "ping: ", remote_server.ping() remote_server.execute_transaction(log.get_data(), file_mode=file_mode) except Exception, e: print "Error sending remote command [%s]" % str(e) job = my.kwargs.get("job") job.set_value("error_log", str(e)) #job.set_value("state", "error") job.commit() # print the stacktrace import traceback tb = sys.exc_info()[2] stacktrace = traceback.format_tb(tb) stacktrace_str = "".join(stacktrace) print "-" * 50 print stacktrace_str print "Error: ", str(e) print "-" * 50 raise
def execute(self): project_code = self.kwargs.get('project_code') project_title = self.kwargs.get('project_title') project_type = self.kwargs.get('project_type') project_description = self.kwargs.get("description") if not project_type: project_type = "simple" is_template = self.kwargs.get('is_template') project_theme = self.kwargs.get('project_theme') use_default_side_bar = self.kwargs.get('use_default_side_bar') if use_default_side_bar in [False, 'false']: use_default_side_bar = False else: use_default_side_bar = True assert project_code assert project_type if project_type: # check to see if it exists search = Search("sthpw/project_type") search.add_filter("code", project_type) project_type_sobj = search.get_sobject() if not project_type_sobj: # just create a default one in this case if it is named # after the project code if not is_template and project_type == project_code: project_type = 'default' # create a new project type search = Search("sthpw/project_type") search.add_filter("code", project_type) project_type_sobj = search.get_sobject() if not project_type_sobj: project_type_sobj = SearchType.create("sthpw/project_type") project_type_sobj.set_value("code", project_type) project_type_sobj.set_value("type", "simple") project_type_sobj.commit() # set the current project to Admin Project.set_project("admin") # create a new project sobject project = SearchType.create("sthpw/project") project.set_value("code", project_code) project.set_value("title", project_title) project.set_value("type", project_type) if project_description: project.set_value("description", project_description) # set the update of the database to current (this is obsolete) #project.set_value("last_db_update", "now()") project.set_value("last_version_update", "2.5.0.v01") if is_template in ['true', True, 'True']: project.set_value("is_template", True) else: project.set_value("is_template", False) if project_type != "default": category = Common.get_display_title(project_type) project.set_value("category", category) project.commit() # if there is an image, check it in upload_path = self.kwargs.get("project_image_path") if upload_path: if not os.path.exists(upload_path): raise TacticException( "Cannot find upload image for project [%s]" % upload_path) file_type = 'main' file_paths = [upload_path] file_types = [file_type] source_paths = [upload_path] from pyasm.biz import IconCreator if os.path.isfile(upload_path): icon_creator = IconCreator(upload_path) icon_creator.execute() web_path = icon_creator.get_web_path() icon_path = icon_creator.get_icon_path() if web_path: file_paths = [upload_path, web_path, icon_path] file_types = [file_type, 'web', 'icon'] from pyasm.checkin import FileCheckin checkin = FileCheckin(project, context='icon', file_paths=file_paths, file_types=file_types) checkin.execute() # find project's base_type base_type = project.get_base_type() if not base_type and project_type == 'unittest': base_type = 'unittest' elif not base_type: base_type = 'simple' # get the database for this project db_resource = project.get_project_db_resource() database = db_resource.get_database_impl() #database = DatabaseImpl.get() database_type = database.get_database_type() if database_type == 'Oracle': raise TacticException( "Creation of project is not supported. Please create manually") # creating project database print "Creating database '%s' ..." % project_code try: # create the datbase database.create_database(db_resource) except Exception as e: print str(e) print "WARNING: Error creating database [%s]" % project_code # import the appropriate schema with config first database.import_schema(db_resource, base_type) self.create_schema(project_code) # before we upgrade, we have to commit the transaction # This is because upgrade actually run as separate processes # so if not commit has been made, the tables from importing the # schema will not have existed yet DbContainer.commit_thread_sql() self.upgrade() # import the appropriate data database.import_default_data(db_resource, base_type) # import default links if use_default_side_bar: self.import_default_side_bar() # create specified stypes self.create_search_types() # create theme if project_theme: self.create_theme(project_theme) # set as main project is_main_project = self.kwargs.get("is_main_project") if is_main_project in [True, 'true', 'on']: Config.set_value("install", "default_project", project_code) Config.save_config() Config.reload_config() # initiate the DbContainer DbContainer.get('sthpw') self.info['result'] = "Finished creating project [%s]." % project_code print "Done."
def create_theme(self, theme): # get a built-in plugin plugin_base_dir = Environment.get_plugin_dir() zip_path = "%s/%s.zip" % (plugin_base_dir, theme) manifest_path = "%s/%s/manifest.xml" % (plugin_base_dir, theme) plugin_base_dir2 = Environment.get_builtin_plugin_dir() zip_path2 = "%s/%s.zip" % (plugin_base_dir2, theme) manifest_path2 = "%s/%s/manifest.xml" % (plugin_base_dir2, theme) # install the theme from tactic.command import PluginInstaller if os.path.exists(manifest_path): plugin_dir = "%s/%s" % (plugin_base_dir, theme) installer = PluginInstaller(plugin_dir=plugin_dir, register=True) installer.execute() is_builtin = False elif os.path.exists(zip_path): installer = PluginInstaller(zip_path=zip_path, register=True) installer.execute() is_builtin = False elif os.path.exists(manifest_path2): plugin_dir = "%s/%s" % (plugin_base_dir2, theme) installer = PluginInstaller(plugin_dir=plugin_dir, register=True) installer.execute() is_builtin = True elif os.path.exists(zip_path2): installer = PluginInstaller(zip_path=zip_path2, register=True) installer.execute() is_builtin = True else: raise Exception("Installation error: cannot find %s theme" % theme) from pyasm.biz import PluginUtil if is_builtin: plugin_util = PluginUtil(base_dir=plugin_base_dir2) else: plugin_util = PluginUtil() data = plugin_util.get_plugin_data(theme) # if the theme does not have the url defined (which it likely # shouldn't, but just in case ... search = Search("config/url") search.add_filter("url", "/index") url = search.get_sobject() if not url: index_view = data.get("index_view") if not index_view: # don't use the folder in the theme base = os.path.basename(theme) index_view = "%s/index" % base # set this as the default index search = SearchType.create("config/url") search.set_value("url", "/index") search.set_value( "widget", ''' <element name='index'> <display class='tactic.ui.panel.CustomLayoutWdg'> <view>%s</view> </display> </element> ''' % index_view) search.set_value("description", "Index Page") search.commit()
def execute(my): input = my.get_input() search_type = input.get('search_type') if search_type != 'sthpw/transaction_log': print "ERROR: this trigger can only be executed for transaction_logs" return project = Project.get() # Block admin project from syncing # NOTE: maybe need an option to enable this? if project.get_code() == 'admin': return log = input.get('sobject') transaction_code = log.get_value("code") # if this is a remote transaction, then do not create a job for it local_prefix = Config.get_value("install", "server") search = Search("sthpw/sync_server") search.add_filter("state", "online") servers = search.get_sobjects() #print "servers: ", len(servers) # These are usually determined by the server entry #sync_mode = input.get('mode') #if not sync_mode or sync_mode == 'default': # sync_mode = 'xmlrpc' ## This will transaction into a "file" folder #sync_mode = "file" #file_mode = 'delayed' #file_mode = 'upload' # get some user info env = Environment.get() #user = env.get_user_name() #ticket = env.get_ticket() project_code = Project.get_project_code() from pyasm.security import AccessManager access_manager = AccessManager() for server in servers: # check security #if not my.check_security(server): # print "Transaction denied due to security restrictions" # continue server_code = server.get_code() # don't publish a transaction back to the original server if log.get_value("server_code") == server_code: continue # check project security rules = server.get_value("access_rules") if not rules: rules = "<rules/>" access_manager.add_xml_rules(rules) namespace = log.get_value("namespace") key1 = {'code': namespace} key2 = {'code': '*'} keys = [key1, key2] if not access_manager.check_access( "project", keys, "allow", default="deny"): continue from tactic.ui.sync import SyncFilter sync_filter = SyncFilter(rules=rules, transaction=log) sync_filter.execute() filtered_xml = sync_filter.get_filtered_xml() message = sync_filter.get_message() # create a new job entry job = SearchType.create("sthpw/sync_job") job.set_value("state", "pending") job.set_value("server_code", server_code) job.set_value("transaction_code", transaction_code) job.set_user() host = server.get_value("host") job.set_value("command", "tactic.command.TransactionQueueCmd") kwargs = { 'server': server.get_value("code"), 'transaction_code': transaction_code, 'project_code': project_code, #'file_mode': file_mode, #'sync_mode': sync_mode } job.set_json_value("data", kwargs) job.commit()
def get_display(my): my.search_type = my.kwargs.get("search_type") search = Search(my.search_type) search.add_filter("_is_collection", True) collections = search.get_sobjects() collections_div = DivWdg() is_refresh = my.kwargs.get("is_refresh") if is_refresh: div = Widget() else: div = DivWdg() my.set_as_panel(div) div.add_class("spt_collection_left_side") div.add(collections_div) collections_div.add_class("spt_collection_list") collections_div.add_style("margin: 5px 0px 5px -5px") from tactic.ui.panel import ThumbWdg2 parts = my.search_type.split("/") collection_type = "%s/%s_in_%s" % (parts[0], parts[1], parts[1]) collections_div.add_relay_behavior({ 'type': 'mouseup', 'search_type': my.search_type, 'collection_type': collection_type, 'bvr_match_class': 'spt_collection_item', 'cbjs_action': ''' var top = bvr.src_el.getParent(".spt_collection_top"); var content = top.getElement(".spt_collection_content"); var list = bvr.src_el.getParent(".spt_collection_list"); var items = list.getElements(".spt_collection_item"); for (var i = 0; i < items.length; i++) { items[i].setStyle("background", ""); items[i].setStyle("box-shadow", ""); } bvr.src_el.setStyle("background", "#EEE"); var collection_key = bvr.src_el.getAttribute("spt_collection_key"); var collection_code = bvr.src_el.getAttribute("spt_collection_code"); var collection_path = bvr.src_el.getAttribute("spt_collection_path"); var expr = "@SEARCH("+bvr.collection_type+"['parent_code','"+collection_code+"']."+bvr.search_type+")"; var parent_dict = {}; var parent_collection = bvr.src_el.getParent(".spt_subcollection_wdg"); var path = collection_path.substring(0, collection_path.lastIndexOf("/")); if (parent_collection) { for (var i = 0; i < collection_path.split("/").length - 1; i++) { var n = path.lastIndexOf("/"); var collection_name = path.substring(n+1); path = path.substring(0, n); var parent_key = parent_collection.getAttribute("spt_parent_key"); parent_dict[collection_name] = parent_key; parent_collection = parent_collection.getParent(".spt_subcollection_wdg"); } } var cls = "tactic.ui.panel.CollectionContentWdg"; var kwargs = { collection_key: collection_key, path: collection_path, search_type: bvr.search_type, show_shelf: false, show_search_limit: true, expression: expr, parent_dict: parent_dict } spt.panel.load(content, cls, kwargs); bvr.src_el.setStyle("box-shadow", "0px 0px 3px rgba(0,0,0,0.5)"); // hide the bottom show_search_limit when clicking into a collection var panel = bvr.src_el.getParent(".spt_panel"); var search_limit_div = panel.getElements(".spt_search_limit_top"); if (search_limit_div.length == 2){ search_limit_div[1].setStyle("visibility", "hidden"); } ''' }) collections_div.add_relay_behavior({ 'type': 'mouseup', 'search_type': my.search_type, 'bvr_match_class': 'spt_collection_open', 'cbjs_action': ''' var item = bvr.src_el.getParent(".spt_collection_div_top"); var next = item.getNext(); if (bvr.src_el.hasClass("spt_open")) { next.innerHTML = ""; bvr.src_el.setStyle("opacity", 1.0); bvr.src_el.removeClass("spt_open"); } else { var collection_key = bvr.src_el.getAttribute("spt_collection_key"); var collection_path = bvr.src_el.getAttribute("spt_collection_path"); var cls = "tactic.ui.panel.CollectionListWdg"; var kwargs = { parent_key: collection_key, path: collection_path, } spt.panel.load(next, cls, kwargs, null, {show_loading: false}); bvr.src_el.setStyle("opacity", 0.3); bvr.src_el.addClass("spt_open"); evt.stopPropagation(); } ''' }) for collection in collections: collection_wdg = CollectionItemWdg( collection=collection, path=collection.get_value("name")) collections_div.add(collection_wdg) collection_wdg.add_class("spt_collection_div") subcollection_wdg = DivWdg() collections_div.add(subcollection_wdg) subcollection_wdg.add_class("spt_subcollection_wdg") subcollection_wdg.add_style("padding-left: 15px") return div
def execute(my): collection_keys = my.kwargs.get("collection_keys") search_keys = my.kwargs.get("search_keys") message = {} if collection_keys == None: collection_keys = [] for collection_key in collection_keys: collection = Search.get_by_search_key(collection_key) if not collection: raise Exception("Collection does not exist") collection_name = collection.get("name") search_type = collection.get_base_search_type() parts = search_type.split("/") collection_type = "%s/%s_in_%s" % (parts[0], parts[1], parts[1]) search = Search(collection_type) search.add_filter("parent_code", collection.get_code()) items = search.get_sobjects() search_codes = [x.get_value("search_code") for x in items] search_codes = set(search_codes) # Try to find all the parent codes of the destination, and see if there's any that # matches the codes in "search_codes" # Check for parent/child hierarchy in destination to prevent circular relationships src_collections_codes = [] for search_key in search_keys: asset = Search.get_by_search_key(search_key) is_collection = asset.get("_is_collection") if is_collection: src_collection_code = asset.get("code") src_collections_codes.append(src_collection_code) if src_collections_codes: collection_code = collection.get("code") my.kwargs["collection_code"] = collection_code my.kwargs["collection_type"] = collection_type my.kwargs["search_type"] = search_type # Run SQL to find all parent collections(and above) of the selected collections # The all_parent_codes contain all parent codes up the relationship tree # ie. parent collections' parents ...etc all_parent_codes = my.get_parent_codes() all_parent_codes.add(collection_code) all_parent_codes = list(all_parent_codes) # Once retrieve the parent codes, use a for loop to check if the the codes in # src_collections_codes are in parent_codes parent_collection_names = [] for parent_code in all_parent_codes: if parent_code in src_collections_codes: message['circular'] = "True" parent_collection_name = Search.get_by_code( search_type, parent_code).get("name") parent_collection_names.append(parent_collection_name) if parent_collection_names: message[ 'parent_collection_names'] = parent_collection_names my.info['message'] = message return has_keywords = SearchType.column_exists(search_type, "keywords") if has_keywords: collection_keywords = collection.get_value("keywords", no_exception=True) collection_keywords = collection_keywords.split(" ") collection_keywords = set(collection_keywords) # create new items has_inserted = False sobjects = Search.get_by_search_keys(search_keys) for sobject in sobjects: if sobject.get_code() in search_codes: continue new_item = SearchType.create(collection_type) new_item.set_value("parent_code", collection.get_code()) new_item.set_value("search_code", sobject.get_code()) new_item.commit() has_inserted = True # copy the metadata of the collection if has_keywords: keywords = sobject.get_value("keywords") keywords = keywords.split(" ") keywords = set(keywords) keywords = keywords.union(collection_keywords) keywords = " ".join(keywords) sobject.set_value("keywords", keywords) sobject.commit() if not has_inserted: message[collection_name] = "No insert" else: message[collection_name] = "Insert OK" my.info['message'] = message my.add_description("Add [%s] item(s) to [%s] collection(s)" % (len(search_keys), len(collection_keys)))
def get_display(my): search_type = my.kwargs.get("search_type") search = Search(search_type) if not search.column_exists("_is_collection"): return my.top search.add_filter("_is_collection", True) collections = search.get_sobjects() dialog = DivWdg() my.set_as_panel(dialog) dialog.add_class('spt_col_dialog_top') title_div = DivWdg() title_div.add_style('margin: 10px') title_div.add(HtmlElement.b("Add selected items to collection(s)")) dialog.add(title_div) add_div = DivWdg() dialog.add(add_div) icon = IconWdg(name="Add new collection", icon="BS_PLUS") icon.add_style("opacity: 0.6") icon.add_style("padding-right: 3px") add_div.add(icon) add_div.add("Create new Collection") add_div.add_style("text-align: center") add_div.add_style("background-color: #EEEEEE") add_div.add_style("padding: 5px") add_div.add_style("height: 20px") add_div.add_class("hand") insert_view = "edit_collection" add_div.add_behavior({ 'type': 'listen', 'event_name': 'refresh_col_dialog', 'cbjs_action': ''' var dialog_content = bvr.src_el.getParent('.spt_col_dialog_top'); spt.panel.refresh(dialog_content); ''' }) add_div.add_behavior({ 'type': 'click_up', 'insert_view': insert_view, 'event_name': 'refresh_col_dialog', 'cbjs_action': ''' var top = bvr.src_el.getParent(".spt_table_top"); var table = top.getElement(".spt_table"); var search_type = top.getAttribute("spt_search_type"); // Hide the dialog when popup loads. var dialog_top = bvr.src_el.getParent(".spt_dialog_top"); dialog_top.style.visibility = "hidden"; kwargs = { search_type: search_type, mode: "insert", view: bvr.insert_view, save_event: bvr.event_name, show_header: false, 'num_columns': 2, default: { _is_collection: true } }; spt.panel.load_popup("Create New Collection", "tactic.ui.panel.EditWdg", kwargs); ''' }) content_div = DivWdg() dialog.add(content_div) content_div.add_style("width: 270px") content_div.add_style("padding: 5px") content_div.add_style("padding-bottom: 0px") custom_cbk = {} custom_cbk['enter'] = ''' var top = bvr.src_el.getParent(".spt_dialog"); var input = top.getElement(".spt_main_search"); var search_value = input.value.toLowerCase(); var collections = top.getElements(".spt_collection_div"); var num_result = 0; for (i = 0; i < collections.length; i++) { // Access the Collection title (without number count) var collection_title = collections[i].attributes[0].value.toLowerCase(); if (collection_title.indexOf(search_value) != '-1') { collections[i].style.display = "block"; num_result += 1; } else { collections[i].style.display = "none"; } } // if no search results, display all if (num_result == 0) { for (i = 0; i < collections.length; i++) { collections[i].style.display = "block"; } } ''' filters = [] filters.append(("_is_collection", True)) filters.append(("status", "Verified")) text = LookAheadTextInputWdg( search_type="workflow/asset", column="name", icon="BS_SEARCH", icon_pos="right", width="100%", height="30px", hint_text="'Enter' to search for Colllection...", value_column="name", filters=filters, custom_cbk=custom_cbk, is_collection=True) text.add_class("spt_main_search") content_div.add(text) # set minimum if there is at least one collection if len(collections) > 0: content_div.add_style("min-height: 300") content_div.add_style("max-height: 300") content_div.add_style("overflow-y: auto") content_div.add("<br clear='all'/>") for collection in collections: search_type = collection.get_base_search_type() parts = search_type.split("/") collection_type = "%s/%s_in_%s" % (parts[0], parts[1], parts[1]) search = Search(collection_type) search.add_filter("parent_code", collection.get_code()) num_items = search.get_count() collection_div = DivWdg() collection_div.add_class("spt_collection_div") content_div.add(collection_div) collection_div.add_style("margin: 3px 5px 0px 5px") go_wdg = DivWdg() collection_div.add(go_wdg) go_wdg.add_style("float: right") #TODO: add some interaction with this arrow # icon = IconWdg(name="View Collection", icon="BS_CHEVRON_RIGHT") # go_wdg.add(icon) #go_wdg.add_behavior( { # 'type': 'click_upX', # 'cbjs_action': ''' # alert("Not Implemented"); # ''' #} ) name = collection.get_value("name") # Adding Collection title (without the number count) as an attribute #collection_div.set_attr("collection_name", name) if not name: name = collection.get_value("code") check_div = DivWdg() collection_div.add(check_div) check = CheckboxWdg("collection_key") check.add_class("spt_collection_checkbox") check_div.add(check) check_div.add_style("float: left") check_div.add_style("margin-right: 5px") check_div.add_style("margin-top: -3px") check.add_attr("collection_key", collection.get_search_key()) check.add_attr("collection_name", collection.get_name()) info_div = DivWdg() collection_div.add(info_div) info_div.add(name) if num_items: info_div.add(" (%s)" % num_items) collection_div.add("<hr/>") add_button = DivWdg() add_button.add("Add") add_button.add_style("margin: 0px 10px 10px 10px") add_button.add_style("width: 50px") add_button.add_class("btn btn-primary") dialog.add(add_button) add_button.add_behavior({ 'type': 'click', 'cbjs_action': ''' var search_keys = spt.table.get_selected_search_keys(false); if (search_keys.length == 0) { spt.notify.show_message("No items selected."); return; } var top = bvr.src_el.getParent(".spt_dialog"); var checkboxes = top.getElements(".spt_collection_checkbox"); var cmd = "tactic.ui.panel.CollectionAddCmd"; var server = TacticServerStub.get(); var is_checked = false; var added = []; var collection_keys = []; var dialog_top = bvr.src_el.getParent(".spt_col_dialog_top"); for (i = 0; i < checkboxes.length; i++) { if (checkboxes[i].checked == true) { var collection_key = checkboxes[i].getAttribute('collection_key'); var collection_name = checkboxes[i].getAttribute('collection_name'); // Preventing a collection being added to itself, check if search_keys contain collection_key. if (search_keys.indexOf(collection_key) != -1) { spt.notify.show_message("Collection [" + collection_name + " ] cannot be added to itself."); return; } // if there is at least one checkbox selected, set is_checked to 'true' is_checked = true; // If the collection is not being added to itself, append to the list of collection keys collection_keys.push(collection_key); } } if (is_checked == false) { spt.notify.show_message("No collection selected."); } else { var kwargs = { collection_keys: collection_keys, search_keys: search_keys } var rtn = server.execute_cmd(cmd, kwargs); var rtn_message = rtn.info.message; if (rtn_message['circular'] == 'True') { var parent_collection_names = rtn_message['parent_collection_names'].join(", "); spt.notify.show_message("Collection [" + collection_name + " ] is a child of the source [" + parent_collection_names + "]"); return; } for (var collection_name in rtn_message) { if (rtn_message[collection_name] != 'No insert') added.push(collection_name); } if (added.length == 0) spt.notify.show_message("Items already added to Collection."); else spt.notify.show_message("Items added to Collection [ " + added.join(', ') + " ]."); // refresh dialog_top, so users can see the number change in Collections spt.panel.refresh(dialog_top); } ''' }) return dialog
def get_display(self): web = WebContainer.get_web() palette = web.get_palette() widget = DivWdg() widget.add_style("width: 100%") widget.add_style("text-align: center") from tactic.ui.app import PageHeaderWdg header = PageHeaderWdg(show_project=False) widget.add(header) security = Environment.get_security() search = Search("sthpw/project") search.add_where("\"code\" not in ('sthpw', 'admin', 'unittest')") search.add_where("\"type\" not in ('resource')") # hide template projects if security.check_access("builtin", "view_site_admin", "allow") or security.check_access( "builtin", "view_template_projects", "allow"): pass else: search.add_op("begin") search.add_filter("is_template", True, op='!=') search.add_filter("is_template", 'NULL', quoted=False, op='is') search.add_op("or") search.add_order_by("category") projects = search.get_sobjects() num = len(projects) # sort by project if num < 5: columns = 1 icon_size = 90 width = 500 elif num < 15: columns = 2 icon_size = 60 width = 700 else: columns = 3 icon_size = 45 width = 800 div = DivWdg() div.add_style("margin-left: auto") div.add_style("margin-right: auto") #div.add_style("width: 520px") div.center() widget.add(div) #logo = TacticLogoWdg() #div.add(logo) div.add("<br/>" * 3) bg_color = palette.color("background") #div.add_color("color", "color") from tactic.ui.container import RoundedCornerDivWdg div = RoundedCornerDivWdg(hex_color_code=bg_color, corner_size="10") div.set_dimensions(width_str='%spx' % width, content_height_str='50px') div.add_border() div.add_style("overflow: hidden") div.set_box_shadow() div.add_style("margin-left: auto") div.add_style("margin-right: auto") div.add_style("width: %spx" % width) table = Table() table.set_max_width() table.add_style("margin-left: auto") table.add_style("margin-right: auto") table.add_style("background-color: %s" % bg_color) table.add_color("color", "color") tr, td = table.add_row_cell() logo_div = DivWdg() logo_div.add_gradient("background", "background3", -5, -10) td.add(logo_div) logo = TacticLogoWdg() logo_div.add(logo) logo_div.add_style("margin: -6 -6 6 -6") app_name = WebContainer.get_web().get_app_name() security = Environment.get_security() last_category = None has_category = False index = 0 # if TACTIC has not been set up, show the configuration page # FIXME: what is the requirement for is_installed? config_path = Config.get_config_path() if not os.path.exists(config_path): is_installed = False else: is_installed = True #is_installed = True # filter out projects due to security filtered = [] for i, project in enumerate(projects): from pyasm.security import get_security_version security_version = get_security_version() if security_version >= 2: key = {"code": project.get_code()} key2 = {"code": "*"} keys = [key, key2] default = "deny" if not security.check_access( "project", keys, "allow", default=default): continue else: if not security.check_access( "project", project.get_code(), "view", default="allow"): continue filtered.append(project) projects = filtered if not is_installed: tr, td = table.add_row_cell() #from tactic.ui.startup import DbConfigWdg #td.add(DbConfigWdg()) title_div = DivWdg() td.add(title_div) title_div.add_style("padding: 5px") title_div.add_style("font-weight: bold") title_div.add("Getting Started ...") title_div.add_gradient("background", "background", -10) projects_div = DivWdg() projects_div.add_style("padding: 20px") td.add(projects_div) projects_div.add_style("text-align: center") projects_div.add("Welcome to TACTIC ...<br/>") projects_div.add_style("font-size: 22px") msg_div = DivWdg() td.add(msg_div) msg_div.add( "Configure TACTIC to connect to an external database and set up asset folders.<br/><br/>" ) msg_div.add_style("text-align: center") action = ActionButtonWdg(title='Confgure', size='medium') action.add_style("margin-left: auto") action.add_style("margin-right: auto") td.add(action) action.add_behavior({ 'type': 'click_up', 'cbjs_action': ''' document.location = "/tactic/admin/#/link/configure"; ''' }) msg_div = DivWdg() td.add(msg_div) msg_div.add( "<br/><br/>Or start using TACTIC with default configuration with an internal database.<br/><br/>" ) msg_div.add_style("text-align: center") action = ActionButtonWdg(title='Start >>', size='medium') action.add_style("margin-left: auto") action.add_style("margin-right: auto") td.add(action) action.add_behavior({ 'type': 'click_up', 'cbjs_action': ''' document.location = "/tactic"; ''' }) msg_div = DivWdg() td.add(msg_div) msg_div.add("<br/><br/><br/>") msg_div.add_style("text-align: center") elif projects: num_projets = 0 for i, project in enumerate(projects): category = project.get_value("category") if category is not None and category != last_category: table.add_row() tr, td = table.add_row_cell() category_div = DivWdg() td.add(category_div) if has_category and not category: category_div.add(" ") else: category_div.add(category) category_div.add_style("padding: 8px") category_div.add_style("font-size: 16px") category_div.add_style("font-weight: bold") category_div.add_color("color", "color") category_div.add_gradient("background", "background3", 0, -10) category_div.add_color("color", "color3") #category_div.set_round_corners() if last_category == None: category_div.add_style("margin: -6 -6 6 -6") else: category_div.add_style("margin: 15 -6 0 -6") table.add_row() has_category = True index = 0 index += 1 last_category = category thumb = ThumbWdg() thumb.set_name("snapshot") thumb.set_sobject(project) thumb.set_show_clipboard(False) thumb.set_has_img_link(False) thumb.set_icon_size(icon_size) code = project.get_code() title = project.get_value("title") # Restrict the length of project name if len(title) >= 36: title = title[:36] + "..." if app_name != 'Browser': href = HtmlElement.href(HtmlElement.h2(title), ref='/tactic/%s/%s'\ %(code, app_name)) img_href = HtmlElement.href(thumb, ref='/tactic/%s/%s'\ %(code, app_name)) link = '/tactic/%s/%s' % (code, app_name) else: href = HtmlElement.href(HtmlElement.h2(title), ref="/tactic/%s/" % code) img_href = DivWdg(thumb) img_href.add_behavior({ 'type': 'click_up', 'code': code, 'cbjs_action': ''' document.location = '/tactic/'+bvr.code+'/'; ''' }) link = '/tactic/%s/' % code href = href.get_buffer_display() if (index - 1) % columns == 0: table.add_row() td = table.add_cell() img_div = DivWdg() img_div.add(img_href) img_div.add_style("margin-right: 20px") img_div.add_style("float: left") img_div.add_border() #img_div.set_round_corners() img_div.set_box_shadow("0px 1px 5px") project_div = DivWdg() td.add(project_div) td.add_style("width: 230px") project_div.add_style("font-size: 16px") project_div.add_style("font-weight: bold") project_div.add_style("vertical-align: middle") project_div.add(img_div) #project_div.add(href) project_div.add(title) if project.get_value("is_template") == True: project_div.add( "<br/><i style='opacity: 0.5; font-size: 12px'>(template)</i>" ) project_div.add_style("height: %spx" % (icon_size - 10)) project_div.add_style("padding: 8px 10px 2px 20px") project_div.add_color("background", "background") project_div.add_behavior({ 'type': 'hover', 'add_color_modifier': -3, 'cb_set_prefix': 'spt.mouse.table_layout_hover', }) project_div.set_round_corners() project_div.add_class("hand") project_div.add_behavior({ 'type': 'click_up', 'link': link, 'title': title, 'cbjs_action': ''' document.location = bvr.link; ''' }) elif not security.check_access( "builtin", "view_site_admin", "allow", default="deny") and not security.check_access( "builtin", "create_projects", "allow", default="deny"): tr, td = table.add_row_cell() msg_div = DivWdg() td.add(msg_div) from pyasm.widget import IconWdg icon = IconWdg("WARNING", IconWdg.WARNING) msg_div.add(icon) msg_div.add("You are not permitted to view any projects") msg_div.add_style("font-size: 16px") msg_div.add_style("text-align: center") msg_div.add_style("font-weight: bold") msg_div.add_style("margin: 50px") msg_div.add("<br/>" * 2) msg_div.add("Please click to Sign Out:<br/>") action = ActionButtonWdg(title='Sign Out >>', size='m') msg_div.add(action) action.add_style('margin: 5px auto') action.add_style('text-align: center') web = WebContainer.get_web() action.add_behavior({ 'type': 'click_up', 'login': web.get_user_name(), 'cbjs_action': ''' var server = TacticServerStub.get(); server.execute_cmd("SignOutCmd", {login: bvr.login} ); window.location.href='/'; ''' }) else: tr, td = table.add_row_cell() title_div = DivWdg() td.add(title_div) title_div.add_style("padding: 10px") title_div.add_style("margin: -8px -6px 20px -6px") title_div.add_style("font-weight: bold") title_div.add("Getting Started ...") title_div.add_gradient("background", "background", -10) projects_div = DivWdg() projects_div.add_style("padding: 20px") td.add(projects_div) projects_div.add_style("text-align: center") projects_div.add("No Projects have been created ...<br/><br/>") projects_div.add_style("font-size: 22px") action = ActionButtonWdg(title='Create Project >>', size='large') action.add_style("margin-left: auto") action.add_style("margin-right: auto") projects_div.add(action) action.add_behavior({ 'type': 'click_up', 'cbjs_action': ''' document.location = "/tactic/admin/link/create_project"; ''' }) if security.check_access("builtin", "view_site_admin", "allow"): admin_div = DivWdg() #href = HtmlElement.href(HtmlElement.h2('Admin Site'), ref='/tactic/admin/') #admin_div.add(href) #admin_div.add_border() admin_div.add_style("font-size: 16px") admin_div.add_style("font-weight: bold") admin_div.add_style("height: 30px") link_div = DivWdg() link_div.add_class("hand") admin_div.add(link_div) link_div.add("Go to Admin Site") link_div.add_style("text-align: center") link_div.add_behavior({ 'type': 'click_up', 'cbjs_action': ''' document.location = '/tactic/admin/'; ''' }) tr, td = table.add_row_cell() td.add("<hr/><br/>") td.add(admin_div) div.add(table) widget.add(div) # Note sure what this is for #BaseAppServer.add_onload_script('spt.first_load=false') div.add_behavior({ 'type': 'load', 'cbjs_action': '''spt.first_load=false''' }) return widget
def get_display(self): element_data_dict = {} config = self.get_config() element_names = config.get_element_names() content_wdg = DivWdg() content_wdg.add_class("spt_simple_search_top") onload_js = DivWdg() content_wdg.add(onload_js) onload_js.add_behavior({ 'type': 'load', 'cbjs_action': self.get_onload_js() }) if not element_names: element_names = ['keywords'] self.set_content(content_wdg) # this is somewhat duplicated logic from alter_search, but since this is called # in ViewPanelWdg, it's a diff instance and needs to retrieve again filter_data = FilterData.get() filter_view = self.kwargs.get("filter_view") if filter_view: search = Search("config/widget_config") search.add_filter("view", filter_view) search.add_filter("category", "search_filter") search.add_filter("search_type", self.search_type) filter_config = search.get_sobject() if filter_config: filter_xml = filter_config.get_xml_value("config") filter_value = filter_xml.get_value("config/filter/values") if filter_value: data_list = jsonloads(filter_value) else: data_list = filter_data.get_values_by_prefix(self.prefix) for data in data_list: handler = data.get("handler") element_name = data.get("element_name") if not element_name: continue element_data_dict[element_name] = data elements_wdg = DivWdg() content_wdg.add(elements_wdg) elements_wdg.add_color("color", "color") elements_wdg.add_style("padding-top: 10px") elements_wdg.add_style("padding-bottom: 15px") #elements_wdg.add_color("background", "background3", 0) elements_wdg.add_color("background", "background", -3) elements_wdg.add_border() if len(element_names) == 1: elements_wdg.add_style("border-width: 0px 0px 0px 0px") elements_wdg.add_style("padding-right: 50px") else: elements_wdg.add_style("border-width: 0px 0px 0px 0px") table = Table() table.add_color("color", "color") elements_wdg.add(table) table.add_class("spt_simple_search_table") columns = self.kwargs.get("columns") if not columns: columns = 2 else: columns = int(columns) num_rows = int(len(element_names) / columns) + 1 tot_rows = int(len(element_names) / columns) + 1 project_code = Project.get_project_code() # self.search_type could be the same as self.base_search_type full_search_type = SearchType.build_search_type( self.search_type, project_code) visible_rows = self.kwargs.get("visible_rows") if visible_rows: visible_rows = int(visible_rows) num_rows = visible_rows else: visible_rows = 0 titles = config.get_element_titles() row_count = 0 for i, element_name in enumerate(element_names): attrs = config.get_element_attributes(element_name) if i % columns == 0: if visible_rows and row_count == visible_rows: tr, td = table.add_row_cell("+ more ...") td.add_class("hand") td.add_class("SPT_DTS") td.add_class("spt_toggle") td.add_style("padding-left: 10px") td.add_behavior({ 'type': 'click_up', 'visible_rows': visible_rows, 'cbjs_action': ''' var top = bvr.src_el.getParent(".spt_simple_search_table"); var expand = true; var rows = top.getElements(".spt_simple_search_row"); for (var i = 0; i < rows.length; i++) { var row = rows[i]; if (row.getStyle("display") == "none") { row.setStyle("display", ""); } else { row.setStyle("display", "none"); expand = false; } } var spacer = top.getElements(".spt_spacer"); var cell = top.getElement(".spt_toggle"); if (expand) { spacer.setStyle("height", (rows.length+bvr.visible_rows)*20); cell.innerHTML = "- less ..."; } else { spacer.setStyle("height", bvr.visible_rows*20); cell.innerHTML = "+ more ..."; } ''' }) tr = table.add_row() if visible_rows and row_count >= visible_rows: tr.add_class("spt_simple_search_row") tr.add_style("display: none") tr.add_style("height: 0px") row_count += 1 icon_td = table.add_cell() title_td = table.add_cell() element_td = table.add_cell() # need to add these to all the elements because it is all separated # by table tds icon_td.add_class("spt_element_item") icon_td.add_attr("spt_element_name", element_name) title_td.add_class("spt_element_item") title_td.add_attr("spt_element_name", element_name) element_td.add_class("spt_element_item") element_td.add_attr("spt_element_name", element_name) # show the title title_td.add_style("text-align: left") title_td.add_style("padding-right: 5px") title_td.add_style("min-width: 60px") element_wdg = DivWdg() if attrs.get('view') == 'false': element_wdg.add_style('display: none') element_td.add(element_wdg) if i >= 0 and i < columns - 1 and len(element_names) > 1: spacer = DivWdg() spacer.add_class("spt_spacer") spacer.add_style("border-style: solid") spacer.add_style("border-width: 0 0 0 0") #spacer.add_style("height: %spx" % (num_rows*20)) spacer.add_style("height: %spx" % (num_rows * 10)) spacer.add_style("width: 10px") spacer.add_style("border-color: %s" % spacer.get_color("border")) spacer.add(" ") td = table.add_cell(spacer) td.add_attr("rowspan", tot_rows) element_wdg.add_style("padding: 4px 10px 4px 5px") element_wdg.add_class("spt_table_search") element_wdg.add_style("margin: 1px") element_wdg.add_style("min-height: 20px") element_wdg.add_style("min-width: 250px") # this is done at get_top() #element_wdg.add_class("spt_search") element_wdg.add(HiddenWdg("prefix", self.prefix)) display_handler = config.get_display_handler(element_name) element_wdg.add(HiddenWdg("handler", display_handler)) element_wdg.add(HiddenWdg("element_name", element_name)) from pyasm.widget import ExceptionWdg try: widget = config.get_display_widget(element_name) if widget: widget.set_title(titles[i]) except Exception as e: element_wdg.add(ExceptionWdg(e)) continue if not widget: # the default for KeywordFilterElementWdg is mode=keyword if not self.column_choice: self.column_choice = self.get_search_col(self.search_type) widget = KeywordFilterElementWdg(column=self.column_choice) widget.set_name(element_name) from pyasm.widget import IconWdg icon_div = DivWdg() icon_td.add(icon_div) icon_div.add_style("width: 20px") icon_div.add_style("margin-top: -2px") icon_div.add_style("padding-left: 6px") icon_div.add_class("spt_filter_top") widget.set_show_title(False) #element_wdg.add("%s: " % title) data = element_data_dict.get(element_name) view_panel_keywords = self.kwargs.get("keywords") #user data takes precedence over view_panel_keywords if isinstance(widget, KeywordFilterElementWdg): if view_panel_keywords: widget.set_value("value", view_panel_keywords) if data: widget.set_values(data) if isinstance( widget, KeywordFilterElementWdg ) and not full_search_type.startswith('sthpw/sobject_list'): widget.set_option('filter_search_type', full_search_type) try: if attrs.get('view') != 'false': title_td.add(widget.get_title_wdg()) element_wdg.add(widget.get_buffer_display()) except Exception as e: element_wdg.add(ExceptionWdg(e)) continue icon = IconWdg("Filter Set", "BS_ASTERISK") #icon.add_style("color", "#393") icon_div.add(icon) icon.add_class("spt_filter_set") icon.add_class("hand") icon.add_attr("spt_element_name", element_name) icon.add_behavior({ 'type': 'click', 'cbjs_action': ''' var element_name = bvr.src_el.getAttribute("spt_element_name"); spt.simple_search.clear_element(element_name); ''' }) if not widget.is_set(): icon.add_style("display: none") else: color = icon_div.get_color("background", -10) icon_td.add_style("background-color", color) title_td.add_style("background-color", color) element_td.add_style("background-color", color) #elements_wdg.add("<br clear='all'/>") top = self.get_top() return top
def init(self): self.user_override = self.kwargs.get('user_override') in ['true', True] custom_search_view = self.kwargs.get('custom_search_view') if not custom_search_view or not custom_search_view.strip(): custom_search_view = 'search' # create a search for this search widget self.search_type = self.kwargs.get('search_type') self.search = self.kwargs.get("search") if not self.search: self.search = Search(self.search_type) self.config = None # determine whether or not to use the last search. If any kind of # state has been set, then ignore the last_search self.use_last_search = True parent_key = self.kwargs.get('parent_key') state = self.kwargs.get('state') if parent_key or state or self.kwargs.get('use_last_search') in [False, 'false']: self.use_last_search = False self.prefix_namespace = self.kwargs.get('prefix_namespace') # NOTE: this is still hard coded self.prefix = 'main_body' # if we are asking for a specific saved search save = self.kwargs.get('save') self.view = self.kwargs.get('view') # get the config from a specific location # if the view is specified, use this view with the values # specified explicitly in this view self.config = None # see if a filter is explicitly passed in filter = self.kwargs.get('filter') self.limit = self.kwargs.get('limit') self.run_search_bvr = self.kwargs.get('run_search_bvr') # get from search view # filter can be either dict(data) or a list or # xml(filter wdg definition) if filter: if type(filter) == types.DictType: self.config = self.get_default_filter_config() filter_data = FilterData([filter]) filter_data.set_to_cgi() elif type(filter) == types.ListType: self.config = self.get_default_filter_config() filter_data = FilterData(filter) filter_data.set_to_cgi() else: try: filter_data = None # TODO: remove this. This is for backward compatibilty self.config = WidgetConfig.get(xml=filter, view='filter') filter_data = FilterData.get() if not filter_data.get_data(): # use widget settings key = SearchWdg._get_key(self.search_type, self.view) data = WidgetSettings.get_value_by_key(key) if data: filter_data = FilterData(data) filter_data.set_to_cgi() except XmlException as e: print("WARNING: non-xml filter detected!!") # NOTE: this is only used to maintain backwards compatibility # plus it is needed for link_search: which contains the filter_config (old way of doing it) if not self.config:# and self.view: """ if ':' in self.view: # avoid view of a SearchWdg like link_search:<search_type>:<view> search_view = custom_search_view else: search_view = self.view """ search_view = custom_search_view config_view = WidgetConfigView.get_by_search_type(self.search_type, view=search_view) # get the self.config first for the display of SearchWdg # then get the filter data below if there is any if config_view.get_config().has_view(search_view): self.config = config_view.get_config() try: search = Search('config/widget_config') search.add_filter("view", self.view) search.add_filter("search_type", self.search_type) config_sobjs = search.get_sobjects() from pyasm.search import WidgetDbConfig config_sobj = WidgetDbConfig.merge_configs(config_sobjs) #config_sobj = config_sobjs[0] except SearchException as e: print("WARNING: ", e) config_sobj = None if config_sobj: config_xml = config_sobj.get_xml_value("config") if not config_view.get_config().has_view(self.view): # make sure it does have the old way of storing filter # elements instead of just filter data if config_xml.get_nodes("config/filter/element"): self.config = WidgetConfig.get(xml=config_xml, view='filter') #self.config = self.get_default_filter_config() # set the form variables for the filters data = config_xml.get_value("config/filter/values") # link_search with specific search params takes precesdence # TODO: make a distinction between search definition and alter # search data provided by user if data and not self.user_override: filter_data = FilterData(data) filter_data.set_to_cgi() else: self.set_filter_data(self.search_type, self.view) else: if self.use_last_search: self.set_filter_data(self.search_type, self.view) if not self.config: # get the approprate filter definition self.config = self.get_default_filter_config() if self.use_last_search: self.set_filter_data(self.search_type, self.view) if not self.config: return self.num_filters_enabled = 0 # create the filters self.filters = [] security = Environment.get_security() element_names = self.config.get_element_names() #element_names = ["Keywords", "Related"] for element_name in element_names: filter = self.config.get_display_widget(element_name) if filter and filter.is_visible(): self.filters.append(filter) # make sure there is at least one filter defined #assert self.filters # just for drawing purpose if self.kwargs.get('skip_search') == True: return try: self.alter_search() self.set_persistent_value() except SearchInputException as e: self.clear_search_data(self.search_type) raise SearchInputException("%s If this problem persists, this view may contain invalid data in < values >. Clean up the data in Widget Config for the view [%s]."%( e.__str__(), self.view)) except: self.clear_search_data(self.search_type) raise
def get_display(self): search_type = self.kwargs.get("search_type") div = self.top div.add("List of Saved Searches: ") div.add(HtmlElement.br(2)) div.add_style("margin: 20px") div.add_style("width: 400px") div.add_class("spt_saved_search_top") try: search = Search("config/widget_config") search.add_op("begin") search.add_filter("view", 'saved_search:%', op="like") search.add_filter("category", 'search_filter') search.add_op("or") search.add_op("begin") search.add_user_filter() search.add_filter("login", "NULL", op="is", quoted=False) search.add_op("or") search.add_filter("search_type", search_type) configs = search.get_sobjects() except SearchException as e: print("WARNING: ", e) configs = [] except: SearchWdg.clear_search_data(search_type) raise """ from tactic.ui.panel import TableLayoutWdg element_names = ['view','name','description','delete'] table = TableLayoutWdg( search_type=search_type, element_names=element_names, search=search, show_shelf=False, show_border=False, show_search_limit=False, height="auto", ) div.add(table) """ values = [x.get("view") for x in configs] labels = [x.get("title") or x.get("view") for x in configs] select = SelectWdg("saved_search") div.add(select) select.set_id("saved_search") select.add_class("spt_saved_search_input") select.add_empty_option("-- Select --") select.set_option("values", values) select.set_option("labels", labels) retrieve_button = ActionButtonWdg(title="Load") behavior = { 'type': 'click', #'cbjs_action': 'spt.dg_table.retrieve_search_cbk(evt, bvr);' 'cbjs_action': ''' var top = bvr.src_el.getParent(".spt_saved_search_top") var input = top.getElement(".spt_saved_search_input"); var value = input.value; if (!value) { spt.alert("Please select a saved search to load."); return; } var popup = bvr.src_el.getParent(".spt_popup"); var activator = popup.activator; var layout = activator.getElement(".spt_layout"); spt.table.set_layout(layout); spt.table.load_search(value); ''' } retrieve_button.add_behavior( behavior ) retrieve_button.add_style("display: inline-block") remove_button = ActionButtonWdg(title="Remove") remove_button.add_behavior( { 'cbjs_action': ''' var top = bvr.src_el.getParent(".spt_saved_search_top") var input = top.getElement(".spt_saved_search_input"); var value = input.value; if (!value) { spt.alert("Please select a saved search to remove."); return; } spt.alert("Remove: " + value); ''' } ) remove_button.add_style("display: inline-block") cancel_button = ActionButtonWdg(title="Cancel") cancel_button.add_behavior( { 'cbjs_action': ''' var popup = bvr.src_el.getParent(".spt_popup"); spt.popup.close(popup); ''' } ) cancel_button.add_style("display: inline-block") div.add("<br/>") button_div = DivWdg() button_div.add_style("text-align: center") button_div.add(retrieve_button) button_div.add(" ") button_div.add(remove_button) button_div.add(" ") button_div.add(cancel_button) div.add(button_div) div.add("<hr/>") save_div = DivWdg() div.add(save_div) save_div.add("Save Current Search") save_div.add("<br/>") save_div.add("<br/>") text = TextInputWdg(name="new_search_name") save_div.add(text) text.add_class("spt_new_search_name") save_div.add("<br/>") save_button = ActionButtonWdg(title="Save Search", width="200") save_div.add(save_button) save_button.add_behavior( { 'cbjs_action': ''' var top = bvr.src_el.getParent(".spt_saved_search_top"); var input = top.getElement(".spt_new_search_name"); var value = input.value; if (!value) { spt.alert("No view name specified"); return; } spt.table.save_search(value, {personal: true}); spt.notify.show_message("Search saved"); var popup = bvr.src_el.getParent(".spt_popup"); spt.popup.close(popup); ''' } ) save_button.add_style("display: inline-block") return div
def get_display(my): collection = my.kwargs.get("collection") path = my.kwargs.get("path") search_type = collection.get_base_search_type() parts = search_type.split("/") collection_type = "%s/%s_in_%s" % (parts[0], parts[1], parts[1]) search = Search(collection_type) search.add_filter("parent_code", collection.get_value("code")) search.add_column("search_code") items = search.get_sobjects() codes = [x.get_value("search_code") for x in items] count = search.get_count() # find the children that are actually collections search = Search(search_type) search.add_filter("_is_collection", True) search.add_filters("code", codes) has_child_collections = search.get_count() > 0 top = my.top collection_top = top collection_top.add_class("spt_collection_div_top") collection_div = DivWdg() name = collection.get_value("name") # Adding Collection title (without the number count) as an attribute collection_top.set_attr("collection_name", name) collection_top.add(collection_div) collection_top.add_class("tactic_hover") collection_top.add_class("hand") collection_div.add_class("spt_collection_item") collection_div.add_attr("spt_collection_key", collection.get_search_key()) collection_div.add_attr("spt_collection_code", collection.get_code()) collection_div.add_attr("spt_collection_path", path) # This is for Drag and Drop from a tile widget collection_div.add_class("spt_tile_top") collection_div.add_attr("spt_search_key", collection.get_search_key()) collection_div.add_attr("spt_search_code", collection.get_code()) collection_div.add_attr("spt_name", name) collection_div.add_style("height: 20px") collection_div.add_style("padding-top: 10px") if has_child_collections: icon_div = DivWdg() icon = IconWdg(name="View Collection", icon="BS_CHEVRON_DOWN") icon_div.add(icon) icon.add_style("float: right") icon.add_style("margin-top: -20px") collection_top.add(icon_div) icon_div.add_class("spt_collection_open") icon_div.add_attr("spt_collection_key", collection.get_search_key()) icon_div.add_attr("spt_collection_path", path) from tactic.ui.panel import ThumbWdg2 thumb_wdg = ThumbWdg2() thumb_wdg.set_sobject(collection) collection_div.add(thumb_wdg) thumb_wdg.add_style("width: 45px") thumb_wdg.add_style("float: left") thumb_wdg.add_style("margin-top: -10px") if count: count_div = DivWdg() collection_div.add(count_div) #count_div.add_style("margin-top: -10px") #count_div.add_style("margin-left: -10px") count_div.add_style("width: 15px") count_div.add_style("height: 15px") count_div.add_style("font-size: 0.8em") count_div.add_style("border-radius: 10px") count_div.add_style("background: #DDD") count_div.add_style("position: absolute") count_div.add_style("text-align: center") count_div.add_style("margin-left: 23px") count_div.add_style("margin-top: -8px") count_div.add_style("box-shadow: 0px 0px 3px rgba(0,0,0,0.5)") expression = "@COUNT(%s['parent_code','%s'])" % ( collection_type, collection.get_code()) count_div.add(count) count_div.add_update({ #'expr_key': collection.get_search_key(), 'expression': expression, 'interval': 2 }) name = collection.get_value("name") collection_div.add(name) return top
def get_display(self): web = WebContainer.get_web() show_multi_project = web.get_form_value('show_multi_project') project = Project.get() search_type_objs = project.get_search_types( include_multi_project=show_multi_project) top = self.top top.add_class("spt_panel_stype_list_top") #top.add_style("min-width: 400px") #top.add_style("max-width: 1000px") #top.add_style("width: 100%") top.center() button = SingleButtonWdg(title="Advanced Setup", icon=IconWdg.ADVANCED) top.add(button) button.add_style("float: right") button.add_style("margin-top: 0px") button.add_behavior({ 'type': 'click_up', 'cbjs_action': ''' var class_name = 'tactic.ui.app.ProjectStartWdg'; spt.tab.set_main_body_tab() spt.tab.add_new("project_setup", "Project Setup", class_name) ''' }) button = SingleButtonWdg(title="Add", tip="Add New Searchable Type (sType)", icon="BS_PLUS") top.add(button) button.add_style("display: inline-block") button.add_style("vertical-align: middle") button.add_style("margin-top: 0px") button.add_style("margin-right: 15px") button.add_style("margin-left: 5px") button.add_behavior({ 'type': 'click_up', 'cbjs_action': ''' var class_name = 'tactic.ui.app.SearchTypeCreatorWdg'; var kwargs = { }; var popup = spt.panel.load_popup("Create New Searchable Type", class_name, kwargs); var top = bvr.src_el.getParent(".spt_panel_stype_list_top"); popup.on_register_cbk = function() { spt.panel.refresh(top); } ''' }) cb = CheckboxWdg('show_multi_project', label=' show multi-project') if show_multi_project: cb.set_checked() cb.add_behavior({ 'type': 'click_up', 'cbjs_action': ''' var panel = bvr.src_el.getParent('.spt_panel_stype_list_top') spt.panel.refresh(panel, {show_multi_project: bvr.src_el.checked}); ''' }) span = SpanWdg(css='small') top.add(span) top.add(cb) top.add("<br clear='all'/>") top.add("<br clear='all'/>") #search_type_objs = [] if not search_type_objs: arrow_div = DivWdg() top.add(arrow_div) icon = IconWdg("Click to Add", IconWdg.ARROW_UP_LEFT_32) icon.add_style("margin-top: -20") icon.add_style("margin-left: -15") icon.add_style("position: absolute") arrow_div.add(icon) arrow_div.add(" " * 5) arrow_div.add("<b>Click to Add</b>") arrow_div.add_style("position: relative") arrow_div.add_style("margin-top: 5px") arrow_div.add_style("margin-left: 20px") arrow_div.add_style("float: left") arrow_div.add_style("padding: 25px") arrow_div.set_box_shadow("0px 5px 20px") arrow_div.set_round_corners(30) arrow_div.add_color("background", "background") div = DivWdg() top.add(div) div.add_border() div.add_style("min-height: 180px") div.add_style("width: 600px") div.add_style("margin: 30px auto") div.add_style("padding: 20px") div.add_color("background", "background3") icon = IconWdg("WARNING", IconWdg.WARNING) div.add(icon) div.add("<b>No Searchable Types have been created</b>") div.add("<br/><br/>") div.add( "Searchables Types contain lists of items that are managed in this project. Each item will automatically have the ability to have files checked into it, track tasks and status and record work hours." ) div.add("<br/>" * 2) div.add("For more information, read the help docs: ") from tactic.ui.app import HelpButtonWdg help = HelpButtonWdg(alias="main") div.add(help) div.add("<br/>") div.add( "Click on the 'Add' button above to start adding new types.") return top div = DivWdg() top.add(div) #div.add_style("max-height: 300px") #div.add_style("overflow-y: auto") table = Table() div.add(table) table.add_style("margin-top: 14px") table.set_max_width() # group mouse over table.add_relay_behavior({ 'type': "mouseover", 'bvr_match_class': 'spt_row', 'cbjs_action': "spt.mouse.table_layout_hover_over({}, {src_el: bvr.src_el, add_color_modifier: -2})" }) table.add_relay_behavior({ 'type': "mouseout", 'bvr_match_class': 'spt_row', 'cbjs_action': "spt.mouse.table_layout_hover_out({}, {src_el: bvr.src_el})" }) border_color = table.get_color("border") tr = table.add_row() tr.add_color("color", "color") tr.add_color("background", "background", -3) tr.add_style("border-bottom: solid 1px %s" % border_color) th = table.add_header("") th.add_style("text-align: left") th = table.add_header("Title") th.add_style("text-align: left") th = table.add_header("# Items") th.add_style("text-align: left") th = table.add_header("View") th.add_style("text-align: left") th = table.add_header("Add") th.add_style("text-align: left") th = table.add_header("Import") th.add_style("text-align: left") th = table.add_header("Custom Columns") th.add_style("text-align: left") th = table.add_header("Workflow") th.add_style("text-align: left") th = table.add_header("Notifications") th.add_style("text-align: left") th = table.add_header("Triggers") th.add_style("text-align: left") th = table.add_header("Edit") th.add_style("text-align: left") #th = table.add_header("Security") #th.add_style("text-align: left") for i, search_type_obj in enumerate(search_type_objs): tr = table.add_row() tr.add_class("spt_row") if not i or not i % 2: tr.add_color("background", "background") else: tr.add_color("background", "background", -2) thumb = ThumbWdg() thumb.set_sobject(search_type_obj) thumb.set_icon_size(30) td = table.add_cell(thumb) search_type = search_type_obj.get_value("search_type") title = search_type_obj.get_title() table.add_cell(title) try: search = Search(search_type) count = search.get_count() if count: table.add_cell("%s item/s" % count) else: table.add_cell(" ") except: td = table.add_cell("< No table >") td.add_style("font-style: italic") td.add_style("color: #F00") continue #search = Search(search_type) #search.add_interval_filter("timestamp", "today") #created_today = search.get_count() #table.add_cell(created_today) td = table.add_cell() button = IconButtonWdg(title="View", icon=IconWdg.ZOOM) td.add(button) button.add_behavior({ 'type': 'click_up', 'search_type': search_type, 'title': title, 'cbjs_action': ''' var class_name = 'tactic.ui.panel.ViewPanelWdg'; var kwargs = { search_type: bvr.search_type, view: 'table', 'simple_search_view': 'simple_search' }; // use tab var top = bvr.src_el.getParent(".spt_dashboard_top"); spt.tab.set_tab_top(top); spt.tab.add_new(bvr.title, bvr.title, class_name, kwargs); //spt.panel.load_popup(bvr.title, class_name, kwargs); ''' }) button.add_style("float: left") arrow_button = IconButtonWdg(tip="More Views", icon=IconWdg.ARROWHEAD_DARK_DOWN) arrow_button.add_style("margin-left: 20px") td.add(arrow_button) cbk = ''' var activator = spt.smenu.get_activator(bvr); var class_name = bvr.class_name; var layout = bvr.layout; var kwargs = { search_type: bvr.search_type, layout: layout, view: bvr.view, simple_search_view: 'simple_search', element_names: bvr.element_names, }; // use tab var top = activator.getParent(".spt_dashboard_top"); spt.tab.set_tab_top(top); spt.tab.add_new('%s', '%s', class_name, kwargs); ''' % (title, title) from tactic.ui.panel import SwitchLayoutMenu SwitchLayoutMenu(search_type=search_type, activator=arrow_button, cbk=cbk, is_refresh=False) td = table.add_cell() button = IconButtonWdg(title="Add", icon=IconWdg.ADD) td.add(button) button.add_behavior({ 'type': 'listen', 'search_type': search_type, 'event_name': 'startup_save:' + search_type_obj.get_title(), 'title': search_type_obj.get_title(), 'cbjs_action': ''' var top = bvr.src_el.getParent(".spt_dashboard_top"); spt.tab.set_tab_top(top); var class_name = 'tactic.ui.panel.ViewPanelWdg'; var kwargs = { search_type: bvr.search_type, view: 'table', 'simple_search_view': 'simple_search' }; spt.tab.add_new(bvr.title, bvr.title, class_name, kwargs); ''' }) button.add_behavior({ 'type': 'click_up', 'search_type': search_type, 'title': search_type_obj.get_title(), 'cbjs_action': ''' var top = bvr.src_el.getParent(".spt_dashboard_top"); spt.tab.set_tab_top(top); var class_name = 'tactic.ui.panel.EditWdg'; var kwargs = { search_type: bvr.search_type, view: "insert", save_event: "startup_save:" + bvr.title } spt.panel.load_popup("Add New Items ("+bvr.title+")", class_name, kwargs); var class_name = 'tactic.ui.panel.ViewPanelWdg'; var kwargs = { search_type: bvr.search_type, view: 'table', 'simple_search_view': 'simple_search' }; spt.tab.add_new(bvr.title, bvr.title, class_name, kwargs); ''' }) """ td = table.add_cell() button = IconButtonWdg(title="Check-in", icon=IconWdg.PUBLISH) td.add(button) button.add_behavior( { 'type': 'click_up', 'search_type': search_type, 'title': title, 'cbjs_action': ''' var class_name = 'tactic.ui.panel.ViewPanelWdg'; var kwargs = { search_type: bvr.search_type, view: 'checkin', element_names: ['preview','code','name','description','history','general_checkin','notes'] }; // use tab var top = bvr.src_el.getParent(".spt_dashboard_top"); spt.tab.set_tab_top(top); spt.tab.add_new(bvr.title, bvr.title, class_name, kwargs); //spt.panel.load_popup(bvr.title, class_name, kwargs); ''' } ) """ td = table.add_cell() button = IconButtonWdg(title="Import", icon=IconWdg.IMPORT) td.add(button) button.add_behavior({ 'type': 'click_up', 'search_type': search_type, 'title': "Import Data", 'cbjs_action': ''' var class_name = 'tactic.ui.widget.CsvImportWdg'; var kwargs = { search_type: bvr.search_type, }; spt.panel.load_popup(bvr.title, class_name, kwargs); ''' }) td = table.add_cell() button = IconButtonWdg(title="Custom Columns", icon=IconWdg.COLUMNS) td.add(button) button.add_behavior({ 'type': 'click_up', 'search_type': search_type, 'title': "Add Custom Columns", 'cbjs_action': ''' var class_name = 'tactic.ui.startup.ColumnEditWdg'; var kwargs = { search_type: bvr.search_type, }; spt.panel.load_popup(bvr.title, class_name, kwargs); ''' }) td = table.add_cell() button = IconButtonWdg(title="Workflow", icon=IconWdg.PIPELINE) button.add_style("float: left") td.add(button) search = Search("sthpw/pipeline") search.add_filter("search_type", search_type) count = search.get_count() if count: check = IconWdg("Has Items", IconWdg.CHECK, width=8) td.add(check) #check.add_style("margin-left: 0px") check.add_style("margin-top: 4px") button.add_behavior({ 'type': 'click_up', 'title': 'Workflow', 'search_type': search_type, 'cbjs_action': ''' var class_name = 'tactic.ui.startup.PipelineEditWdg'; var kwargs = { search_type: bvr.search_type }; spt.panel.load_popup(bvr.title, class_name, kwargs); ''' }) td = table.add_cell() button = IconButtonWdg(title="Notifications", icon=IconWdg.MAIL) button.add_style("float: left") td.add(button) search = Search("sthpw/notification") search.add_filter("search_type", search_type) count = search.get_count() if count: check = IconWdg("Has Items", IconWdg.CHECK, width=8) td.add(check) #check.add_style("margin-left: 0px") check.add_style("margin-top: 4px") button.add_behavior({ 'type': 'click_up', 'title': 'Trigger', 'search_type': search_type, 'cbjs_action': ''' var class_name = 'tactic.ui.tools.TriggerToolWdg'; var kwargs = { mode: "search_type", search_type: bvr.search_type }; spt.panel.load_popup(bvr.title, class_name, kwargs); ''' }) td = table.add_cell() button = IconButtonWdg(title="Triggers", icon=IconWdg.ARROW_OUT) td.add(button) button.add_style("float: left") search = Search("config/trigger") search.add_filter("search_type", search_type) count = search.get_count() if count: check = IconWdg("Has Items", IconWdg.CHECK, width=8) td.add(check) #check.add_style("margin-left: 0px") check.add_style("margin-top: 4px") button.add_behavior({ 'type': 'click_up', 'title': 'Trigger', 'search_type': search_type, 'cbjs_action': ''' var class_name = 'tactic.ui.tools.TriggerToolWdg'; var kwargs = { mode: "search_type", search_type: bvr.search_type }; spt.panel.load_popup(bvr.title, class_name, kwargs); ''' }) td = table.add_cell() button = IconButtonWdg(title="Edit Searchable Type", icon=IconWdg.EDIT) td.add(button) button.add_behavior({ 'type': 'click_up', 'search_key': search_type_obj.get_search_key(), 'cbjs_action': ''' var class_name = 'tactic.ui.panel.EditWdg'; var kwargs = { search_type: "sthpw/sobject", view: "edit_startup", search_key: bvr.search_key } spt.panel.load_popup("Edit Searchable Type", class_name, kwargs); ''' }) """ td = table.add_cell() button = IconButtonWdg(title="Security", icon=IconWdg.LOCK) td.add(button) button.add_behavior( { 'type': 'click_up', 'title': 'Trigger', 'search_type': search_type, 'cbjs_action': ''' alert("security"); ''' } ) """ columns_wdg = DivWdg() top.add(columns_wdg) return top
def get_display(self): from pyasm.biz import Project security = Environment.get_security() if not security.check_access("builtin", "side_bar_schema", "allow", default="deny"): return DivWdg() section_div = LabeledHidableWdg(label="Schema Views") section_div.set_attr('spt_class_name', Common.get_full_class_name(self) ) palette = Palette.get() color = palette.color("background3") project_div = RoundedCornerDivWdg(hex_color_code=color,corner_size="10") project_div.set_dimensions( width_str='175px', content_height_str='100px' ) project = Project.get() project_code = project.get_code() project_type = project.get_type() div = DivWdg() section_div.add(project_div) project_div.add(div) # get project type schema schema = Schema.get_by_code(project_code) if schema: div.add( self.get_schema_wdg(schema) ) #if not project_type: # raise SetupException("Project type not found for this [%s]" %project_code) if project_type: schema = Schema.get_predefined_schema(project_type) if schema: div.add( self.get_schema_wdg(schema) ) schema = Schema.get_predefined_schema('config') div.add( self.get_schema_wdg(schema) ) schema = Schema.get_admin_schema() div.add( self.get_schema_wdg(schema) ) return section_div # create a fake schema project = Project.get() db_name = project.get_database() sql = DbContainer.get(db_name) tables = sql.get_tables() tables.sort() tables_str = "\n".join( ['<search_type name="%s"/>'%x for x in tables] ) # look at all of the search objects for mapped tables search = Search("sthpw/search_object") #search.add_where('''"namespace" = 'MMS' or namespace = '{project}' ''') search.add_filter("namespace", 'MMS') search.add_filter("namespace", '{project}') search.add_where("or") search_types = search.get_sobjects() schema_xml = ''' <schema> %s </schema> ''' % tables_str schema = SearchType.create("sthpw/schema") schema.set_value("code", "table") schema.set_value("schema", schema_xml) #div.add( self.get_schema_wdg(schema) ) return section_div
def handle_sobject(my, main_sobject, command, input): search_type = main_sobject.get_search_type_obj().get_base_key() parent = None if main_sobject.has_value('search_type') and main_sobject.has_value( 'search_id'): parent = main_sobject.get_parent() if not parent: Environment.add_warning( 'Parent not found', 'Parent not found for task [%s]' % main_sobject.get_search_key()) return # the command needs to set this info if it wants to search # for the search type of its parent if command.get_info('parent_centric') == True: search_type = parent.get_search_type_obj().get_base_key() # get all of the notifications for this search_type search = Search("sthpw/notification") #search.add_where("(\"search_type\" = '%s' or \"search_type\" is NULL)"% search_type) search.add_filter("search_type", search_type) search.add_where( "(\"project_code\" = '%s' or \"project_code\" is NULL)" % Project.get().get_code()) # Basically, this selects which command this notification will be # run from. Other commands will be ignored. search.add_filter("code", my.notification_code) notifications = search.get_sobjects() # send an email for each notification that matches the rules for notification in notifications: # check if there are any recievers for this notification notification_id = notification.get_id() #logins = GroupNotification.get_logins_by_id(notification_id) #if not logins: # continue # get the rules from the database rules_xml = notification.get_xml_value("rules") rule_nodes = rules_xml.get_nodes("rules/rule") is_skipped = True for rule_node in rule_nodes: rule = [] group_type = Xml.get_attribute(rule_node, "group") rule_key = Xml.get_attribute(rule_node, 'key') rule_value = Xml.get_attribute(rule_node, 'value') compare = Xml.get_attribute(rule_node, 'compare') # parse the rule if group_type == "sobject": if not my._process_sobject(main_sobject, rule_key, compare): break value = main_sobject.get_value(rule_key, no_exception=True) elif group_type == "parent": if not parent or not my._process_sobject( parent, rule_key, compare): break value = parent.get_value(rule_key, no_exception=True) else: # group_type == 'command' value = command.get_info(rule_key) if not value: break # match the rule to the value p = re.compile(rule_value) if not p.match(value): print "... skipping: '%s' != %s" % (value, rule_value) break else: is_skipped = False # allow the handler to check for whether an email should be sent handler = my.get_email_handler(notification, main_sobject, parent, command, input) if is_skipped or not handler.check_rule(): continue # if all rules are met then get the groups for this notification try: to_users = handler.get_to() cc_users = handler.get_cc() bcc_users = handler.get_bcc() subject = handler.get_subject() if len(subject) > 60: subject = subject[0:60] + " ..." message = handler.get_message() except SObjectValueException, e: raise Exception("Error in running Email handler [%s]. %s" \ %(handler.__class__.__name__, e.__str__())) # set the email my.send(to_users, cc_users, bcc_users, subject, message) from_user = Environment.get_user_name() project_code = Project.get_project_code() # log the notification sobject = SearchType.create("sthpw/notification_log") sobject.set_value("command_cls", command.get_title()) sobject.set_user() sobject.set_value("subject", subject) sobject.set_value("message", message) sobject.set_value("project_code", project_code) sobject.commit(triggers=False) log_id = sobject.get_id() # add the recipients # log the notification for to_user in to_users: login = to_user.get_value("login") sobject = SearchType.create("sthpw/notification_login") sobject.set_value("notification_log_id", log_id) sobject.set_value("login", login) sobject.set_value("type", "to") sobject.set_value("project_code", project_code) sobject.commit(triggers=False) sobject = SearchType.create("sthpw/notification_login") sobject.set_value("notification_log_id", log_id) sobject.set_value("login", from_user) sobject.set_value("type", "from") sobject.set_value("project_code", project_code) sobject.commit(triggers=False)
def preprocess(my): my.preprocessed = True my.today = datetime.date.today() wday = int(my.today.strftime("%w")) web = WebContainer.get_web() start_date = web.get_form_value('start_date') web_data = web.get_form_value('web_data') if web_data: web_data = jsonloads(web_data) workhour_data = None if web_data: web_data = web_data[0] workhour_data = web_data.get('workhour_data') if start_date: start_date = my._get_date_obj(start_date) elif workhour_data: workhour_data = jsonloads(workhour_data) start_date = workhour_data.get('start_date') start_date = my._get_date_obj(start_date) else: if my.days_per_page < 7: start_date = my.today else: start_date = my.today - datetime.timedelta(days=wday) my.start_date = start_date end_date = start_date + datetime.timedelta(days=my.days_per_page - 1) # this may not be necessary any more """ if not my.sobjects: sk = my.kwargs.get('search_key') task = SearchKey.get_by_search_key(sk) my.sobjects = [task] """ task_codes = [x.get_code() for x in my.sobjects] search = Search("sthpw/work_hour") search.add_user_filter() search.add_filter("day", start_date, ">=") search.add_filter("day", end_date, "<=") search.add_filters("task_code", task_codes) entries = search.get_sobjects() # NOTE: # This widget assumes one entry per day. This is not the case # when time for each entry must be recorded and you may have # multiple entries per day # organize into days my.entries = {} for entry in entries: day = entry.get_value("day") if not day: continue day = parser.parse(day) day = day.strftime("%Y_%m_%d") task_code = entry.get_value("task_code") task_entries = my.entries.get(task_code) if task_entries == None: task_entries = {} my.entries[task_code] = task_entries entry_list = task_entries.get(day) if entry_list == None: entry_list = [] task_entries[day] = entry_list entry_list.append(entry) # break into 2 categories for key, sub_dict in my.entries.items(): if my.use_straight_time: for key2, entry_list in sub_dict.items(): entry_list_dict = {my.OT: [], my.ST: []} for entry in entry_list: if entry.get_value('category') == my.OT: entry_list_dict[my.OT].append(entry) elif entry.get_value('category') == my.ST: entry_list_dict[my.ST].append(entry) else: # in case they haven't run the upgrade script # (potentially include some custom-entered category) entry_list_dict[my.ST].append(entry) sub_dict[key2] = entry_list_dict else: for key2, entry_list in sub_dict.items(): entry_list_dict = {my.STT: [], my.ENT: []} for entry in entry_list: entry_list_dict[my.STT].append(entry) entry_list_dict[my.ENT].append(entry) sub_dict[key2] = entry_list_dict my.dates = list( rrule.rrule(rrule.DAILY, dtstart=start_date, until=end_date)) for idx in xrange(0, 8): my.summary_st[idx] = {} for idx in xrange(0, 8): my.summary_ot[idx] = {}