Esempio n. 1
0
    def wrap(self):
        if DEBUG:
            print("Wrapping list item...")

        p_style, list_level, list_type = get_current_li(self.section.extra)

        self.cell_object.add_paragraph(style=p_style)

        numbered = False
        if list_type == ORDERED_LIST_NAME:
            numbered = True

        utils.list_number(self.cell_object.cell,
                          self.cell_object.paragraph,
                          level=list_level,
                          num=numbered)

        if isinstance(self.section.contents, str):
            insert_text(self.cell_object, self.section.contents)
            return

        temp_section = MarkdownSection('markdown', self.section.contents, {},
                                       {})
        temp_section.propagate_extra('inline', True)

        markdown.invoke(self.cell_object,
                        temp_section,
                        invoked_from_wrapper=True)
Esempio n. 2
0
    def insert(self):
        if DEBUG:
            print("Adding list...")

        list_data = self.section.contents
        if isinstance(list_data, dict) and len(list_data) != 1:
            list_data = [list_data]

        if isinstance(list_data, dict) and len(list_data) == 1:
            # Create the parent title
            wrapper_table = self.cell_object.cell.add_table(rows=2, cols=1)
            title_cell = wrapper_table.cell(0, 0)
            title_text = list(list_data.keys())[0]
            insert_text(title_cell, title_text,
                        self.style['title'])

            # Create a list in a list because this is a grouped list
            co = CellObject(wrapper_table.cell(1, 0))

            table_data = list_data[title_text]
            invoke(co,
                   Section('list', table_data, self.section.layout,
                           {}))
        else:
            table.invoke(self.cell_object,
                         Section('table', list_data,
                                 self.section.layout,
                                 {'list_style': True}))
Esempio n. 3
0
    def wrap(self, invoked_from_wrapper=False):
        # Handle called from another wrapper.
        items = self.section.contents

        if not isinstance(items, list):
            raise ValueError('ItemsSection does not have valid contents ' +
                             '(must be a list)')

        table_width = max(items, key=lambda x: x['endCol']).get('endCol')
        row_count = max(items,
                        key=lambda x: x.get('index', 0)).get('index') + 1

        item_table = self.cell_object.cell.add_table(rows=row_count,
                                                     cols=table_width)

        if DEBUG:
            item_table.style = DEFAULT_TABLE_STYLE

        for item in items:
            row, col, col_to_merge = item.get(
                'index', 0), item.get('startCol'), item.get('endCol')
            current_cell = item_table.cell(row, col)
            current_cell.merge(item_table.cell(row, col_to_merge - 1))

            field_name = item.get("fieldName", "")
            field_name = field_name[0].upper() + field_name[1:]
            field_name = f'{field_name}: '

            if item.get('displayType', self.display_types['ROW']) == \
                    self.display_types['CARD']:
                field_name += '\n'

            insert_text(current_cell, field_name, self.style['key'])
            insert_text(current_cell, item.get("data", ""),
                        self.style['value'])
Esempio n. 4
0
    def insert(self):
        if DEBUG:
            print('Adding number...')

        table = self.cell_object.cell.add_table(rows=1, cols=1)

        if DEBUG:
            table.style = 'Table Grid'

        # add background color
        background_color = self.section.layout.get('style', {}).get(
            'backgroundColor', '')[1:]

        # Add the main number
        inner_cell = table.cell(0, 0)
        style_cell(inner_cell, color_hex=background_color)
        main_number = CellObject(inner_cell)

        sign = self.section.layout.get('sign', '')
        sign = '' if sign is None else sign
        insert_text(main_number,
                    str(self.section.contents) + sign, self.style['main'])

        main_number.add_paragraph(add_run=True)
        insert_text(main_number, str(self.section.extra['title']),
                    self.style['title'])
Esempio n. 5
0
    def insert(self):
        if DEBUG:
            print('Adding horizontal line...')

        self.cell_object.add_paragraph(add_run=False)
        insert_text(self.cell_object,
                    '⎯' * DEFAULT_HR_DASHES_SIZE,
                    style={PYDOCX_TEXT_ALIGN: 'center'})
