From c0d5c7d649c4e0401c9a5260dfbba12bedf48a28 Mon Sep 17 00:00:00 2001 From: Michael Wedl Date: Tue, 13 Feb 2024 09:17:28 +0100 Subject: [PATCH 1/2] Predefined component for cover page --- .../components/Design/LayoutComponentForm.vue | 11 +- .../components/Design/designer-components.ts | 184 +++++++++--------- rendering/src/components/Wrapper.vue | 9 + rendering/src/main.js | 3 +- 4 files changed, 115 insertions(+), 92 deletions(-) create mode 100644 rendering/src/components/Wrapper.vue diff --git a/frontend/src/components/Design/LayoutComponentForm.vue b/frontend/src/components/Design/LayoutComponentForm.vue index fc35c4295..4a87f079c 100644 --- a/frontend/src/components/Design/LayoutComponentForm.vue +++ b/frontend/src/components/Design/LayoutComponentForm.vue @@ -162,7 +162,14 @@ You can add and style the remaining fields afterwards in HTML.

- + diff --git a/frontend/src/components/Design/designer-components.ts b/frontend/src/components/Design/designer-components.ts index cf46973dd..8fe8212f4 100644 --- a/frontend/src/components/Design/designer-components.ts +++ b/frontend/src/components/Design/designer-components.ts @@ -813,7 +813,7 @@ export class PageHeaderComponent extends DesignerComponentBase { } const id = createUniqueId('header', context); - let html = `
\n`; + let html = `\n`; let css = trimLeadingWhitespace(` @page { margin-top: 35mm; @@ -864,7 +864,7 @@ export class PageHeaderComponent extends DesignerComponentBase { css += `#${id}-right { height: 100%; width: auto; }\n#${id}-right img { width: auto; height: auto; }\n`; } } - html += '
\n'; + html += '\n'; return { html, css: `/* #region ${id} */\n${css}/* #endregion ${id} */`, @@ -894,7 +894,7 @@ export class PageFooterComponent extends DesignerComponentBase { createCode(form: any, context: DesignerContext) { const id = createUniqueId('footer', context); - let html = `
\n`; + let html = `\n`; let css = ``; let cssPage = ''; if (form.footer.textLeft) { @@ -914,7 +914,7 @@ export class PageFooterComponent extends DesignerComponentBase { }; cssPage += ` @bottom-right-corner { content: ${counterContents[form.footer.pageNumberStyle]}; }\n`; } - html += '
'; + html += ''; if (cssPage) { css = `@page {\n${cssPage}}\n` + css; } @@ -932,91 +932,96 @@ export class CoverPageComponent extends DesignerComponentBase { return tagInfo.attributes['data-sysreptor-generated']?.value === 'page-cover'; } - // TODO: cover page: how to integrate with headers/footers - // getCreateForm() { - // return { - // form: 'page-cover-create', - // coverPage: { - // // backgroundColor: null, - // // backgroundImage: null, - // hideHeader: true, - // hideFooter: true, - // } - // }; - // } - - // createCode(form: any, context: DesignerContext) { - // const id = createUniqueId('page-cover', context); - // const html = trimLeadingWhitespace(` - //
- //
- //

PENTEST REPORT

- //

{{ report.title }}

- //
- //
- //

- // Customer:
- // ${'customer' in context.projectType.report_fields ? '{{ report.customer }}' : 'Example Customer'}
- // ${'document_history' in context.projectType.report_fields ? - // "{{ report.document_history[report.document_history.length - 1]?.date || '' }}
" + - // "{{ report.document_history[report.document_history.length - 1]?.version || '0.0' }}
" : "" - // } - //

- //
- // - //
- // `); - - // let pageCss = ''; - // // if (form.coverPage.backgroundColor) { - // // pageCss += ` background-color: ${form.coverPage.backgroundColor};\n\n`; - // // } - // if (form.coverPage.hideHeader) { - // pageCss += ' /* Hide header */\n'; - // pageCss += ' @top-left-corner { content: none !important; }\n'; - // pageCss += ' @top-left { content: none !important; }\n'; - // pageCss += ' @top-center { content: none !important; }\n'; - // pageCss += ' @top-right { content: none !important; }\n'; - // pageCss += ' @top-right-corner { content: none !important; }\n'; - // } - // if (form.coverPage.hideFooter) { - // pageCss += ' /* Hide footer */\n'; - // pageCss += ' @bottom-left-corner { content: none !important; }\n'; - // pageCss += ' @bottom-left { content: none !important; }\n'; - // pageCss += ' @bottom-center { content: none !important; }\n'; - // pageCss += ' @bottom-right { content: none !important; }\n'; - // pageCss += ' @bottom-right-corner { content: none !important; }\n'; - // } - - // let css = trimLeadingWhitespace(` - // #${id} { - // page: ${id}; - // } - // `) + '\n'; - // if (pageCss) { - // css += `@page ${id} {\n${pageCss}}\n`; - // } - - // css += trimLeadingWhitespace(` - // #${id} .page-cover-title { - // position: absolute; - // top: 20mm; - // left: 0; - // width: 14cm; - // } - // #${id} .page-cover-customer { - // position: absolute; - // top: 11cm; - // left: 0; - // width: 14cm; - // } - // `) + '\n'; - - // return { - // html, - // css: `/* #region ${id} */\n${css}/* #endregion ${id} */`, - // }; - // } + getCreateForm() { + return { + form: 'page-cover-create', + coverPage: { + background: null, + hideHeader: true, + hideFooter: true, + } + }; + } + + createCode(form: any, context: DesignerContext) { + const id = createUniqueId('page-cover', context); + const html = trimLeadingWhitespace(` +
+
+

PENTEST REPORT

+

{{ report.title }}

+
+
+

+ Customer:
+ ${'customer' in context.projectType.report_fields ? '{{ report.customer }}' : 'Example Customer'}
+ ${'document_history' in context.projectType.report_fields ? + "{{ report.document_history[report.document_history.length - 1]?.date || '' }}
" + + "{{ report.document_history[report.document_history.length - 1]?.version || '0.0' }}
" : "" + } +

+
+ +
+ `); + + let pageCss = ''; + if (form.coverPage.background === 'color') { + pageCss += ` background-color: #ff0000;\n\n`; + } + if (form.coverPage.background === 'image') { + pageCss += ` background-image: url("/assets/name/background.png");\n`; + pageCss += ` background-repeat: no-repeat;\n`; + pageCss += ` background-size: cover;\n`; + pageCss += ` background-position: center;\n` + pageCss += ` background-attachment: fixed;\n\n`; + } + if (form.coverPage.hideHeader) { + pageCss += ' /* Hide header */\n'; + pageCss += ' @top-left-corner { content: none !important; }\n'; + pageCss += ' @top-left { content: none !important; }\n'; + pageCss += ' @top-center { content: none !important; }\n'; + pageCss += ' @top-right { content: none !important; }\n'; + pageCss += ' @top-right-corner { content: none !important; }\n'; + } + if (form.coverPage.hideFooter) { + pageCss += ' /* Hide footer */\n'; + pageCss += ' @bottom-left-corner { content: none !important; }\n'; + pageCss += ' @bottom-left { content: none !important; }\n'; + pageCss += ' @bottom-center { content: none !important; }\n'; + pageCss += ' @bottom-right { content: none !important; }\n'; + pageCss += ' @bottom-right-corner { content: none !important; }\n'; + } + + let css = trimLeadingWhitespace(` + #${id} { + page: ${id}; + } + `) + '\n'; + if (pageCss) { + css += `@page ${id} {\n${pageCss}}\n`; + } + + css += trimLeadingWhitespace(` + #${id} .page-cover-title { + position: absolute; + top: 20mm; + left: 0; + width: 14cm; + } + #${id} .page-cover-customer { + position: absolute; + top: 11cm; + left: 0; + width: 14cm; + } + `) + '\n'; + + return { + html, + css: `/* #region ${id} */\n${css}/* #endregion ${id} */`, + }; + } } export const unknownComponent = new DesignerComponentBase({ type: 'unknown', name: 'Code' }); @@ -1048,6 +1053,7 @@ export const predefinedDesignerComponentGroups = [ components: [ new PageHeaderComponent(), new PageFooterComponent(), + new CoverPageComponent(), ], }, { diff --git a/rendering/src/components/Wrapper.vue b/rendering/src/components/Wrapper.vue new file mode 100644 index 000000000..1f0588245 --- /dev/null +++ b/rendering/src/components/Wrapper.vue @@ -0,0 +1,9 @@ + + + diff --git a/rendering/src/main.js b/rendering/src/main.js index 4528c0d06..f75c44813 100644 --- a/rendering/src/main.js +++ b/rendering/src/main.js @@ -10,6 +10,7 @@ import ListOfTables from './components/ListOfTables.vue'; import Chart from './components/ChartVue.vue'; import MermaidDiagram from './components/MermaidDiagram.vue'; import Ref from './components/Ref.vue'; +import Wrapper from './components/Wrapper.vue'; import { callForTicks } from './utils'; import lodash from 'lodash'; @@ -133,7 +134,7 @@ if (!window.RENDERING_COMPLETED) { const app = createApp({ name: 'root', render: RENDER_FUNCTION, - components: { Pagebreak, Markdown, CommaAndJoin, TableOfContents, ListOfFigures, ListOfTables, Chart, MermaidDiagram, Ref }, + components: { Pagebreak, Markdown, CommaAndJoin, TableOfContents, ListOfFigures, ListOfTables, Chart, MermaidDiagram, Ref, Wrapper }, data: () => ({ data: REPORT_DATA, _tickCount: 0, From b2e8c4c49004078501482b129695192897659de8 Mon Sep 17 00:00:00 2001 From: Michael Wedl Date: Tue, 13 Feb 2024 14:24:54 +0100 Subject: [PATCH 2/2] CSS instead of wrapper for header/footer --- frontend/src/components/Design/designer-components.ts | 11 ++++++----- rendering/src/components/Wrapper.vue | 9 --------- rendering/src/main.js | 3 +-- 3 files changed, 7 insertions(+), 16 deletions(-) delete mode 100644 rendering/src/components/Wrapper.vue diff --git a/frontend/src/components/Design/designer-components.ts b/frontend/src/components/Design/designer-components.ts index 8fe8212f4..da6e5bbb8 100644 --- a/frontend/src/components/Design/designer-components.ts +++ b/frontend/src/components/Design/designer-components.ts @@ -813,7 +813,7 @@ export class PageHeaderComponent extends DesignerComponentBase { } const id = createUniqueId('header', context); - let html = `\n`; + let html = `
\n`; let css = trimLeadingWhitespace(` @page { margin-top: 35mm; @@ -849,6 +849,7 @@ export class PageHeaderComponent extends DesignerComponentBase { } } + #${id} { position: absolute; width: 0; } `) + '\n'; if (form.header.left) { html += `
\n${getHeaderTypeContent(form.header.left)}\n
\n`; @@ -864,7 +865,7 @@ export class PageHeaderComponent extends DesignerComponentBase { css += `#${id}-right { height: 100%; width: auto; }\n#${id}-right img { width: auto; height: auto; }\n`; } } - html += '\n'; + html += '
\n'; return { html, css: `/* #region ${id} */\n${css}/* #endregion ${id} */`, @@ -894,8 +895,8 @@ export class PageFooterComponent extends DesignerComponentBase { createCode(form: any, context: DesignerContext) { const id = createUniqueId('footer', context); - let html = `\n`; - let css = ``; + let html = `
\n`; + let css = `#${id} { position: absolute; width: 0; }\n`; let cssPage = ''; if (form.footer.textLeft) { html += `
${form.footer.textLeft}
\n`; @@ -914,7 +915,7 @@ export class PageFooterComponent extends DesignerComponentBase { }; cssPage += ` @bottom-right-corner { content: ${counterContents[form.footer.pageNumberStyle]}; }\n`; } - html += ''; + html += '
'; if (cssPage) { css = `@page {\n${cssPage}}\n` + css; } diff --git a/rendering/src/components/Wrapper.vue b/rendering/src/components/Wrapper.vue deleted file mode 100644 index 1f0588245..000000000 --- a/rendering/src/components/Wrapper.vue +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/rendering/src/main.js b/rendering/src/main.js index f75c44813..4528c0d06 100644 --- a/rendering/src/main.js +++ b/rendering/src/main.js @@ -10,7 +10,6 @@ import ListOfTables from './components/ListOfTables.vue'; import Chart from './components/ChartVue.vue'; import MermaidDiagram from './components/MermaidDiagram.vue'; import Ref from './components/Ref.vue'; -import Wrapper from './components/Wrapper.vue'; import { callForTicks } from './utils'; import lodash from 'lodash'; @@ -134,7 +133,7 @@ if (!window.RENDERING_COMPLETED) { const app = createApp({ name: 'root', render: RENDER_FUNCTION, - components: { Pagebreak, Markdown, CommaAndJoin, TableOfContents, ListOfFigures, ListOfTables, Chart, MermaidDiagram, Ref, Wrapper }, + components: { Pagebreak, Markdown, CommaAndJoin, TableOfContents, ListOfFigures, ListOfTables, Chart, MermaidDiagram, Ref }, data: () => ({ data: REPORT_DATA, _tickCount: 0,