def TR(widths, items): return Row(width='100%').add(*[ Row( width=widths[i], height='100%', border=Border( width=0.5, color=Color.BLACK, ), padding=Rect([3, 6, 3, 0]) if i in (2, 4) else Rect([3, 0, 3, 0]), ).add( Image( filename=get_resource_abspath('images/{}'.format(item['icon'] ), ), height=8, margin=Rect([2, 4, 4, 4]), ) if item.get('icon') else None, Text( markup=xstr(item.get('text')), font_family='Roboto Condensed', font_size=7, width=("100%" if i != 0 else None), height="100%", alignment=Text.RIGHT if i in (2, 4) else Text.CENTER, vertical_alignment=Text.MIDDLE, )) for i, item in enumerate(items) ])
def FurtherInfoNotes(data, **kwargs): # TODO: check nans before entering return Row(**kwargs, width='100%', height=16).add( Text( text=boil('page_2_futher_information'), font_family='Roboto Condensed', font_size=7, font_weight=Pango.Weight.BOLD, padding=Rect([12.5, 0, 0, 5]), ), *[ Column(padding=Rect(8)).add( Text( text='{}. {} ({})'.format( get_lang_num(i + 1), contact['name'] if contact['name'] and contact['name'] != 'None' else '', contact['title'] if contact['title'] and contact['title'] != 'None' else '', ), font_family='Roboto Condensed', font_size=7, padding=Rect([5, 0, 0, 0]), ), Text( text=' {}'.format( get_lang_num(contact['phone']) if contact['phone'] and contact['phone'] != 'None' else ''), font_family='Roboto Condensed', font_size=7, ), ) for i, contact in enumerate(data) if not all([is_nan(v) for v in contact.values()]) ])
def NonCompliance(data): return Column(width='50%').add( Text( text=boil('recon_&_retrofit_non-compliances_title'), color=Color.ACCENT, font_family="Roboto Condensed", font_size=9, font_weight=Text.BOLD, margin=Rect([3.2, 0, 5, 0]), ), Text(markup='<b>{}:</b> {}'.format( boil('recon_&_retrofit_registered_(both)'), fmt_num(data['registered']), ), font_family="Roboto Condensed", font_size=7.5, margin=Rect([0, 0, 3, 0])), Text( markup='<b>{}:</b> {}'.format( boil('recon_&_retrofit_addressed_(both)'), fmt_num(data['addressed']), ), font_family="Roboto Condensed", font_size=7.5, ), )
def __init__(self, **kwargs): self.children = [] self.x = 0 self.y = 0 self.width = None self.height = None self.angle = 0 self.top = None self.left = None self.bottom = None self.right = None self.w = None self.h = None self.bg_color = [0, 0, 0, 0] self.border = Border() self.margin = Rect() self.padding = Rect() self.parent = None self.absolute = False self.relative = False self.relative_parent = None self.extra = None for key, value in kwargs.items(): setattr(self, key, value) self.initial_kwargs = kwargs self.init()
def Houses(data): return Column(width='100%').add( Text(text=boil('recon_&_retrofit_houses_title'), font_family="Roboto Condensed", font_size=9, font_weight=Text.BOLD, color=Color.ACCENT, margin=Rect([0, 0, 2, 0])), Row( width='100%', justify='space-between', margin=Rect([0, 0, 3, 0]), ).add( Text( markup='<b>{}</b>: {}'.format( boil('recon_&_retrofit_under_construction'), fmt_num(data['under_construction'], )), font_family="Roboto Condensed", font_size=7.5, ), Text( markup='<b>{}</b>: {}'.format( boil('recon_&_retrofit_completed'), fmt_num(data['completed'], )), font_family="Roboto Condensed", font_size=7.5, )), )
def RetrofitStatus(data): rows = [ TwoValueLineChart(datum, bar_color=Color.ACCENT2) for datum in data ] return Column(width='100%').add( Text( text=boil('recon_&_retrofit_retrofitting_status_title'), font_family="Roboto Condensed", font_size=9, font_weight=Text.BOLD, color=Color.ACCENT, ), Hr( width='100%', height=1, margin=Rect([3, 0, 3, 0]), dash=[3], color=Color.PRIMARY, ), *rows, Hr( width='100%', height=1, margin=Rect([3, 0, 3, 0]), dash=[3], color=Color.PRIMARY, ), )
def BottomBox(data): return Row( width='100%', margin=Rect([8, 0, 6, 0]), border=Border( width=0.5, color=Color.BLACK, ), padding=Rect([2, 8, 4, 8]), ).add( Column(width='50%').add( Text( text=boil('status_of_cm_types_of_workers'), font_family='Roboto Condensed', font_size=8, font_weight=Pango.Weight.BOLD, ), Text(text='{} {}'.format( boil('status_of_cm_list_1'), boil('status_of_cm_skilled_mason'), ), font_family='Roboto Condensed', font_size=8, padding=Rect([2, 0, 2, 0])), Text( text='{} {}'.format( boil('status_of_cm_list_2'), boil('status_of_cm_labourer'), ), font_family='Roboto Condensed', font_size=8, ), ), Column(width='60%').add( Text( text=boil('status_of_cm_avg._daily_wage_(nrs.)'), width='100%', alignment=Text.CENTER, font_family='Roboto Condensed', font_size=8, font_weight=Pango.Weight.BOLD, ), Text( text='%s %s' % (fmt_num(data['avg_wage_1']), '/-'), width='65%', alignment=Text.RIGHT, font_family='Roboto Condensed', font_size=8, padding=Rect([2, 0, 2, 0]), ), Text( text='%s %s' % (fmt_num(data['avg_wage_2']), '/-'), width='65%', alignment=Text.RIGHT, font_family='Roboto Condensed', font_size=8, padding=Rect([0, 0, 1, 0]), )), )
def Header(data): nm_text = '{} | {}'.format( data['rep_data']['dist_nm'], data['rep_data']['palika_nm'], ) return Column( width='100%', margin=Rect([0, 5, 8, 5]), ).add( Row(height=52, width='10%').add( Text( text=boil('header_title'), font_family='Roboto Condensed', font_size=24, font_weight=Pango.Weight.BOLD, color=Color.PRIMARY, height='100%', vertical_alignment=Text.BOTTOM, ), Vr( width=2, height='100%', color=Color.PRIMARY, margin=Rect([0, 16, 0, 16]), padding=Rect([24, 0, 0, 0]), ), Column(height='100%', justify='end').add( Text( text='{} {}'.format( boil('header_month'), boil('header_year') if isinstance( boil('header_year'), str) else get_lang_num( str(boil('header_year'))), ), font='Roboto Light', font_size=10, color=Color.PRIMARY, ), Text( text=nm_text, font='Roboto Light', font_size=calc_nm_len(nm_text), color=Color.PRIMARY, ))), Hr( width='100%', height=1, color=Color.PRIMARY, margin=Rect([8, 0, 0, 0]), ), Hr( width='100%', height=1.8, color=Color.PRIMARY, margin=Rect([2, 0, 0, 0]), ), )
def ReconstructionAndRetrofit(data): return Row(width='100%', padding=Rect(8)).add( Column(width='50%', padding=Rect([3, 8, 0, 2])).add( ReconstructionStatus(data['reconstruction_status']), Houses(data['houses']), ), Column(width='50%', padding=Rect([3, 2, 0, 8])).add( RetrofitStatus(data['retrofitting_status']), Row(width='100%').add( Grievances(data['grievances']), NonCompliance(data['non_compliances']), ), ))
def Icon(filename): return Image( filename=get_resource_abspath('images/{}'.format(filename)), width=18, height=16, padding=Rect([2, 2, 2, 4]), )
def Sector(label, items, icon): return Column( width='50%', height='100%', justify='center', align='center', ).add( Canvas( width=56, height=56, renderer=IconRenderer(filename=icon), ), Text( text=label, color=Color.ACCENT, margin=Rect(4), font_family='Roboto Condensed', font_size=8, font_weight=Pango.Weight.BOLD, ), *[ Row().add( Text( text='{}: '.format(key), font_family='Roboto Condensed', font_size=8, font_weight=Pango.Weight.BOLD, ), Text( text=value, font_family='Roboto Condensed', font_size=8, )) for key, value in items.items() ])
def Label(text): return Text( text=text, font='RobotoCondensed', font_size=6, padding=Rect(2), )
def PoGroup(h, pos): #TODO: set global val for what blank is label = pos[0] pos_list = pos[1] return Column( width='98%', height='{}%'.format(h + 4), border=Border( width=0.5, color=Color.BLACK, ), ).add( Text( width='98%', height='{}%'.format(h + 4), # markup='{}'.format('hello '*60), markup='<b>{}:</b> {}'.format(boil(label), pos_list), color=Color.BLACK, font_family="Roboto Condensed", font_size=7, #TODO: fix bug where row cuts off early auto_scale_height=False, padding=Rect([1, 0, 5, 3]), ), )
def Contact(it, title, contact): for k, v in contact.items(): # TODO: fix 'none' if not v or v == 'None': contact[k] = '-' return Column(width='33%', padding=Rect([0, 8, 0, 8])).add( Text( text=title, font_family="Roboto Condensed", font_size=9, font_weight=Text.BOLD, ), Text( text=contact['name'] if contact['name'] != ZERO_DEFAULT else '', font_family="Roboto Condensed", font_size=7, ), Text( text=contact['title'] if contact['title'] != ZERO_DEFAULT else '', font_family="Roboto Condensed", font_size=7, ), Text( text=get_lang_num(contact['contact']) if contact['contact'] != ZERO_DEFAULT else '', font_family="Roboto Condensed", font_size=7, ))
def TwoValueLineChart(data, bar_color): row_margin = [4, 0, 0, 0] # if get_lang() == 'en': # row_margin = [4, 0, 0, 0] # elif get_lang() == 'np': # row_margin = [6, 0, 0, 0] label = boil(data['label']) if (label == 'Ist Tranche received'): label = 'I<sup>st</sup> Tranche received' if (label == 'IInd Tranche received'): label = 'II<sup>nd</sup> Tranche received' if (label == 'IIIrd Tranche received'): label = 'III<sup>rd</sup> Tranche received' return Row( width='100%', height=16, margin=Rect(row_margin), ).add( Text( width='40%', markup=label, font_family="Roboto Condensed", font_size=9, font_weight=Text.BOLD, ), # Row(width='60%', height='70%').add(add Row(width='60%', height='70%').add( Canvas( width='100%', height='100%', renderer=Bars(data, bar_color), )))
def Page2(data, LANG): set_lang(LANG) return Column( width=WIDTH, height=HEIGHT, bg_color=Color.WHITE, padding=Rect(32), ).add(Page2Content(data), )
def ReconstructionAndRetrofitFooter(**kwargs): return Text(**kwargs, text='{} {}'.format(boil('recon_&_retrofit_panel_footer'), kwargs['data']), font_family="Roboto Light", font_size=6, color=Color.DARK_GRAY, padding=Rect([0, 5, 2, 0]))
def Label(label, color): return Row( margin=Rect([0, 10, 0, 10]), padding=Rect([8, 10, 5, 10]), ).add( Node( width=7, height=7, bg_color=color, margin=Rect([0, 4, 0, 0]), ), Text( text=label, font='Roboto Light', font_size=6, ) )
def Label(label, color): return Row( margin=Rect([8, 0, 0, 0]), ).add( Node( width=10, height=10, bg_color=color, margin=Rect([2, 4, 0, 0]), ), Text( text=label, font='Roboto Light', font_size=8, padding=Rect([2.5, 0, 0, 0]) ) )
def Panel(**kwargs): title = kwargs.pop('title', None) left_footer = kwargs.pop('left_footer', empty) right_footer = kwargs.pop('right_footer', empty) footer_data = kwargs.pop('footer_data', empty) return Row( border=Border( color=Color.BLUE, radius=16, width=1, ), relative=True, margin=Rect([10, 5, 10, 5]), **kwargs, ).add( Text( text=title, absolute=True, font_family='Roboto Condensed', font_size=13, font_weight=Pango.Weight.BOLD, color=Color.BLUE, top=-6, left=10, bg_color=Color.WHITE, padding=Rect([0, 6, 0, 6]), ), left_footer( absolute=True, bottom=-12, left=0, data=footer_data, ), right_footer( absolute=True, bottom=-12, right=2, data=footer_data, ), )
def Pop(data): for k, v in data.items(): if not v: data[k] = boil('partner_orgs_no_partner_orgs') hs = _calc_box_hs([v for v in data.values()]) return Column(width='100%', height='100%').add( Column( width='100% - 16', height='76%', margin=Rect([12, 8, 4, 11]), ).add(*[PoGroup(info[0], info[1]) for info in zip(hs, data.items())]))
def Footer(data): faq_blocks = [] for it, item in enumerate(data): question = Text( width='100%', text='{}: {}'.format(boil('faq_q'), item['q']), font_family='Roboto Condensed', font_size=8.5, font_weight=Pango.Weight.BOLD, ) answer = Text( width='100%', text='{}: {}'.format(boil('faq_a'), item['a']), font_family='Roboto Condensed', font_size=8, padding=Rect([0, 0, 8, 0]) if it == 0 else Rect(0), ) faq_blocks.append(question) faq_blocks.append(answer) return Column( width='100%', padding=Rect([10, 16, 6, 16]), ).add(*faq_blocks, )
def KeyContacts(data): titles = [boil('key_contacts_municipal_office_title')] * 4 + [ boil('key_contacts_gmali/nra_title'), boil('key_contacts_dlpiu-building_title'), ] return Column( width='100%', margin=Rect([0, 5, 0, 0]), ).add( Row( width='100%', padding=Rect([15, 0, 20, 0]), ).add(*[ Contact(i, titles[i], contact) for i, contact in enumerate(data[:3]) ])).add( Row( width='100%', padding=Rect([0, 0, 12, 0]), ).add(*[ Contact(i + 3, titles[i + 3], contact) for i, contact in enumerate(data[3:]) ]))
def TR_Text(widths, items): return Row(width='100%').add(*[ Row( width=widths[i], height='100%', border=Border( width=0.5, color=Color.BLACK, ), padding=Rect(5), ).add( Text( markup=xstr(item), font_family='Roboto Condensed', font_size=7, width=("100%" if i != 0 else None), height="100%", alignment=Text.CENTER, vertical_alignment=Text.MIDDLE, )) for i, item in enumerate(items) ])
def HH(data): """for showing the HH bar. logic: if 0 values: show message that there are no reported issues if 1 value: do something #TODO else: show bar """ # info f.e type items = [ { 'key': 'landless', 'label': boil('land_issues_landless'), 'color': hx('#ff6117'), }, { 'key': 'no_land_certificates', 'label': boil('land_issues_no_land_certificates'), 'color': hx('#bf053d'), }, { 'key': 'right_of_way', 'label': boil('land_issues_right_of_way'), 'color': hx('#7d0547'), }, { 'key': 'affected_by_hep', 'label': boil('land_issues_affected_by_hep'), 'color': hx('#1e7a8c'), }, { 'key': 'smallplots', 'label': boil('land_issues_small_plots'), 'color': hx('#abd1b5'), }, { 'key': 'guthi_land', 'label': boil('land_issues_guthi_land'), 'color': hx('#ffc202'), }, ] # add val and drop item if it's zero or invalid items = _filter_items(items, data) wdz = _get_widths(items) bars = [] labels = [] if wdz: for item in wdz: color = item['color'] bar = Text( bg_color=color, height=20, width='{}%'.format(item['w']), alignment=Text.CENTER, vertical_alignment=Text.MIDDLE, text=fmt_num(item['val']), color=Color.WHITE, font_family='Roboto Condensed', font_size=11, font_weight=Pango.Weight.BOLD, ) bars.append(bar) label = Label( label=item['label'], color=color, ) labels.append(label) return Column( width='100%', padding=Rect([16, 16, 8, 16]), ).add( Row(width='100%').add(*bars), Row( width='100%', justify='space-between' if len(labels) > 1 else None, ).add(*labels) ) else: return Column(width='100%', height='100%').add( Text( height='100%', width='100%', alignment=Text.CENTER, vertical_alignment=Text.MIDDLE, text=boil('land_issues_no_information'), color=Color.GRAY, font_family='Roboto Condensed', font_size=18, font_weight=Pango.Weight.BOLD, margin=Rect([0, 0, 43, 0]), ) )
def Trainings(data): short = data['short'] vocational = data['vocational'] short_training = [ {'value': short['reached'], 'color': Color.ACCENT}, {'value': _calc_reached(short['reqd'], short['reached']), 'color': Color.GRAY}, ] vocational_training = [ {'value': vocational['reached'], 'color': Color.ACCENT}, {'value': _calc_reached(vocational['reqd'], vocational['reached']), 'color': Color.GRAY}, ] items = [ {'label': boil('training_reached'), 'color': Color.ACCENT}, {'label': boil('training_remaining'), 'color': Color.GRAY}, ] return Column( width='100%', height='100%', padding=Rect([10, 10, 4, 10]), ).add( Text( height=13, text=boil('training_sub_title'), color=Color.PRIMARY, font_family='Roboto Condensed', font_size=8, font_weight=Pango.Weight.BOLD, ), Row(width='100%', height='100% - 32', padding=Rect(4)).add( Canvas( width='50%', height='100%', renderer=PieChart( items=short_training, label=boil('training_short_training'), ) ), Canvas( width='50%', height='100%', renderer=PieChart( items=vocational_training, label=boil('training_vocational_training'), ) ), ), Row( width='100%', height=16, justify='center', align='center', ).add( *[ Label( label=item['label'], color=item['color'], ) for item in items ] ), )
class Node: def __init__(self, **kwargs): self.children = [] self.x = 0 self.y = 0 self.width = None self.height = None self.angle = 0 self.top = None self.left = None self.bottom = None self.right = None self.w = None self.h = None self.bg_color = [0, 0, 0, 0] self.border = Border() self.margin = Rect() self.padding = Rect() self.parent = None self.absolute = False self.relative = False self.relative_parent = None self.extra = None for key, value in kwargs.items(): setattr(self, key, value) self.initial_kwargs = kwargs self.init() def init(self): pass def clone(self): node = self.__class__(**self.initial_kwargs) node.add(*[c.clone() for c in self.children]) return node def add(self, *nodes): for node in nodes: if not node: continue if node.parent: raise Exception('Node already added to another parent') node.parent = self self.children.append(node) return self def set_relative_parent(self, relative_parent): self.relative_parent = relative_parent if self.relative: [c.set_relative_parent(self) for c in self.children] return [c.set_relative_parent(relative_parent) for c in self.children] def update_absolute_layout(self): self.calculate_layout() if self.relative_parent: if self.left is not None: self.x = self.relative_parent.x \ + self.left + self.margin.left elif self.right is not None and self.relative_parent.w: self.x = self.relative_parent.x + self.relative_parent.w \ - self.right - self.margin.right - self.w if self.top is not None: self.y = self.relative_parent.y \ + self.top + self.margin.top elif self.bottom is not None and self.relative_parent.h: self.y = self.relative_parent.y + self.relative_parent.h \ - self.bottom - self.margin.bottom - self.h self.update_layout() def calculate_layout(self): parent_w = self.parent and self.parent.w parent_h = self.parent and self.parent.h if isinstance(self.width, str): w = self.width if '%' in w: if not parent_w: return parent_w -= self.parent.padding.spacing_x() w = w.replace('%', '* {} / 100'.format(parent_w)) self.w = eval(w) else: self.w = self.width if isinstance(self.height, str): h = self.height if '%' in h: if not parent_h: return parent_h -= self.parent.padding.spacing_y() h = h.replace('%', '* {} / 100'.format(parent_h)) self.h = eval(h) else: self.h = self.height def update_layout(self): self.calculate_layout() def can_draw(self): return ( self.w is not None and self.h is not None ) def set_context(self, ctx): self.ctx = ctx [c.set_context(ctx) for c in self.children] def draw_content(self, x, y, w, h): pass def draw(self): self.border.draw(self.ctx, self.x, self.y, self.w, self.h) self.ctx.save() self.ctx.set_source_rgba(*self.bg_color) self.ctx.fill() x = self.x + self.padding.left y = self.y + self.padding.top w = self.w - self.padding.spacing_x() h = self.h - self.padding.spacing_y() angle = self.angle * math.pi / 180 if angle: self.ctx.translate(x, y) self.ctx.rotate(angle) self.ctx.translate(-x, -y) self.draw_content(x, y, w, h) [ c.draw() for c in self.children if c.can_draw() ] self.ctx.restore()
def TechnicalStaff(tech_data, mason_data): widths = ['35%', '30%', '35%'] headers = [ boil('tech_staff_staff_title'), boil('tech_staff_available_title'), boil('tech_staff_addl_req_title') ] tech_data = [[ boil(item['lookup']), fmt_num(item['available']), fmt_num(item['additional']) ] for item in tech_data] mason_data = [ boil(mason_data['lookup']), mason_data['available'], mason_data['additional'] ] # mason_data = [mason_data['label'], 100, 300] header_row = Row(width='100%').add(*[ Text( border=Border(width=0.5, color=Color.BLACK), text=item, width=widths[i], font_family='Roboto Condensed', font_size=7, font_weight=Pango.Weight.BOLD, padding=Rect(4), alignment=(Text.LEFT if i == 0 else Text.CENTER), ) for i, item in enumerate(headers) ]) # add non masons data_rows = [ Row(width='100%').add( *[ Text( border=Border(width=0.5, color=Color.BLACK), text=item, width=widths[i], height='15', font_family='Roboto Condensed', font_size=7 if i == 0 else 9, font_weight=Pango.Weight.BOLD if i == 0 else None, padding=Rect([3, 0, 0, 4]), alignment=(Text.LEFT if i == 0 else Text.CENTER), ) for i, item in enumerate(row) ], ) for row in tech_data ] # add masons data_rows.append( Row(width='100%').add(*[ Text( border=Border(width=0.5, color=Color.BLACK), text=mason_data[0], width=widths[0], font_family='Roboto Condensed', font_weight=Pango.Weight.BOLD, font_size=7, padding=Rect(4), alignment=Text.LEFT, ), Column( border=Border(width=0.5, color=Color.BLACK), height='100%', width=widths[1], ).add( Text( text='{} ({} {})'.format(fmt_num(mason_data[1][0]), fmt_num(7), boil( 'tech_staff_days')), font_family='Roboto Condensed', font_size=6, width='100%', alignment=Text.CENTER, padding=Rect([2, 0, 0, 0]), )).add( Text( text='{} ({} {})'.format(fmt_num(mason_data[1][1]), fmt_num(50), boil('tech_staff_days')), font_family='Roboto Condensed', font_size=6, width='100%', alignment=Text.CENTER, )), Column(border=Border(width=0.5, color=Color.BLACK), height='100%', width=widths[2]).add( Text( text='{} ({} {})'.format(fmt_num(mason_data[2][0]), fmt_num(7), boil('tech_staff_days')), font_family='Roboto Condensed', font_size=6, width='100%', alignment=Text.CENTER, padding=Rect([2, 0, 0, 0]), )).add( Text( text='{} ({} {})'.format( fmt_num(mason_data[2][1]), fmt_num(50), boil('tech_staff_days')), font_family='Roboto Condensed', font_size=6, width='100%', alignment=Text.CENTER, )), ])) # # Row(width=widths[1], # border=Border(width=0.5, color=Color.BLACK), # height='100%').add( # Row(border=Border(width=0.5, color=Color.BLACK)).add( # Text( # text='xx22', # font='RobotoCondensed bold 6', # font_size='RobotoCondensed bold', # alignment=Text.CENTER, # ), # ).add(Row(border=Border(width=0.5, color=Color.BLACK)).add( # Text( # text='yy', # font='RobotoCondensed 6', # ), # ), # ), return Column( width='100%', padding=Rect(16), ).add( header_row, *data_rows, )
def Typologies(data): widths = ['60%', '20%', '20%'] headers = [ boil('typologies_typology'), boil('typologies_municipal'), boil('typologies_district') ] if get_lang() == 'np': row_seperator_padding = [3.5, 0, 4.5, 0] else: row_seperator_padding = [4.5, 0, 4.5, 0] # flatten and add dict # TODO: assert that we don't have duplicate keys? (exclude blanks)) rows = get_list_typo(OrderedDict((boil(k), v) for k, v in data.items()), 5) return Column( width='100%', padding=Rect(12), ).add( Row(width='100%').add(*[ Text( width=widths[i], text=header, font_family="Roboto Condensed", font_size=9, font_weight=Text.BOLD, color=Color.ACCENT, alignment=Text.LEFT if i == 0 else Text.RIGHT, ) for i, header in enumerate(headers) ]), Hr( width='100%', height=1, color=Color.PRIMARY, dash=[3], margin=Rect([3, 0, 3, 0]), ), *[ Row(width='100%').add(*[ Item( width=widths[i], text=k if i == 0 else fmt_pct( list(d_v.items())[i - 1][1], pts=2, ), index=i, padding=Rect(row_seperator_padding), ) for i in range(NUM_COLS) ]) for k, d_v in rows.items() ], *[ Row(width='100%').add(*[ Item( width=widths[i], text=' ', index=i, padding=Rect(row_seperator_padding), ) for i in range(NUM_COLS) ]) for v in range(NUM_ROWS - len(rows)) ], Text(width='100%', text=boil('typologies_cbs_footer'), font_family="Roboto Light", font_size=6, alignment=Text.RIGHT, color=Color.DARK_GRAY, padding=Rect([0, 0, 10, 0])), )
def CMTable(top_data, bot_data): materials = [{ 'label': boil('status_of_cm_stone'), 'key': 'stone', 'icon': 'stone.png', 'unit': boil('status_of_cm_cubic_metre_measurement'), }, { 'label': boil('status_of_cm_aggregate'), 'key': 'aggregate', 'icon': 'aggregate.png', 'unit': boil('status_of_cm_cubic_metre_measurement'), }, { 'label': boil('status_of_cm_sand'), 'key': 'sand', 'icon': 'sand.png', 'unit': boil('status_of_cm_cubic_metre_measurement'), }, { 'label': boil('status_of_cm_timber'), 'key': 'timber', 'icon': 'timber.png', 'unit': boil('status_of_cm_cubic_feet_measurement'), }, { 'label': boil('status_of_cm_cement_(ppc)'), 'key': 'cement_ppc', 'icon': 'cement.png', 'unit': boil('status_of_cm_sack_measurement'), }, { 'label': boil('status_of_cm_cement_(opc)'), 'key': 'cement_opc', 'icon': 'cement.png', 'unit': boil('status_of_cm_sack_measurement'), }, { 'label': boil('status_of_cm_rebars'), 'key': 'rebar', 'icon': 'rebar.png', 'unit': boil('status_of_cm_kg_plural_measurement'), }, { 'label': boil('status_of_cm_tin'), 'key': 'tin', 'icon': 'tin.png', 'unit': boil('status_of_cm_bundle_measurement'), }, { 'label': boil('status_of_cm_bricks'), 'key': 'bricks', 'icon': 'bricks.png', 'unit': boil('status_of_cm_pieces_measurement'), }] rows = [] for material in materials: key = material['key'] datum = top_data[key] label = material['label'] if datum['ava'] is None: datum['ava'] = ZERO_DEFAULT rows.append([ { 'text': label, 'icon': material.get('icon') }, { 'text': material['unit'] }, { 'text': fmt_num(datum['req_quantity']) }, { 'text': datum['ava'] }, { 'text': fmt_num(datum['cost']) }, ]) headers = [ '<b>{}</b>'.format(boil(k)) for k in [ 'status_of_cm_materials_header', 'status_of_cm_unit_header', 'status_of_cm_req._quantity*_header', 'status_of_cm_ava._header', 'status_of_cm_cost_(nrs.)**_header', ] ] widths = ['28%', '12%', '25%', '10%', '25%'] return Column(width='100%', padding=Rect([16, 14, 0, 14])).add( TR_Text(widths=widths, items=headers), *[TR(widths=widths, items=row) for row in rows], BottomBox(bot_data), )