Esempio n. 6
0
    def insert(self):
        if DEBUG:
            print('Adding link...')

        insert_text(self.cell_object, self.section.contents)

        add_hyperlink_into_run(self.cell_object.paragraph, self.cell_object.run,
                               self.section.extra['href'])
Esempio n. 7
0
    def insert(self):
        if DEBUG:
            print('Adding date...')

        try:
            formatted_date = get_formatted_date(self.section.contents,
                                                self.section.layout)
        except ParserError as e:
            formatted_date = 'n/a'

        insert_text(self.cell_object, formatted_date)
Esempio n. 8
0
    def insert(self):
        if DEBUG:
            print('Adding number...')

        table = self.cell_object.cell.add_table(rows=1, cols=1)

        if DEBUG:
            table.style = 'Table Grid'

        # Add the main number
        inner_cell = table.cell(0, 0)
        style_cell(inner_cell)
        main_number = CellObject(inner_cell)

        insert_text(main_number, str(self.section.contents),
                    self.style['main'])

        main_number.add_paragraph(add_run=True)
        insert_text(main_number, str(self.section.extra['title']),
                    self.style['title'])
Esempio n. 9
0
    def insert(self):
        if DEBUG:
            print('Adding text...')

        default_date_format = '%m %b %Y %H:%M:%S %SZ'

        formatted_date = "N/A"
        date = moment.date(self.section.contents)

        if self.section.contents == '':
            formatted_date = moment.now().strftime(default_date_format)

        elif self.section.layout:
            layout = self.section.layout

            if "format" in layout:
                formatted_date = date.format(layout["format"])
            else:
                formatted_date = date.strftime(default_date_format)

        insert_text(self.cell_object, formatted_date)
Esempio n. 10
0
    def insert(self):
        if DEBUG:
            print('Adding error element...')

        style = {
            'bold': False,
            'color': '#ff0013',
            'fontSize': 10,
            'underline': False,
            'strikethrough': False,
            'italic': False
        }

        # Add some padding
        table = self.cell_object.cell.add_table(rows=1, cols=1)
        if DEBUG:
            table.style = 'Table Grid'
        inner_cell = table.cell(0, 0)
        style_cell(inner_cell, {"top": 50, "bottom": 50})

        error_message = f'ERROR GENERATING SECTION ({self.section.contents})'
        utils.insert_text(inner_cell, error_message, style)
Esempio n. 11
0
    def insert(self):
        if DEBUG:
            print("Adding table...")

        table_data = self.section.contents
        if 'tableColumns' not in self.section.layout:
            return

        if 'readableHeaders' in self.section.layout:
            ordered = self.section.layout['tableColumns']
            readable_headers = self.section.layout['readableHeaders'].values()
            table_columns = fix_order(ordered, readable_headers)
        else:
            table_columns = self.section.layout['tableColumns']

        for i, header_text in enumerate(table_columns):
            if not isinstance(header_text, str):
                table_columns.remove(header_text)

        if 'title' in self.section.extra:
            table = self.cell_object.cell.add_table(rows=2,
                                                    cols=len(table_columns))
            title = table.cell(0, 0)
            title.merge(table.cell(0, len(table_columns) - 1))
            insert_text(title, self.section.extra['title'],
                        self.style['title'])

            hdr_cells = table.rows[1].cells
        else:
            table = self.cell_object.cell.add_table(rows=2,
                                                    cols=len(table_columns))
            hdr_cells = table.rows[0].cells

        table.style = DEFAULT_TABLE_STYLE

        if 'list_style' in self.section.extra and self.section.extra[
                'list_style']:
            table.style = None

        for i, header_text in enumerate(table_columns):
            insert_text(hdr_cells[i], header_text, self.style['text'])

        for r in table_data:
            row_cells = table.add_row().cells
            for i, header_text in enumerate(table_columns):
                if header_text not in r:
                    continue

                # Old json format can have 'Avatars', which are images
                if isinstance(r[header_text], dict) and \
                        r[header_text]['type'] == 'image':
                    row_temp = r[header_text]
                    s = Section(row_temp['type'], row_temp['data'], {}, {})
                    co = CellObject(row_cells[i], add_run=False)
                    image.invoke(co, s)
                else:
                    insert_text(row_cells[i], r[header_text],
                                self.style['text'])
