def get_sobject_info_wdg(my): attr_table = Table() attr_table.add_color("color", "color") attr_table.add_color("background", "background", -5) attr_table.add_border() attr_table.set_box_shadow("0px 0px 5px") sobject = my.get_sobject() tr, td = attr_table.add_row_cell() td.add("<b>Task Info<hr/></b>") td.add_style("padding-top: 5px") td.add_style("padding-left: 5px") titles, exprs = my.get_task_info() for title, expr in zip(titles, exprs): try: value = Search.eval(expr, sobject, single=True) except Exception, e: print "WARNING: ", e.message continue if value == '': value = '<i>none</i>' attr_table.add_row() th = attr_table.add_cell("%s: " % title) th.add_style("text-align: left") th.add_style("padding-right: 15px") th.add_style("padding-left: 5px") th.add_style("padding-bottom: 2px") td = attr_table.add_cell(value)
def get_display(self): outer_div = DivWdg() outer_div.set_id('link_components_to_packages_div') table = Table() table.add_attr('id', 'link_components_to_packages_table') table.add_style('width', '100%') table.add_border(style='solid', color='#F2F2F2', size='1px') order_code = self.order_sobject.get_code() components = get_component_sobjects_from_order_code(order_code) packages = get_package_sobjects_from_order_code(order_code) existing_component_package_links = self.get_existing_entries( components, packages) package_row = table.add_row() table.add_cell(row=package_row) for package in packages: table.add_cell(package.get('name'), row=package_row) for component in components: component_row = table.add_row() component_row.set_id(component.get_code()) table.add_cell(component.get('name'), row=component_row) for package in packages: checkbox = CheckboxWdg(name='{0}_{1}'.format( component.get_code(), package.get_code())) if self.component_package_link_exists( component, package, existing_component_package_links): checkbox.set_checked() checkbox_cell = table.add_cell(checkbox) checkbox_cell.add_style('text-align', 'center') outer_div.add(table) submit_button = SubmitWdg('Submit') submit_button.add_behavior(self.get_submit_button_behavior()) outer_div.add(submit_button) return outer_div
def get_display(self): outer_div = DivWdg() outer_div.set_id('link_components_to_packages_div') table = Table() table.add_attr('id', 'link_components_to_packages_table') table.add_style('width', '100%') table.add_border(style='solid', color='#F2F2F2', size='1px') order_code = self.order_sobject.get_code() components = get_component_sobjects_from_order_code(order_code) packages = get_package_sobjects_from_order_code(order_code) existing_component_package_links = self.get_existing_entries(components, packages) package_row = table.add_row() table.add_cell(row=package_row) for package in packages: table.add_cell(package.get('name'), row=package_row) for component in components: component_row = table.add_row() component_row.set_id(component.get_code()) table.add_cell(component.get('name'), row=component_row) for package in packages: checkbox = CheckboxWdg(name='{0}_{1}'.format(component.get_code(), package.get_code())) if self.component_package_link_exists(component, package, existing_component_package_links): checkbox.set_checked() checkbox_cell = table.add_cell(checkbox) checkbox_cell.add_style('text-align', 'center') outer_div.add(table) submit_button = SubmitWdg('Submit') submit_button.add_behavior(self.get_submit_button_behavior()) outer_div.add(submit_button) return outer_div
def get_category_wdg(self, category, mode="new"): subscriptions = self.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 = self.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 = self.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 = self.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 = self.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_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") div.add(button) 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 = Table() table.add_style('width: 100%') table.add_border() table.add_color("background", "background3") 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 msg_element = FormatMessageWdg(subscription=subscription, short_format='true') # 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 = "" td.add(timestamp_str) #td = table.add_cell() #td.add(subscription.get_value("last_cleared")) td = table.add_cell() td.add(history_icon) td.add(HtmlElement.br(2)) td.add_style('width: 30px') icon = IconButtonWdg(title="Unsubscribe", icon=IconWdg.DELETE) td.add(icon) 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); ''' } ) 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
widget.add(HtmlElement.br()) table_div = DivWdg() widget.add(table_div) table_div.add_style("max-width: 650px") table_div.add_style("overflow-x: auto") # draw the actual table of data table = Table() table_div.add(table) table.add_color('background','background') table.add_color('color','color') table.add_border() table.set_attr("cellpadding", "3") #table.add_attr('border','1') table.add_style("width: 100%") table.add_row() for i, title in enumerate(columns): if not title: title = "<b style='color:red'>*</b>" th = table.add_header(title) th.add_style("min-width: 100px") th.add_gradient("background", "background", -5) th.add_style("padding: 3px") th.add_style("text-align: left")
def get_display(self): table = Table() table.add_attr('id', 'bigboard') table.add_style('width', '100%') table.add_style('background-color', '#FCFCFC') table.add_style('font-size', '12px') table.add_style('font-family', 'Helvetica') table.add_border(style='solid', color='#F2F2F2', size='1px') # Because Tactic doesn't allow for the <thead> element (that I know of), the table header has to be split # into it's own <tbody>. Highly inelegant, but I don't have a choice. header_body = table.add_tbody() header_body.add_style('display', 'block') header_body.add_attr('id', 'thead-section') # Get the titles that fall under 'external rejection' (they need to be on the top of the board) search_for_external_rejections = Search('twog/title') search_for_external_rejections.add_filter('is_external_rejection', 'true') external_rejections_sobjects = search_for_external_rejections.get_sobjects() external_rejections = [hot_item for hot_item in external_rejections_sobjects if hot_item.get_value('status') != 'Completed'] search_in_external_rejection_database = Search('twog/external_rejection') search_in_external_rejection_database.add_filter('status', 'Open') external_rejection_title_codes = [item.get_value('title_code') for item in search_in_external_rejection_database.get_sobjects()] external_rejection_title_codes = [code for code in external_rejection_title_codes if code not in [item.get_value('code') for item in external_rejections]] search_for_external_rejection_extra_titles = Search('twog/title') search_for_external_rejection_extra_titles.add_filters('code', external_rejection_title_codes) external_rejections.extend([item for item in search_for_external_rejection_extra_titles.get_sobjects()]) # Search for titles that are marked as 'hot' search_for_hot_items = Search('twog/title') search_for_hot_items.add_filter('bigboard', True) search_for_hot_items.add_filter('is_external_rejection', 'false') search_for_hot_items.add_order_by('priority') search_for_hot_items.add_order_by('expected_delivery_date') hot_items_sobjects = search_for_hot_items.get_sobjects() hot_items = [hot_item for hot_item in hot_items_sobjects if hot_item.get_value('status') != 'Completed'] # The database query for tasks will fail if there are no external rejections being passed in, causing the # whole hotlist to crash. This if/else prevents that. if external_rejections: external_rejection_tasks = self.get_tasks(external_rejections) else: external_rejection_tasks = [] tasks = self.get_tasks(hot_items) # Current priority will be updated each time a title has a different priority from the last value current_priority = 0 title_counter = 1 # Get a list of all the users allowed to change priorities on the list. Only they will be able to see # the input box to change priority. is_admin_user = False admin_search = Search("twog/global_resource") admin_search.add_filter('name', 'Usernames Allowed Hot Today Changes') admin_search_object = admin_search.get_sobject() if admin_search_object: # The users allowed to make priority changes are stored in the 'description' section of this sobject, # in a comma separated list admin_users = admin_search_object.get_value('description').split(',') # Check if current user is in the list (no idea why you need get_login twice, but it doesn't work otherwise) if Environment.get_login().get_login() in admin_users: is_admin_user = True # 'title' is also in the headers, but since that always displays we'll leave it out here header_groups = self.get_header_groups(tasks) self.set_header(table, header_groups) hotlist_body = table.add_tbody() hotlist_body.add_style('display', 'block') hotlist_body.add_style('overflow-x', 'hidden') hotlist_body.add_style('overflow-y', 'scroll') hotlist_body.add_style('height', '850px') hotlist_body.add_style('width', '100%') hotlist_body.add_attr('id', 'hotlist-body') dictionary_of_tasks = {} dictionary_of_external_rejection_tasks = {} for task in external_rejection_tasks: task_title_code = task.get_value('title_code') task_header = task.get_value('assigned_login_group') if task_title_code not in dictionary_of_external_rejection_tasks.keys(): dictionary_of_external_rejection_tasks[task_title_code] = {task_header: None} if not dictionary_of_external_rejection_tasks[task_title_code].get(task_header): dictionary_of_external_rejection_tasks[task_title_code][task_header] = [task] else: dictionary_of_external_rejection_tasks[task_title_code][task_header].append(task) for task in tasks: task_title_code = task.get_value('title_code') task_header = task.get_value('assigned_login_group') if task_title_code not in dictionary_of_tasks.keys(): dictionary_of_tasks[task_title_code] = {task_header: None} if not dictionary_of_tasks[task_title_code].get(task_header): dictionary_of_tasks[task_title_code][task_header] = [task] else: dictionary_of_tasks[task_title_code][task_header].append(task) # Put external rejections on the board first for external_rejection in external_rejections: item_tasks = dictionary_of_external_rejection_tasks.get(external_rejection.get_value('code')) self.set_row(external_rejection, table, title_counter, header_groups, item_tasks, current_priority, is_admin_user, True) title_counter += 1 for hot_item in hot_items: hot_item_priority = float(hot_item.get_value('priority')) # Get the tasks that correspond to a title by comparing the task's title_code to the title's code # item_tasks = (task for task in tasks if task.get_value('title_code') == hot_item.get_value('code')) item_tasks = dictionary_of_tasks.get(hot_item.get_value('code')) # If an item requires QC Mastering, it should go on the hot board, regardless of if it has tasks or not requires_mastering_qc = hot_item.get_value('requires_mastering_qc', False) if item_tasks or requires_mastering_qc: if current_priority < hot_item_priority: self.set_priority_row(table, hot_item_priority) current_priority = hot_item_priority self.set_row(hot_item, table, title_counter, header_groups, item_tasks, current_priority, is_admin_user) title_counter += 1 # Put the table in a DivWdg, makes it fit better with the Tactic side bar hotlist_div = DivWdg() hotlist_div.add_attr('id', 'hotlist_div') hotlist_div.add_style('height', '900px') hotlist_div.add_attr('overflow', 'hidden') hotlist_div.add(table) # Add an 'outer' div that holds the hotlist div, with the buttons below. outer_div = DivWdg() outer_div.add(hotlist_div) outer_div.add(self.get_buttons(is_admin_user)) outer_div.add_behavior(get_scrollbar_width()) return outer_div
def get_display(my): search_key = my.kwargs.get("search_key") path = my.kwargs.get("path") parser_str = my.kwargs.get("parser") use_tactic_tags = my.kwargs.get("use_tactic_tags") from pyasm.checkin import PILMetadataParser, ImageMagickMetadataParser, ExifMetadataParser, BaseMetadataParser if parser_str: parser = BaseMetadataParser.get_parser(parser_str, path) else: parser = BaseMetadataParser.get_parser_by_path(path) if parser: if use_tactic_tags in ['true', True]: metadata = parser.get_tactic_metadata() else: metadata = parser.get_metadata() else: metadata = {} top = my.top top.add_color("background", "background") table = Table() table.set_max_width() top.add(table) table.set_unique_id() table.add_border() table.add_smart_styles("spt_cell", { 'padding': '3px' } ) tr = table.add_row() tr.add_gradient("background", "background3") th = table.add_header("Property") th.add_style("min-width: 200px") th.add_style("padding: 5px") th = table.add_header("Value") th.add_style("min-width: 400px") th.add_style("padding: 5px") keys = metadata.get("__keys__") if not keys: keys = metadata.keys() empty = False if not keys: empty = True keys = ['','','','','','',''] table.add_smart_styles("spt_cell", { 'height': '20px' } ) for i, key in enumerate(keys): value = metadata.get(key) title = Common.get_display_title(key) tr = table.add_row() if i % 2: tr.add_color("background", "background") tr.add_color("color", "color") else: tr.add_color("background", "background", -8) tr.add_color("color", "color") td = table.add_cell() td.add_class("spt_cell") td.add(title) td = table.add_cell() td.add_class("spt_cell") if len(str(value)) > 500: inside = DivWdg() td.add(inside) value = value[:500] inside.add(value) inside.add_style("max-width: 600px") else: td.add(value) if empty: div = DivWdg() top.add(div) div.add_style("height: 30px") div.add_style("width: 150px") div.add_style("margin-top: -110px") div.center() div.add("<b>No Metadata</b>") div.add_border() div.add_color("background", "background3") div.add_color("color", "color3") div.add_style("padding: 20px") div.add_style("text-align: center") top.add_style("min-height: 200px") return top
def get_display(self): top = DivWdg() name = self.get_name() top.add_class("spt_note_input_top") context = self.get_option("context") if not context: context = name sobject = self.get_option("sobject") if not sobject: search_key = self.get_option("search_key") sobject = Search.get_by_search_key(search_key) else: search_key = sobject.get_search_key() if search_key or (sobject and not sobject.is_insert()): search = Search("sthpw/note") #search.add_relationship_filters(self.filtered_parents, type='hierarchy') search.add_parent_filter(sobject) search.add_filter("context", context) search.add_order_by("process") search.add_order_by("context") search.add_order_by("timestamp desc") search.add_filter("context", context) count = search.get_count() last_note = search.get_sobject() else: last_note = None count = 0 #if not last_note: # last_note = SearchType.create("sthpw/note") # last_note.set_value("login", "") # last_note.set_value("timestamp", "") # last_note.set_value("note", "") if last_note: last_div = DivWdg() top.add(last_div) table = Table() table.add_style("width: 100%") table.add_attr("cellpadding", "0px") table.add_attr("cellspacing", "0px") last_div.add(table) table.add_row() td = table.add_cell() td.add_style("vertical-align: top") td.add_style("padding: 5px 15px 10px 5px") table.add_border() table.add_color("background", "background", -5) note_str = last_note.get_value("note") login = last_note.get_value("login") if not login: login = "******" date = last_note.get_datetime_value("timestamp") if date: date_str = "<i style='font-size: 0.8em'>%s</i>" % date.strftime("%Y-%m-%d") else: date_str = "" login = "******" % login td.add("%s - %s<br/>" % (date_str, login)) note_str_div = DivWdg() note_str_div.add(note_str) note_str_div.add_style("padding: 10px 15px 10px 10px") #td = table.add_cell( note_str_div ) td.add( note_str_div ) #td.add_style("vertical-align: top") #td.add_style("padding: 10px 15px 10px 10px") """ td.add_behavior( { 'type': 'click_up', 'cbjs_action': ''' var top = bvr.src_el.getParent(".spt_note_input_top"); var text_el = top.getElement(".spt_add_entry"); text_el.setStyle("display", ""); ''' } ) """ # log if count == 0: td = table.add_cell( "" ) elif count == 1: td = table.add_cell( "<i style='font-size: 0.8em'>More...><br/>(%s entry)</i>" % count ) else: td = table.add_cell( "<i style='font-size: 0.8em'>More...><br/>(%s entries)</i>" % count ) td.add_style("vertical-align: top") td.add_style("padding: 3px") td.add_class("hand") td.add_behavior( { 'type': 'click_up', 'search_key': search_key, 'context': context, 'cbjs_action': ''' var class_name = 'tactic.ui.input.note_input_wdg.NoteHistoryWdg'; var kwargs = { search_key: bvr.search_key, context: bvr.context } spt.panel.load_popup("Notes Log", class_name, kwargs); ''' } ) name = self.get_input_name() text = TextAreaWdg(name) top.add(text) text.add_style("width: 100%") text.add_class("spt_add_entry") """ if search_key and not sobject.is_insert(): from tactic.ui.widget import DiscussionWdg discussion_wdg = DiscussionWdg(search_key=search_key, context_hidden=False, show_note_expand=False, show_add=False) top.add(discussion_wdg) """ return top
class ResizableTableWdg(BaseRefreshWdg): def __init__(self, **kwargs): self.table = Table() self.table.add_style("border-collapse: collapse") self.table.add_style("padding: 0px") self.table.set_attr("cellpadding", "0px") self.table.set_attr("cellspacing", "0px") self.is_first_row = True self.hilight = self.table.get_color("background", -40) super(ResizableTableWdg, self).__init__(**kwargs) def set_style(self, name, value=None): self.table.set_style(name, value) def set_max_width(self): self.table.set_max_width() def add_class(self, name): self.table.add_class(name) def get_display(self): top = self.top self.table.add_class("spt_resizable_table_top") self.table.add_behavior( { 'type': 'load', 'cbjs_action': self.get_onload_js() } ) self.table.add_behavior( { 'type': 'load', 'cbjs_action': ''' var resizable_cells = bvr.src_el.getElements(".spt_resizable_cell"); for (var i = 0; i < resizable_cells.length; i++) { var resizable_el = resizable_cells[i].getElement(".spt_resizable"); if (!resizable_el) { continue; } var size = resizable_cells[i].getSize(); resizable_el.setStyle("width", size.x); resizable_el.setAttribute("width", size.x); } ''' } ) top.add(self.table) return top def set_keep_table_size(self): self.table.add_class("spt_resizable_keep_size") def add_color(self, color, modifier=0): self.table.add_color(color, modifier) def add_border(self, modifier=0): self.table.add_border(modifier=modifier) def add_style(self, name, value=None): self.table.add_style(name, value=value) def add_row(self, resize=True): # add resize row if not self.is_first_row and resize == True: tr, td = self.table.add_row_cell() td.add_style("height: 3px") td.add_style("min-height: 3px") td.add_style("cursor: n-resize") tr.add_behavior( { 'type': 'drag', 'cb_set_prefix': 'spt.resizable_table.row_drag' } ) tr.add_behavior( { 'type': 'hover', 'hilight': self.hilight, 'cbjs_action_over': ''' var color = bvr.src_el.getStyle("background-color"); bvr.src_el.setStyle("background-color", bvr.hilight); bvr.src_el.setAttribute("spt_last_background", color); ''', 'cbjs_action_out': ''' var color = bvr.src_el.getAttribute("spt_last_background"); bvr.src_el.setStyle("background-color", color); ''' } ) icon = IconWdg("Drag to Resize", IconWdg.RESIZE_VERTICAL) td.add(icon) td.add_style("text-align: center") content_tr = self.table.add_row() self.is_first_row = False return content_tr def add_resize_row(self): tr, td = self.table.add_row_cell() td.add_style("height: 3px") td.add_style("min-height: 3px") td.add_style("cursor: n-resize") tr.add_behavior( { 'type': 'drag', 'cb_set_prefix': 'spt.resizable_table.row_drag' } ) tr.add_behavior( { 'type': 'hover', 'hilight': self.hilight, 'cbjs_action_over': ''' var color = bvr.src_el.getStyle("background-color"); bvr.src_el.setStyle("background-color", bvr.hilight); bvr.src_el.setAttribute("spt_last_background", color); ''', 'cbjs_action_out': ''' var color = bvr.src_el.getAttribute("spt_last_background"); bvr.src_el.setStyle("background-color", color); ''' } ) icon = IconWdg("Drag to Resize", IconWdg.RESIZE_VERTICAL) td.add(icon) return tr, td def add_cell(self, widget=None, resize=True, rowspan=1, colspan=1): td_content = self.table.add_cell() td_content.add_style("vertical-align: top") td_content.add_class("spt_resizable_cell") if rowspan > 1: td_content.add_attr("rowspan", rowspan+1) if colspan > 1: td_content.add_attr("colspan", colspan+1) if not resize: return td_content # add resize cell td = self.table.add_cell() td.add_style("width: 4px") td.add_style("min-width: 4px") td.add_style("cursor: e-resize") icon_div = DivWdg() icon_div.add_style("width: 4px") icon_div.add_style("overflow: hidden") icon = IconWdg("Drag to Resize", IconWdg.RESIZE_HORIZ) icon_div.add(icon) td.add(icon_div) td.add_style("vertical-align: middle") td.add_behavior( { 'type': 'drag', 'cb_set_prefix': 'spt.resizable_table.cell_drag' } ) td.add_behavior( { 'type': 'hover', 'hilight': self.hilight, 'cbjs_action_over': ''' var color = bvr.src_el.getStyle("background-color"); bvr.src_el.setStyle("background-color", bvr.hilight); bvr.src_el.setAttribute("spt_last_background", color); ''', 'cbjs_action_out': ''' var color = bvr.src_el.getAttribute("spt_last_background"); bvr.src_el.setStyle("background-color", color); ''' } ) if rowspan > 1: td.add_attr("rowspan", rowspan+1) if colspan > 1: td.add_attr("colspan", colspan+1) if widget: td_content.add(widget) return td_content def get_onload_js(self): return r'''
def get_display(my): search_key = my.kwargs.get("search_key") path = my.kwargs.get("path") parser_str = my.kwargs.get("parser") use_tactic_tags = my.kwargs.get("use_tactic_tags") from pyasm.checkin import PILMetadataParser, ImageMagickMetadataParser, ExifMetadataParser, BaseMetadataParser if parser_str: parser = BaseMetadataParser.get_parser(parser_str, path) else: parser = BaseMetadataParser.get_parser_by_path(path) if parser: if use_tactic_tags in ['true', True]: metadata = parser.get_tactic_metadata() else: metadata = parser.get_metadata() else: metadata = {} top = my.top top.add_color("background", "background") table = Table() table.set_max_width() top.add(table) table.set_unique_id() table.add_border() table.add_smart_styles("spt_cell", {'padding': '3px'}) tr = table.add_row() tr.add_gradient("background", "background3") th = table.add_header("Property") th.add_style("min-width: 200px") th.add_style("padding: 5px") th = table.add_header("Value") th.add_style("min-width: 400px") th.add_style("padding: 5px") keys = metadata.get("__keys__") if not keys: keys = metadata.keys() empty = False if not keys: empty = True keys = ['', '', '', '', '', '', ''] table.add_smart_styles("spt_cell", {'height': '20px'}) for i, key in enumerate(keys): value = metadata.get(key) title = Common.get_display_title(key) tr = table.add_row() if i % 2: tr.add_color("background", "background") tr.add_color("color", "color") else: tr.add_color("background", "background", -8) tr.add_color("color", "color") td = table.add_cell() td.add_class("spt_cell") td.add(title) td = table.add_cell() td.add_class("spt_cell") if len(str(value)) > 500: inside = DivWdg() td.add(inside) value = value[:500] inside.add(value) inside.add_style("max-width: 600px") else: td.add(value) if empty: div = DivWdg() top.add(div) div.add_style("height: 30px") div.add_style("width: 150px") div.add_style("margin-top: -110px") div.center() div.add("<b>No Metadata</b>") div.add_border() div.add_color("background", "background3") div.add_color("color", "color3") div.add_style("padding: 20px") div.add_style("text-align: center") top.add_style("min-height: 200px") return top
def get_display(my): search_type_obj = SearchType.get(my.search_type) sobj_title = search_type_obj.get_title() top_div = DivWdg() if not my.is_refresh: my.set_as_panel(top_div) content_div = DivWdg() content_div.add_class("spt_edit_top") content_div.set_attr("spt_search_key", my.search_key) # add close listener # FIXME: this is an absolute search, but is here for backwards # compatibility content_div.add_named_listener('close_EditWdg', ''' var popup = bvr.src_el.getParent( ".spt_popup" ); if (popup) spt.popup.close(popup); ''') attrs = my.config.get_view_attributes() default_access = attrs.get("access") if not default_access: default_access = "edit" project_code = Project.get_project_code() security = Environment.get_security() base_key = search_type_obj.get_base_key() key = { 'search_type': base_key, 'project': project_code } access = security.check_access("sobject", key, "edit", default=default_access) if not access: my.is_disabled = True else: my.is_disabled = False disable_wdg = None if my.is_disabled: # TODO: This overlay doesn't work in IE, size, position, # and transparency all fail. disable_wdg = DivWdg(id='edit_wdg') disable_wdg.add_style("position: absolute") disable_wdg.add_style("height: 90%") disable_wdg.add_style("width: 100%") disable_wdg.add_style("left: 0px") #disable_wdg.add_style("bottom: 0px") #disable_wdg.add_style("top: 0px") disable_wdg.add_style("opacity: 0.2") disable_wdg.add_style("background: #fff") #disable_wdg.add_style("-moz-opacity: 0.2") disable_wdg.add_style("filter: Alpha(opacity=20)") disable_wdg.add("<center>EDIT DISABLED</center>") content_div.add(disable_wdg) attrs = my.config.get_view_attributes() inner = DivWdg() content_div.add(inner) menu = my.get_header_context_menu() menus = [menu.get_data()] menus_in = { 'HEADER_CTX': menus, } SmartMenu.attach_smart_context_menu( inner, menus_in, False ) table = Table() inner.add(table) table.add_color("background", "background") table.add_border() table.add_color("color", "color") width = attrs.get('width') if not width: width = my.kwargs.get("width") if not width: width = 500 table.add_style("width: %s" % width) height = attrs.get('height') if height: table.add_style("height: %s" % height) tr = table.add_row() #tr.add_border() my.add_header(table, sobj_title) single = my.kwargs.get("single") if single in ['false', False] and my.mode == 'insert': multi_div = DivWdg() multi_div.add_style("text-align: left") multi_div.add("Specify the number of items that will be added with this form:<br/><br/>") multi_div.add("<b># of new items to add: </b>") multi_div.add(" "*4) multi_text = TextWdg("multiplier") multi_text.add_style("width: 30px") multi_div.add(multi_text) tr, td = table.add_row_cell( multi_div ) td.add_color("border-color", "table_border", default="border") td.add_style("border-width: 1px") td.add_style("border-style: solid") td.add_style("padding: 8 3 8 3") td.add_color("background", "background3") td.add_color("color", "color3") security = Environment.get_security() # break the widgets up in columns num_columns = attrs.get('num_columns') if not num_columns: num_columns = my.kwargs.get('num_columns') if not num_columns: num_columns = 1 else: num_columns = int(num_columns) # go through each widget and draw it for i, widget in enumerate(my.widgets): # since a widget name called code doesn't necessariy write to code column, it is commented out for now """ key = { 'search_type' : search_type_obj.get_base_key(), 'column' : widget.get_name(), 'project': project_code} # check security on widget if not security.check_access( "sobject_column",\ key, "edit"): my.skipped_element_names.append(widget.get_name()) continue """ if not hasattr(widget, 'set_input_prefix'): msg = DivWdg("Warning: The widget definition for [%s] uses [%s] and is not meant for use in Edit Layout. Please revise the edit_definition in widget config."% (widget.get_name(), widget.__class__.__name__ )) msg.add_style('color: orange') content_div.add(msg) content_div.add(HtmlElement.br()) continue """ raise TacticException('The widget definition for [%s] uses [%s] and is not meant for use in Edit. Please revise the definition in widget config'% (widget.__class__.__name__, widget.get_name())) """ if my.input_prefix: widget.set_input_prefix(my.input_prefix) if isinstance(widget, HiddenWdg): content_div.add(widget) continue # Set up any validations configured on the widget ... from tactic.ui.app import ValidationUtil v_util = ValidationUtil( widget=widget ) v_bvr = v_util.get_validation_bvr() if v_bvr: if (isinstance(widget, CalendarInputWdg)): widget.set_validation( v_bvr.get('cbjs_validation'), v_bvr.get('validation_warning') ); else: widget.add_behavior( v_bvr ) widget.add_behavior( v_util.get_input_onchange_bvr() ) new_row = i % num_columns == 0 if new_row: tr = table.add_row() if i % 2 == 0: tr.add_color("background", "background") else: tr.add_color("background", "background", -5) show_title = (widget.get_option("show_title") != "false") if show_title: title = widget.get_title() td = table.add_cell(title) td.add_style("padding: 10px 15px 10px 5px") td.add_style("vertical-align: top") security = Environment.get_security() if security.check_access("builtin", "view_site_admin", "allow"): SmartMenu.assign_as_local_activator( td, 'HEADER_CTX' ) #td.add_color("background", "background", -12) td.add_style("width: 100px") td.add_color("border-color", "table_border", default="border") td.add_style("border-width: 1" ) td.add_style("border-style: solid" ) td.add_style("text-align: right" ) if not show_title: th, td = table.add_row_cell( widget ) #td.add_border() continue else: td = table.add_cell( widget ) #td = table.add_cell( widget.get_value() ) td.add_style("min-width: 300px") td.add_style("padding: 10px 15px 10px 5px") td.add_style("vertical-align: top") td.add_color("border-color", "table_border", default="border") td.add_style("border-width: 1" ) td.add_style("border-style: solid" ) hint = widget.get_option("hint") if hint: table.add_data( HintWdg(hint) ) if not my.is_disabled and not my.mode == 'view': tr, td = table.add_row_cell( my.get_action_html() ) if my.input_prefix: prefix = HiddenWdg("input_prefix", my.input_prefix) tr, td = table.add_row_cell() td.add(prefix) top_div.add(content_div) return top_div
def get_display(self): top = DivWdg() name = self.get_name() top.add_class("spt_note_input_top") context = self.get_option("context") if not context: context = name sobject = self.get_option("sobject") if not sobject: search_key = self.get_option("search_key") sobject = Search.get_by_search_key(search_key) else: search_key = sobject.get_search_key() if search_key or (sobject and not sobject.is_insert()): search = Search("sthpw/note") #search.add_relationship_filters(self.filtered_parents, type='hierarchy') search.add_parent_filter(sobject) search.add_filter("context", context) search.add_order_by("process") search.add_order_by("context") search.add_order_by("timestamp desc") search.add_filter("context", context) count = search.get_count() last_note = search.get_sobject() else: last_note = None count = 0 #if not last_note: # last_note = SearchType.create("sthpw/note") # last_note.set_value("login", "") # last_note.set_value("timestamp", "") # last_note.set_value("note", "") if last_note: last_div = DivWdg() top.add(last_div) table = Table() table.add_style("width: 100%") table.add_attr("cellpadding", "0px") table.add_attr("cellspacing", "0px") last_div.add(table) table.add_row() td = table.add_cell() td.add_style("vertical-align: top") td.add_style("padding: 5px 15px 10px 5px") table.add_border() table.add_color("background", "background", -5) note_str = last_note.get_value("note") login = last_note.get_value("login") if not login: login = "******" date = last_note.get_datetime_value("timestamp") if date: date_str = "<i style='font-size: 0.8em'>%s</i>" % date.strftime( "%Y-%m-%d") else: date_str = "" login = "******" % login td.add("%s - %s<br/>" % (date_str, login)) note_str_div = DivWdg() note_str_div.add(note_str) note_str_div.add_style("padding: 10px 15px 10px 10px") #td = table.add_cell( note_str_div ) td.add(note_str_div) #td.add_style("vertical-align: top") #td.add_style("padding: 10px 15px 10px 10px") """ td.add_behavior( { 'type': 'click_up', 'cbjs_action': ''' var top = bvr.src_el.getParent(".spt_note_input_top"); var text_el = top.getElement(".spt_add_entry"); text_el.setStyle("display", ""); ''' } ) """ # log if count == 0: td = table.add_cell("") elif count == 1: td = table.add_cell( "<i style='font-size: 0.8em'>More...><br/>(%s entry)</i>" % count) else: td = table.add_cell( "<i style='font-size: 0.8em'>More...><br/>(%s entries)</i>" % count) td.add_style("vertical-align: top") td.add_style("padding: 3px") td.add_class("hand") td.add_behavior({ 'type': 'click_up', 'search_key': search_key, 'context': context, 'cbjs_action': ''' var class_name = 'tactic.ui.input.note_input_wdg.NoteHistoryWdg'; var kwargs = { search_key: bvr.search_key, context: bvr.context } spt.panel.load_popup("Notes Log", class_name, kwargs); ''' }) name = self.get_input_name() text = TextAreaWdg(name) top.add(text) text.add_style("width: 100%") text.add_class("spt_add_entry") """ if search_key and not sobject.is_insert(): from tactic.ui.widget import DiscussionWdg discussion_wdg = DiscussionWdg(search_key=search_key, context_hidden=False, show_note_expand=False, show_add=False) top.add(discussion_wdg) """ return top
def get_display(self): table = Table() table.add_attr('id', 'hot_today') table.add_style('width', '100%') table.add_style('background-color', '#FCFCFC') table.add_style('font-size', '12px') table.add_style('font-family', 'Helvetica') table.add_border(style='solid', color='#F2F2F2', size='1px') # Because Tactic doesn't allow for the <thead> element (that I know of), the table header has to be split # into it's own <tbody>. Highly inelegant, but I don't have a choice. header_body = table.add_tbody() header_body.add_attr('id', 'thead-section') # Initialize the Tactic server server = TacticServerStub.get() # Get today's date as a string todays_date = datetime.datetime.today() due_date_string = todays_date.strftime('%Y-%m-%d') # Search for orders that are either due today or are past due. orders_due_today_or_earlier_list = server.eval( "@SOBJECT(twog/order['due_date', 'is before', '{0}']['@ORDER_BY', 'due_date asc'])".format( due_date_string)) orders_due_today_or_earlier_not_complete_list = [ order for order in orders_due_today_or_earlier_list if order.get('status') != 'complete' ] components_list = self.get_component_or_package_list(orders_due_today_or_earlier_not_complete_list, 'twog/component') packages_list = self.get_component_or_package_list(orders_due_today_or_earlier_not_complete_list, 'twog/package') task_list = self.get_tasks_for_search_type(components_list, 'twog/component?project=twog') task_list.extend(self.get_tasks_for_search_type(packages_list, 'twog/package?project=twog')) header_groups = self.get_header_groups(task_list) # Get the header groups as a sorted set header_groups = self.sort_header_groups(header_groups) self.set_header(table, header_groups) hotlist_body = table.add_tbody() hotlist_body.add_style('display', 'table') hotlist_body.add_style('overflow-x', 'hidden') hotlist_body.add_style('overflow-y', 'scroll') hotlist_body.add_style('height', '850px') hotlist_body.add_style('width', '100%') hotlist_body.add_attr('id', 'hotlist-body') dictionary_of_tasks = {} for task in task_list: order_sobject = get_order_sobject_from_task_sobject(task) order_code = order_sobject.get_code() process_name = task.get('process') if len(process_name.split(':')) > 1: task_header = process_name.split(':')[0] if order_code not in dictionary_of_tasks.keys(): dictionary_of_tasks[order_code] = {task_header: None} if not dictionary_of_tasks[order_code].get(task_header): dictionary_of_tasks[order_code][task_header] = [task] else: dictionary_of_tasks[order_code][task_header].append(task) counter = 1 for hot_item in orders_due_today_or_earlier_not_complete_list: # Get the tasks that correspond to a title by comparing the task's title_code to the title's code item_tasks = dictionary_of_tasks.get(hot_item.get('code')) if item_tasks: self.set_row(hot_item, table, counter, header_groups, item_tasks) counter += 1 # Put the table in a DivWdg, makes it fit better with the Tactic side bar hotlist_div = DivWdg() hotlist_div.add_attr('id', 'hotlist_div') hotlist_div.add_attr('overflow', 'hidden') hotlist_div.add(table) # Add an 'outer' div that holds the hotlist div, with the buttons below. outer_div = DivWdg() outer_div.add(hotlist_div) outer_div.add_behavior(get_scrollbar_width()) return outer_div
def get_display(self): search_key = self.kwargs.get("search_key") snapshot = self.kwargs.get("snapshot") if snapshot: self.snapshot = snapshot else: self.snapshot = SearchKey.get_by_search_key(search_key) assert self.snapshot metadata = self.snapshot.get_metadata() top = self.top top.add_color("background", "background") table = Table() table.set_max_width() top.add(table) table.set_unique_id() table.add_border() table.add_smart_styles("spt_cell", {'padding': '3px'}) tr = table.add_row() tr.add_color("background", "background", -5) th = table.add_header("Property") th.add_style("min-width: 200px") th.add_style("padding: 5px") th = table.add_header("Value") th.add_style("min-width: 400px") th.add_style("padding: 5px") keys = metadata.get("__keys__") if not keys: keys = metadata.keys() empty = False if not keys: empty = True keys = ['', '', '', '', '', '', ''] table.add_smart_styles("spt_cell", {'height': '20px'}) for i, key in enumerate(keys): value = metadata.get(key) title = Common.get_display_title(key) tr = table.add_row() if i % 2: tr.add_color("background", "background") tr.add_color("color", "color") else: tr.add_color("background", "background", -8) tr.add_color("color", "color") td = table.add_cell() td.add_class("spt_cell") td.add(title) td = table.add_cell() td.add_class("spt_cell") td.add(value) if empty: div = DivWdg() top.add(div) div.add_style("height: 30px") div.add_style("width: 150px") div.add_style("margin-top: -110px") div.center() div.add("<b>No Metadata</b>") div.add_border() div.add_color("background", "background3") div.add_color("color", "color3") div.add_style("padding: 20px") div.add_style("text-align: center") top.add_style("min-height: 200px") return top
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") div.add(button) 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 = Table() table.add_style("width: 100%") table.add_border() table.add_color("background", "background3") 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(my.get_preview_wdg(subscription)) td = table.add_cell() td.add("No Messages") continue size = 60 category = message.get_value("category") td = table.add_cell() td.add( my.get_preview_wdg(subscription) ) #td = table.add_cell(message_code) message_value = message.get_value("message") if message_value.startswith("{") and message_value.endswith("}"): # FIXME: this is needed because the json has some bad # \\ issues. message_value = message_value.replace(r"\\", "\\"); message_value = jsonloads(message_value) update_data = message_value.get("update_data") if category == "sobject": search_type = message_value.get("search_type") if search_type == "sthpw/note": description = "<b>Note Added:</b><br/>%s" % update_data.get("note") elif search_type == "sthpw/task": description = "<b>Task modified:</b><br/>%s" % update_data.get("process") elif search_type == "sthpw/snapshot": sobject = message_value.get("sobject") description = "<b>Files Checked In:</b><br/>%s" % sobject.get("process") else: description = "<b>Data modified:</b><br/>%s" % update_data else: description = message_value.get("description") else: if category == "chat": login = message.get("login") timestamp = message.get("timestamp") message_value = message.get("message") message_value = message_value.replace("\n", "<br/>") description = ''' <b>%s</b><br/> %s ''' % (login, message_value) else: description = message_value td = table.add_cell() icon = IconButtonWdg(title="Subscription History", icon=IconWdg.HISTORY) td.add(icon) subscription_key = subscription.get_search_key() message_code = subscription.get_value("message_code") 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; alert(message_code); var kwargs = { search_type: 'sthpw/message_log', show_shelf: false, expression: "@SOBJECT(sthpw/message_log['message_code','"+message_code+"'])", }; spt.tab.set_main_body_tab(); spt.tab.add_new("Message History", "Message History", class_name, kwargs); ''' } ) td = table.add_cell() desc_div = DivWdg() td.add(desc_div) desc_div.add(description) desc_div.add_style("padding: 0px 20px") desc_div.add_style("max-width: 600px") 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 = "" td.add(timestamp_str) #td = table.add_cell() #td.add(subscription.get_value("last_cleared")) td = table.add_cell() icon = IconButtonWdg(title="Unsubscribe", icon=IconWdg.DELETE) td.add(icon) subscription_key = subscription.get_search_key() icon.add_behavior( { 'type': 'click_up', 'search_key': subscription_key, 'cbjs_action': ''' if (!confirm("Confirm subscription delete?")) { return; } var top = bvr.src_el.getParent(".spt_subscription_top"); var server = TacticServerStub.get(); server.delete_sobject(bvr.search_key); spt.panel.refresh(top); ''' } ) 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_display(my): search_key = my.kwargs.get("search_key") snapshot = my.kwargs.get("snapshot") if snapshot: my.snapshot = snapshot else: my.snapshot = SearchKey.get_by_search_key(search_key) assert my.snapshot metadata = my.snapshot.get_metadata() top = my.top top.add_color("background", "background") table = Table() table.set_max_width() top.add(table) table.set_unique_id() table.add_border() table.add_smart_styles("spt_cell", { 'padding': '3px' } ) tr = table.add_row() tr.add_gradient("background", "background3") th = table.add_header("Property") th.add_style("min-width: 200px") th.add_style("padding: 5px") th = table.add_header("Value") th.add_style("min-width: 400px") th.add_style("padding: 5px") keys = metadata.get("__keys__") if not keys: keys = metadata.keys() empty = False if not keys: empty = True keys = ['','','','','','',''] table.add_smart_styles("spt_cell", { 'height': '20px' } ) for i, key in enumerate(keys): value = metadata.get(key) title = Common.get_display_title(key) tr = table.add_row() if i % 2: tr.add_color("background", "background") tr.add_color("color", "color") else: tr.add_color("background", "background", -8) tr.add_color("color", "color") td = table.add_cell() td.add_class("spt_cell") td.add(title) td = table.add_cell() td.add_class("spt_cell") td.add(value) if empty: div = DivWdg() top.add(div) div.add_style("height: 30px") div.add_style("width: 150px") div.add_style("margin-top: -110px") div.center() div.add("<b>No Metadata</b>") div.add_border() div.add_color("background", "background3") div.add_color("color", "color3") div.add_style("padding: 20px") div.add_style("text-align: center") top.add_style("min-height: 200px") return top