Esempio n. 12
0
    def wrap(self, invoked_from_wrapper=False):
        # Handle called from another wrapper.
        items = self.section.contents

        if not isinstance(items, list):
            raise ValueError('ItemsSection does not have valid contents ' +
                             '(must be a list)')

        table_width = max(items, key=lambda x: x['endCol']).get('endCol')
        row_count = max(items,
                        key=lambda x: x.get('index', 0)).get('index') + 1

        title_offset = 0
        has_title = 'title' in self.section.extra
        if has_title:
            title_offset += 1

        item_table = self.cell_object.cell.add_table(rows=row_count +
                                                     title_offset,
                                                     cols=table_width)
        if DEBUG:
            item_table.style = DEFAULT_TABLE_STYLE

        if has_title:
            section_title = self.section.extra['title']
            insert_text(item_table.cell(0, 0), section_title + '\n',
                        self.style['title'])

        for item in items:
            row, col, col_to_merge = item.get(
                'index',
                0 + title_offset), item.get('startCol'), item.get('endCol')
            current_cell = item_table.cell(row + title_offset, col)
            current_cell.merge(
                item_table.cell(row + title_offset, col_to_merge - 1))

            field_name = item.get("fieldName", "")
            field_type = item.get("fieldType", "shortText")
            field_name = field_name[0].upper() + field_name[1:]
            field_name = f'{field_name}: '

            if item.get('displayType', self.display_types['ROW']) == \
                    self.display_types['CARD']:
                field_name += '\n'

            data = item.get("data", "")
            insert_text(current_cell, field_name, self.style['key'])

            if field_type == 'grid':
                table.invoke(
                    self.cell_object,
                    SectionObject('table', data, self.section.layout, {}))
            else:
                insert_text(current_cell, data, self.style['value'])
Esempio n. 13
0
    def insert(self):
        if DEBUG:
            print("Adding trend...")

        table = self.cell_object.cell.add_table(rows=2, cols=4)
        # add background color
        background_color = self.section.layout.get('style', {}).get('backgroundColor', '')[1:]

        # Add the main number
        current_sum = self.section.contents['currSum']
        inner_cell = table.cell(0, 1)
        style_cell(inner_cell, color_hex=background_color)
        main_number = CellObject(inner_cell)
        insert_text(main_number, str(current_sum), self.style['main'])

        # Add the trend number
        previous_sum = self.section.contents['prevSum']
        # Fix for the percentages
        divider = previous_sum
        if previous_sum == 0:
            divider = 1

        change = ((current_sum - previous_sum) * 100) / divider
        if change < 0:
            direction = '▼'  # Down arrow
        elif change == 0:
            direction = '= '
        else:
            direction = '▲'  # Up arrow

        if change > 999.0:
            change = '> 999'
        elif change < -999.0:
            change = '< -999'
        else:
            change = "{0:.2f}".format(change)
        value_percent = f'{direction}{change}%'
        inner_cell = table.cell(0, 2)
        style_cell(inner_cell, color_hex=background_color)
        trend_number = CellObject(inner_cell)
        insert_text(trend_number, value_percent, self.style['trend'])

        # Add the title
        third_cell = table.cell(1, 1)
        style_cell(third_cell, color_hex=background_color)
        table.cell(1, 2).merge(third_cell)
        title = CellObject(third_cell)
        insert_text(title, str(self.section.extra['title']),
                    self.style['title'])
Esempio n. 14
0
    def insert(self):
        if DEBUG:
            print("Adding trend...")

        table = self.cell_object.cell.add_table(rows=2, cols=4)

        # Add the main number
        current_sum = self.section.contents['currSum']
        inner_cell = table.cell(0, 1)
        style_cell(inner_cell)
        main_number = CellObject(inner_cell)
        insert_text(main_number, str(current_sum), self.style['main'])

        # Add the trend number
        previous_sum = self.section.contents['prevSum']
        # Fix for the percentages
        if previous_sum == 0:
            previous_sum = 1

        change = (current_sum * 100) / previous_sum
        if change < 0:
            direction = '⏷'  # Down arrow
        elif change == 0:
            direction = '= '
        else:
            direction = '⏶'  # Up arrow

        change = "{0:.2f}".format(change)
        value_percent = f'{direction}{change}%'
        inner_cell = table.cell(0, 2)
        style_cell(inner_cell)
        trend_number = CellObject(inner_cell)
        insert_text(trend_number, value_percent, self.style['trend'])

        # Add the title
        third_cell = table.cell(1, 1)
        style_cell(third_cell)
        table.cell(1, 2).merge(third_cell)
        title = CellObject(third_cell)
        insert_text(title, str(self.section.extra['title']),
                    self.style['title'])
Esempio n. 15
0
    def insert(self):
        if DEBUG:
            print("Adding table...")

        table_data = self.section.contents

        if isinstance(table_data, dict):
            table_data = table_data.get('data', table_data)

        # If table columns isn't present, use the dict values of the table data
        # as table columns (kind of like list).
        if 'tableColumns' not in self.section.layout:
            self.section.layout['tableColumns'] = list(table_data[0].keys())

        # Use and order according to readableHeaders if present.
        if 'readableHeaders' in self.section.layout:
            ordered = self.section.layout['tableColumns']
            readable_headers = self.section.layout['readableHeaders']
            table_columns = fix_order(ordered, readable_headers)
        else:
            table_columns = self.section.layout['tableColumns']

        # Quick fix, word crashes on more than MAX_MS_TABLE_COLS_LIMIT
        #   (64 right now) columns.
        # See: https://stackoverflow.com/questions/36921010/docx-does-not-support-more-than-63-columns-in-a-table
        table_columns = table_columns[0:MAX_MS_TABLE_COLS_LIMIT]

        for i, row_title in enumerate(table_columns):
            if not isinstance(row_title, str):
                table_columns.remove(row_title)

        if 'title' in self.section.extra:
            table = self.cell_object.cell.add_table(rows=2,
                                                    cols=len(table_columns))
            title = table.cell(0, 0)
            title.merge(table.cell(0, len(table_columns) - 1))
            insert_text(title, self.section.extra['title'], self.style['title'])

            hdr_cells = table.rows[1].cells
        else:
            table = self.cell_object.cell.add_table(rows=1,
                                                    cols=len(table_columns))
            hdr_cells = table.rows[0].cells

        table.style = DEFAULT_TABLE_STYLE

        if 'list_style' in self.section.extra and self.section.extra[
            'list_style']:
            table.style = None

        for i, row_title in enumerate(table_columns):
            insert_text(hdr_cells[i], row_title, self.style['text'])

        for row_item in table_data:
            row_cells = table.add_row().cells
            for i, row_title in enumerate(table_columns):
                if row_title not in row_item:
                    continue

                # Old json format can have 'Avatars', which are images
                if isinstance(row_item[row_title], dict) and \
                        row_item[row_title]['type'] == 'image':
                    insert_table_image(row_item, row_title, row_cells[i])
                else:
                    insert_text(row_cells[i], str(row_item[row_title]),
                                self.style['text'])
Esempio n. 16
0
    def wrap(self, invoked_from_wrapper=False):
        # Handle called from another wrapper.
        md_section_list = None
        if isinstance(self.section.contents, list):
            md_section_list = self.section.contents

        elif invoked_from_wrapper and \
                isinstance(self.section.contents.contents, str):
            md_section_list = [self.section.contents]

        if not isinstance(md_section_list, list):
            raise ValueError('Markdown section does not have valid contents ' +
                             '(must be a list)')

        for section in md_section_list:
            # === Start wrappers ===
            if section.type == MD_TYPE_DIV:
                temp_section = MarkdownSection('markdown', section.contents,
                                               {}, {})
                invoke(self.cell_object, temp_section)
                continue

            if section.type == MD_TYPE_CODE:
                md_code.invoke(self.cell_object, section)
                self.cell_object.update_paragraph()
                continue

            if section.type == MD_TYPE_QUOTE:
                md_blockquote.invoke(self.cell_object, section)
                self.cell_object.update_paragraph()
                continue

            if section.type == MD_TYPE_UNORDERED_LIST:
                md_ul.invoke(self.cell_object, section)
                self.cell_object.update_paragraph()
                continue

            if section.type == MD_TYPE_ORDERED_LIST:
                md_ol.invoke(self.cell_object, section)
                self.cell_object.update_paragraph()
                continue

            if section.type == MD_TYPE_LIST_ITEM:
                md_li.invoke(self.cell_object, section)
                continue

            if section.type == MD_TYPE_TABLE:
                table_html = section.extra['original_html']
                t = PyQuery(table_html)
                headers = [i.find('th') for i in t.find('tr').items()][0]
                headers = [c.text() for c in headers.items()]

                rows = [
                    i.find('td') for i in t.find('tr').items() if i.find('td')
                ]
                data = []
                for row in rows:
                    r = {
                        headers[i]: c.text()
                        for i, c in enumerate(row.items())
                    }
                    data.append(r)
                s = Section("table", data, {"tableColumns": headers}, {})
                table.invoke(self.cell_object, s)
                continue

            # Fix wrapped:
            #   (Some times there are elements which contain other elements,
            #    but are not considered one of the declared wrappers)
            if isinstance(section.contents, list):
                is_inside_wrapper = False

                if 'inline' in section.extra:
                    is_inside_wrapper = True

                if section.type == 'span':
                    section.propagate_extra('check_newline',
                                            True,
                                            only_multiple_children=False)

                # TODO: Fix problem with H1 no newline even if in span.
                temp_section = MarkdownSection('markdown', section.contents,
                                               {}, section.extra,
                                               section.attrs)
                invoke(self.cell_object,
                       temp_section,
                       invoked_from_wrapper=is_inside_wrapper)
                continue

            # === Elements ===

            if section.type in SHOULD_NEW_LINE and section.get_extra(
                    'check_newline'):
                self.cell_object.add_paragraph()

            if section.type == MD_TYPE_HORIZONTAL_LINE:
                md_hr.invoke(self.cell_object, section)
                continue

            # Add a block (newline) if not called from a wrapper
            #  (Should come after hr)
            if not invoked_from_wrapper:
                self.cell_object.add_paragraph()

            if section.type in MD_TYPES_HEADERS:
                # We want to keep the h{1...6} for styling
                insert_header(self.cell_object,
                              section.contents,
                              header=section.type)

                continue

            if section.type in [MD_TYPE_TEXT, MD_TYPE_INLINE_TEXT]:
                if invoked_from_wrapper:
                    self.cell_object.add_run()

                insert_text(self.cell_object, section)
                continue

            if section.type == MD_TYPE_LINK:
                md_link.invoke(self.cell_object, section)
                continue

            if section.type == MD_TYPE_IMAGE:
                md_image.invoke(self.cell_object, section)
                continue

            raise ValueError(f'Section type is not defined: {section.type}')
Esempio n. 17
0
    def insert(self):
        if DEBUG:
            print("Adding duration...")

        contents = self.section.contents

        days = '0'
        hours = '0'
        minutes = '0'
        if contents:
            result = 0
            if len(contents) > 0 and isinstance(
                    contents[0]['data'],
                    list) and len(contents[0]['data']) > 0:
                result = contents[0]['data'][0]

            days = floor(result / (3600 * 24))
            result -= days * 3600 * 24

            hours = floor(result / 3600)
            result -= hours * 3600

            minutes = floor(result / 60)

            days = format_number(days)
            hours = format_number(hours)
            minutes = format_number(minutes)

        # Split the table as so:
        # +---------------+
        # | Title         |
        # +---------------+
        # | H |:| M |:| S |
        # +---+-+---+-+---+
        # .cell(row, col)
        set_cell_margins(self.cell_object.cell, {"top": 50})
        table = self.cell_object.cell.add_table(rows=2, cols=5)
        if DEBUG:
            table.style = 'Table Grid'

        title_cell = table.cell(0, 0)
        style_cell(title_cell)
        title_cell.merge(table.cell(0, 4))

        title = DEFAULT_DURATION_TITLE

        if 'title' in self.section.extra:
            title = self.section.extra['title']
        elif len(contents
                 ) > 0 and 'name' in contents[0] and contents[0]['name'] != '':
            title = contents['data']['name']

        insert_text(title_cell, title, self.style['title'])

        # Days
        days_cell = table.cell(1, 0)
        style_cell(days_cell)
        insert_text(days_cell, days, self.style['duration'])
        insert_text(days_cell,
                    DURATION_DAYS_LABEL,
                    self.style['label'],
                    add_run=True)

        # Add first colon
        colon_right = table.cell(1, 1)
        style_cell(colon_right)
        insert_text(colon_right, ':', self.style['duration'])

        # Hours
        hours_cell = table.cell(1, 2)
        style_cell(hours_cell)
        insert_text(hours_cell, hours, self.style['duration'])
        insert_text(hours_cell,
                    DURATION_HOURS_LABEL,
                    self.style['label'],
                    add_run=True)

        # Add second colon
        colon_left = table.cell(1, 3)
        style_cell(colon_left)
        insert_text(colon_left, ':', self.style['duration'])

        # Minutes
        minutes_cell = table.cell(1, 4)
        style_cell(minutes_cell)
        insert_text(minutes_cell,
                    minutes,
                    self.style['duration'],
                    add_run=True)
        insert_text(minutes_cell,
                    DURATION_MINUTES_LABEL,
                    self.style['label'],
                    add_run=True)
Esempio n. 18
0
    def insert(self):
        if DEBUG:
            print("Adding table...")

        table_data = self.section.contents

        if isinstance(table_data, dict):
            table_data = table_data.get('data', table_data)

        if 'tableColumns' not in self.section.layout:
            # Quick dirty fix for test - will be refactored in upcoming PR
            self.section.layout['tableColumns'] = list(table_data[0].keys())

        # Fix new lists
        if isinstance(table_data, dict):
            wrapper_table = self.cell_object.cell.add_table(
                rows=2, cols=len(table_data.keys()))
            i = 0

            # Add the wrapping headers
            for wrapper_header, table_contents in table_data.items():
                hdr = wrapper_table.cell(0, i)
                insert_text(hdr, wrapper_header, self.style['title'])
                body = wrapper_table.cell(1, i)
                c = CellObject(body)
                # Hacky but will do the job
                invoke(c, Section('table', table_contents, {}, {}))
                i += 1
            return

        if 'readableHeaders' in self.section.layout:
            ordered = self.section.layout['tableColumns']
            readable_headers = self.section.layout['readableHeaders']
            table_columns = fix_order(ordered, readable_headers)
        else:
            table_columns = self.section.layout['tableColumns']

        # Quick fix, word crashes on more than 64 columns.
        # See: https://stackoverflow.com/questions/36921010/docx-does-not-support-more-than-63-columns-in-a-table
        table_columns = table_columns[0:63]

        for i, header_text in enumerate(table_columns):
            if not isinstance(header_text, str):
                table_columns.remove(header_text)

        if 'title' in self.section.extra:
            table = self.cell_object.cell.add_table(rows=2,
                                                    cols=len(table_columns))
            title = table.cell(0, 0)
            title.merge(table.cell(0, len(table_columns) - 1))
            insert_text(title, self.section.extra['title'],
                        self.style['title'])

            hdr_cells = table.rows[1].cells
        else:
            table = self.cell_object.cell.add_table(rows=2,
                                                    cols=len(table_columns))
            hdr_cells = table.rows[0].cells

        table.style = DEFAULT_TABLE_STYLE

        if 'list_style' in self.section.extra and self.section.extra[
                'list_style']:
            table.style = None

        for i, header_text in enumerate(table_columns):
            insert_text(hdr_cells[i], header_text, self.style['text'])

        if len(table_columns) > 63:
            # TODO: add error.
            pass

        for r in table_data:
            row_cells = table.add_row().cells
            for i, header_text in enumerate(table_columns):
                if header_text not in r:
                    continue

                # Old json format can have 'Avatars', which are images
                if isinstance(r[header_text], dict) and \
                        r[header_text]['type'] == 'image':
                    row_temp = r[header_text]
                    s = Section(row_temp['type'], row_temp['data'], {}, {})
                    co = CellObject(row_cells[i], add_run=False)
                    image.invoke(co, s)
                else:
                    insert_text(row_cells[i], r[header_text],
                                self.style['text'])