diff --git a/index.json b/index.json index 418f425..0579a66 100644 --- a/index.json +++ b/index.json @@ -12,12 +12,8 @@ "download_url": "https://raw.githubusercontent.com/amidaware/reporting-templates/master/templates/Agent%20List_By%20Client%20%28pdf%29.json" }, { - "name": "Agent List_By Client with Specs (pdf)", - "download_url": "https://raw.githubusercontent.com/amidaware/reporting-templates/master/templates/Agent%20List_By%20Client%20with%20Specs%20%28pdf%29.json" - }, - { - "name": "Agent List_By Client with Specs MultiColour(pdf)", - "download_url": "https://raw.githubusercontent.com/amidaware/reporting-templates/master/templates/Agent%20List_By%20Client%20with%20Specs%20MultiColour%28pdf%29.json" + "name": "Agent List_By Client with Specs (pdf) v1.2", + "download_url": "https://raw.githubusercontent.com/amidaware/reporting-templates/master/templates/Agent%20List_By%20Client%20with%20Specs%20%28pdf%29%20v1.2.json" }, { "name": "Agent Specs", @@ -124,24 +120,24 @@ "download_url": "https://raw.githubusercontent.com/amidaware/reporting-templates/master/templates/All%20Fields%20-%20Windows%20Update%20Policies.json" }, { - "name": "All Fields - Windows Update_Per Site (csv)", - "download_url": "https://raw.githubusercontent.com/amidaware/reporting-templates/master/templates/All%20Fields%20-%20Windows%20Update_Per%20Site%20%28csv%29.json" + "name": "All Fields - Windows Update_By Site (csv)", + "download_url": "https://raw.githubusercontent.com/amidaware/reporting-templates/master/templates/All%20Fields%20-%20Windows%20Update_By%20Site%20%28csv%29.json" }, { "name": "All Fields - Windows Updates", "download_url": "https://raw.githubusercontent.com/amidaware/reporting-templates/master/templates/All%20Fields%20-%20Windows%20Updates.json" }, { - "name": "All Fields Windows Update_Per Device (csv)", - "download_url": "https://raw.githubusercontent.com/amidaware/reporting-templates/master/templates/All%20Fields%20Windows%20Update_Per%20Device%20%28csv%29.json" + "name": "All Fields Windows Update_By Device (csv)", + "download_url": "https://raw.githubusercontent.com/amidaware/reporting-templates/master/templates/All%20Fields%20Windows%20Update_By%20Device%20%28csv%29.json" }, { - "name": "All Fields Windows Update_Per Site (csv)", - "download_url": "https://raw.githubusercontent.com/amidaware/reporting-templates/master/templates/All%20Fields%20Windows%20Update_Per%20Site%20%28csv%29.json" + "name": "All Fields Windows Update_By Site (csv)", + "download_url": "https://raw.githubusercontent.com/amidaware/reporting-templates/master/templates/All%20Fields%20Windows%20Update_By%20Site%20%28csv%29.json" }, { - "name": "All Fields Windows Update_Per Site w-sort (csv)", - "download_url": "https://raw.githubusercontent.com/amidaware/reporting-templates/master/templates/All%20Fields%20Windows%20Update_Per%20Site%20w-sort%20%28csv%29.json" + "name": "All Fields Windows Update_By Site w-sort (csv)", + "download_url": "https://raw.githubusercontent.com/amidaware/reporting-templates/master/templates/All%20Fields%20Windows%20Update_By%20Site%20w-sort%20%28csv%29.json" }, { "name": "Antivirus Report", @@ -232,20 +228,20 @@ "download_url": "https://raw.githubusercontent.com/amidaware/reporting-templates/master/templates/WIP-Dashboard%20Demo.json" }, { - "name": "Windows 11 Compatible List fixed (csv)", - "download_url": "https://raw.githubusercontent.com/amidaware/reporting-templates/master/templates/Windows%2011%20Compatible%20List%20fixed%20%28csv%29.json" + "name": "Windows 11 Compatible List_By Client (csv)", + "download_url": "https://raw.githubusercontent.com/amidaware/reporting-templates/master/templates/Windows%2011%20Compatible%20List_By%20Client%20%28csv%29.json" }, { "name": "Windows 11 Compatible List_By Client (html) v1.8", "download_url": "https://raw.githubusercontent.com/amidaware/reporting-templates/master/templates/Windows%2011%20Compatible%20List_By%20Client%20%28html%29%20v1.8.json" }, { - "name": "Windows Update Not Installed _By Client", - "download_url": "https://raw.githubusercontent.com/amidaware/reporting-templates/master/templates/Windows%20Update%20Not%20Installed%20_By%20Client.json" + "name": "Windows Update Not Installed_By Client", + "download_url": "https://raw.githubusercontent.com/amidaware/reporting-templates/master/templates/Windows%20Update%20Not%20Installed_By%20Client.json" }, { - "name": "Windows Update Not Installed _By Client (csv)", - "download_url": "https://raw.githubusercontent.com/amidaware/reporting-templates/master/templates/Windows%20Update%20Not%20Installed%20_By%20Client%20%28csv%29.json" + "name": "Windows Update Not Installed_By Client (csv)", + "download_url": "https://raw.githubusercontent.com/amidaware/reporting-templates/master/templates/Windows%20Update%20Not%20Installed_By%20Client%20%28csv%29.json" }, { "name": "Windows Update_Last Install Date (csv)", diff --git a/templates/Agent List_By Client with Specs (pdf).json b/templates/Agent List_By Client with Specs (pdf) v1.2.json similarity index 63% rename from templates/Agent List_By Client with Specs (pdf).json rename to templates/Agent List_By Client with Specs (pdf) v1.2.json index d906d0d..273a1ef 100644 --- a/templates/Agent List_By Client with Specs (pdf).json +++ b/templates/Agent List_By Client with Specs (pdf) v1.2.json @@ -4,9 +4,9 @@ "html": "\n \n \n \n \n {% block content %}{% endblock %}\n \n" }, "template": { - "name": "Agent List_By Client with Specs (pdf)", - "template_css": "@font-face {\r\n font-family: Fira Sans;\r\n font-weight: 400;\r\n src: url(https://raw.githubusercontent.com/CourtBouillon/weasyprint-samples/master/report/firasans-regular.otf);\r\n}\r\n@font-face {\r\n font-family: Fira Sans;\r\n font-style: italic;\r\n font-weight: 400;\r\n src: url(https://raw.githubusercontent.com/CourtBouillon/weasyprint-samples/master/report/firasans-italic.otf);\r\n}\r\n@font-face {\r\n font-family: Fira Sans;\r\n font-weight: 300;\r\n src: url(https://raw.githubusercontent.com/CourtBouillon/weasyprint-samples/master/report/firasans-light.otf);\r\n}\r\n@font-face {\r\n font-family: Fira Sans;\r\n font-style: italic;\r\n font-weight: 300;\r\n src: url(https://raw.githubusercontent.com/CourtBouillon/weasyprint-samples/master/report/firasans-lightitalic.otf);\r\n}\r\n@font-face {\r\n font-family: Fira Sans;\r\n font-weight: 700;\r\n src: url(https://raw.githubusercontent.com/CourtBouillon/weasyprint-samples/master/report/firasans-bold.otf);\r\n}\r\n\r\n@page {\r\n \r\n @top-left {\r\n background: #ffcc00;\r\n content: \"\";\r\n height: 50px;\r\n width: 50px;\r\n position: absolute;\r\n top: 0;\r\n left: 0;\r\n background-image: url('https://github.com/amidaware/reporting-templates/blob/471b2d34fae8029d8c05b6c3d000c027648a07e4/assets/2orig1%20(256).png?raw=true');\r\n background-size: cover;\r\n background-repeat: no-repeat;\r\n background-position: center;\r\n }\r\n @top-center {\r\n background: #ffcc00;\r\n content: '';\r\n display: block;\r\n height: .05cm;\r\n opacity: .5;\r\n width: 100%;\r\n }\r\n \r\n @bottom-left {\r\n background: #ffcc00;\r\n content: counter(page);\r\n height: 1cm;\r\n text-align: center;\r\n width: 1cm;\r\n }\r\n @bottom-center {\r\n background: #ffcc00;\r\n content: '';\r\n display: block;\r\n height: .05cm;\r\n opacity: .5;\r\n width: 100%;\r\n }\r\n @bottom-right {\r\n content: string(heading);\r\n font-size: 9pt;\r\n height: 1cm;\r\n vertical-align: middle;\r\n width: 100%;\r\n }\r\n}\r\n@page :blank {\r\n @top-left { background: none; content: '' }\r\n @top-center { content: none }\r\n @top-right { content: none }\r\n}\r\n@page no-chapter {\r\n @top-left { background: none; content: none }\r\n @top-center { content: none }\r\n @top-right { content: none }\r\n}\r\n@page :first {\r\n background: url(https://raw.githubusercontent.com/CourtBouillon/weasyprint-samples/master/report/report-cover.jpg) no-repeat center;\r\n background-size: cover;\r\n margin: 0;\r\n}\r\n@page chapter {\r\n background: #ffcc00;\r\n margin: 0;\r\n @top-left { content: none }\r\n @top-center { content: none }\r\n @top-right { content: none }\r\n}\r\n\r\nhtml {\r\n color: #393939;\r\n font-family: Fira Sans;\r\n font-size: 11pt;\r\n font-weight: 300;\r\n line-height: 1.5;\r\n}\r\n\r\nh1 {\r\n color: #ffcc00;\r\n font-size: 38pt;\r\n margin: 5cm 2cm 0 2cm;\r\n page: no-chapter;\r\n width: 100%;\r\n}\r\nh2, h3, h4 {\r\n color: black;\r\n font-weight: 400;\r\n}\r\nh2 {\r\n break-before: always;\r\n font-size: 28pt;\r\n string-set: heading content();\r\n}\r\nh3 {\r\n font-weight: 300;\r\n font-size: 15pt;\r\n}\r\nh4 {\r\n font-size: 13pt;\r\n}\r\n\r\n#cover {\r\n align-content: space-between;\r\n display: flex;\r\n flex-wrap: wrap;\r\n height: 297mm;\r\n}\r\n#cover address {\r\n background: #ffcc00;\r\n flex: 1 50%;\r\n margin: 0 -2cm;\r\n padding: 1cm 0;\r\n white-space: pre-wrap;\r\n}\r\n#cover address:first-of-type {\r\n padding-left: 3cm;\r\n}\r\n#contents {\r\n page: no-chapter;\r\n}\r\n#contents h2 {\r\n font-size: 20pt;\r\n font-weight: 400;\r\n margin-bottom: 3cm;\r\n}\r\n#contents h3 {\r\n font-weight: 500;\r\n margin: 3em 0 1em;\r\n}\r\n#contents h3::before {\r\n background: #ffcc00;\r\n content: '';\r\n display: block;\r\n height: .08cm;\r\n margin-bottom: .25cm;\r\n width: 2cm;\r\n}\r\n#contents ul {\r\n list-style: none;\r\n padding-left: 0;\r\n}\r\n#contents ul li {\r\n border-top: .25pt solid #c1c1c1;\r\n margin: .25cm 0;\r\n padding-top: .25cm;\r\n}\r\n#contents ul li::before {\r\n color: #ffcc00;\r\n content: '• ';\r\n font-size: 40pt;\r\n line-height: 16pt;\r\n vertical-align: bottom;\r\n}\r\n#contents ul li a {\r\n color: inherit;\r\n text-decoration-line: inherit;\r\n}\r\n#contents ul li a::before {\r\n content: target-text(attr(href));\r\n}\r\n#contents ul li a::after {\r\n color: #ffcc00;\r\n content: target-counter(attr(href), page);\r\n float: right;\r\n}\r\n\r\n#columns section {\r\n columns: 2;\r\n column-gap: 1cm;\r\n padding-top: 1cm;\r\n}\r\n#columns section p {\r\n text-align: justify;\r\n}\r\n#columns section p:first-of-type {\r\n font-weight: 700;\r\n}\r\n\r\n#skills h3 {\r\n background: #ffcc00;\r\n margin: 0 -3cm 1cm;\r\n padding: 1cm 1cm 1cm 3cm;\r\n width: 21cm;\r\n}\r\n#skills section {\r\n padding: .5cm 0;\r\n}\r\ntable.GeneratedTable {\r\n width: 100%;\r\n background-color: #ffffff;\r\n border-collapse: collapse;\r\n border-width: 2px;\r\n border-color: #ffcc00;\r\n border-style: solid;\r\n color: #000000;\r\n}\r\n\r\ntable.GeneratedTable td, table.GeneratedTable th {\r\n border-width: 2px;\r\n border-color: #ffcc00;\r\n border-style: solid;\r\n padding: 3px;\r\n}\r\n\r\ntable.GeneratedTable thead {\r\n background-color: #ffcc00;\r\n}\r\n#skills section#tablecontent::before {\r\n background: url(https://raw.githubusercontent.com/CourtBouillon/weasyprint-samples/master/report/table-content.svg) no-repeat center #ffcc00;\r\n background-size: 50%;\r\n content: '';\r\n display: inline-block;\r\n float: left;\r\n height: 2cm;\r\n margin-right: .5cm;\r\n vertical-align: middle;\r\n width: 2cm;\r\n}\r\n#skills section#heading::before {\r\n background: url(https://raw.githubusercontent.com/CourtBouillon/weasyprint-samples/master/report/heading.svg) no-repeat center #ffcc00;\r\n background-size: 50%;\r\n content: '';\r\n display: inline-block;\r\n float: left;\r\n height: 2cm;\r\n margin-right: .5cm;\r\n vertical-align: middle;\r\n width: 2cm;\r\n}\r\n#skills section#multicolumns::before {\r\n background: url(https://raw.githubusercontent.com/CourtBouillon/weasyprint-samples/master/report/multi-columns.svg) no-repeat center #ffcc00;\r\n background-size: 50%;\r\n content: '';\r\n display: inline-block;\r\n float: left;\r\n height: 2cm;\r\n margin-right: .5cm;\r\n vertical-align: middle;\r\n width: 2cm;\r\n}\r\n#skills section#internallinks::before {\r\n background: url(https://raw.githubusercontent.com/CourtBouillon/weasyprint-samples/master/report/internal-links.svg) no-repeat center #ffcc00;\r\n background-size: 50%;\r\n content: '';\r\n display: inline-block;\r\n float: left;\r\n height: 2cm;\r\n margin-right: .5cm;\r\n vertical-align: middle;\r\n width: 2cm;\r\n}\r\n#skills section#style::before {\r\n background: url(https://raw.githubusercontent.com/CourtBouillon/weasyprint-samples/master/report/style.svg) no-repeat center #ffcc00;\r\n background-size: 50%;\r\n content: '';\r\n display: inline-block;\r\n float: left;\r\n height: 2cm;\r\n margin-right: .5cm;\r\n vertical-align: middle;\r\n width: 2cm;\r\n}\r\n#skills section h4 {\r\n margin: 0;\r\n}\r\n#skills section p {\r\n margin-top: 0;\r\n}\r\n\r\n#offers {\r\n display: flex;\r\n flex-wrap: wrap;\r\n justify-content: space-between;\r\n}\r\n#offers h2, #offers h3 {\r\n width: 100%;\r\n}\r\n#offers section {\r\n width: 30%;\r\n}\r\n#offers section h4 {\r\n margin-bottom: 0;\r\n}\r\n#offers section ul {\r\n list-style: none;\r\n margin: 0;\r\n padding-left: 0;\r\n}\r\n#offers section ul li:not(:last-of-type) {\r\n margin: .5cm 0;\r\n}\r\n#offers section p {\r\n background: #ffcc00;\r\n display: block;\r\n font-size: 15pt;\r\n font-weight: 700;\r\n margin-bottom: 0;\r\n padding: .25cm 0;\r\n text-align: center;\r\n}\r\n\r\n#chapter {\r\n align-items: center;\r\n display: flex;\r\n height: 297mm;\r\n justify-content: center;\r\n page: chapter;\r\n}\r\n\r\n#typography section {\r\n display: flex;\r\n flex-wrap: wrap;\r\n margin: 1cm 0;\r\n}\r\n#typography section h4 {\r\n border-top: 1pt solid;\r\n flex: 1 25%;\r\n margin: 0;\r\n}\r\n#typography section h4 + * {\r\n flex: 1 75%;\r\n margin: 0;\r\n padding-left: .5cm;\r\n}\r\n#typography section p {\r\n text-align: justify;\r\n}\r\n#typography section ul {\r\n line-height: 2;\r\n list-style: none;\r\n}\r\n#typography section#smallcaps p {\r\n font-variant: small-caps;\r\n}\r\n#typography section#ligatures dl {\r\n display: flex;\r\n flex-wrap: wrap;\r\n}\r\n#typography section#ligatures dl dt {\r\n font-weight: 400;\r\n width: 30%;\r\n}\r\n#typography section#ligatures dl dd {\r\n flex: 1 70%;\r\n margin: 0;\r\n padding: 0;\r\n}\r\n#typography section#ligatures .none {\r\n font-variant-ligatures: none;\r\n}\r\n#typography section#ligatures .common {\r\n font-variant-ligatures: common-ligatures;\r\n}\r\n#typography section#ligatures .discretionary {\r\n font-variant-ligatures: discretionary-ligatures;\r\n}\r\n#typography section#ligatures .contextual {\r\n font-variant-ligatures: contextual;\r\n}\r\n#typography section#numbers dl {\r\n display: flex;\r\n flex-wrap: wrap;\r\n}\r\n#typography section#numbers dl dt {\r\n font-weight: 400;\r\n width: 30%;\r\n}\r\n#typography section#numbers dl dd {\r\n flex: 1 70%;\r\n margin: 0;\r\n padding: 0;\r\n}\r\n#typography section#numbers #fractions {\r\n font-variant-numeric: diagonal-fractions;\r\n}\r\n#typography section#numbers #ordinals {\r\n font-variant-numeric: ordinal;\r\n}\r\n#typography section#numbers #slashed {\r\n font-variant-numeric: slashed-zero;\r\n}\r\n#typography section#numbers #super {\r\n font-variant-position: super;\r\n}\r\n#typography section#numbers #sub {\r\n font-variant-position: sub;\r\n}\r\n#typography section#figures dl {\r\n columns: 4;\r\n}\r\n#typography section#figures dl dt {\r\n font-weight: 400;\r\n}\r\n#typography section#figures dl dd {\r\n display: flex;\r\n margin: 0;\r\n padding: 0;\r\n}\r\n#typography section#figures dl dd ul {\r\n padding: 0 1em 0 0;\r\n}\r\n#typography section#figures #oldstyle {\r\n font-variant-numeric: oldstyle-nums;\r\n}", - "template_md": "{% block content %}\r\n~~A cover~~\r\n# Agent List for {{client.name}}\r\n
\r\nCompany\r\n123 anywhere st\r\nCity, State zip\r\n
\r\n
\r\nme@here.com\r\nhttps://example.com\r\n
\r\n~~/A~~\r\n~~A~~\r\n{{ client.name }} Agents List\r\n\r\n \r\n\r\n\r\n\r\n\r\n \r\n \r\n {% for item in data_sources.agentAllFields %}\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n {% endfor %}\r\n \r\n
Agent\r\nInfo
\r\n
Site Name
\r\n
Name:\r\nUser:\r\nOS:\r\nLast Seen:
\r\n
\r\n{{ item.hostname }}
\r\n{{ item.last_logged_in_user }}
\r\n{{ (item.operating_system.split(',')[0] if item.operating_system else 'N/A') }}
\r\n{{ item.last_seen.strftime('%Y-%m-%d %H:%M') }}
\r\n
\r\nCPU:
\r\n\r\nRAM:
\r\n\r\nDisks:
\r\n
\r\n{{ (item.wmi_detail.cpu[0][0].Name.replace('(R)', '').replace('(TM)', '').split('@')[0].strip() if item.wmi_detail and item.wmi_detail.cpu and item.wmi_detail.cpu[0][0].Name else 'N/A') }}
\r\n{{ item.total_ram }}GB
\r\n{% for disk in item.disks %}{% if not loop.previtem or loop.previtem.device != disk.device %} {{disk.device}} {{disk.total}}{% endif %}{% else %}N/A{% endfor %}
\r\n
{{item.site__name}}
\r\n~~/A~~\r\n{% endblock %}", + "name": "Agent List_By Client with Specs (pdf) v1.2", + "template_css": "@font-face {\r\n font-family: Fira Sans;\r\n font-weight: 400;\r\n src: url(https://raw.githubusercontent.com/CourtBouillon/weasyprint-samples/master/report/firasans-regular.otf);\r\n}\r\n@font-face {\r\n font-family: Fira Sans;\r\n font-style: italic;\r\n font-weight: 400;\r\n src: url(https://raw.githubusercontent.com/CourtBouillon/weasyprint-samples/master/report/firasans-italic.otf);\r\n}\r\n@font-face {\r\n font-family: Fira Sans;\r\n font-weight: 300;\r\n src: url(https://raw.githubusercontent.com/CourtBouillon/weasyprint-samples/master/report/firasans-light.otf);\r\n}\r\n@font-face {\r\n font-family: Fira Sans;\r\n font-style: italic;\r\n font-weight: 300;\r\n src: url(https://raw.githubusercontent.com/CourtBouillon/weasyprint-samples/master/report/firasans-lightitalic.otf);\r\n}\r\n@font-face {\r\n font-family: Fira Sans;\r\n font-weight: 700;\r\n src: url(https://raw.githubusercontent.com/CourtBouillon/weasyprint-samples/master/report/firasans-bold.otf);\r\n}\r\n\r\n@page {\r\n size: landscape;\r\n @top-left {\r\n background: #ffcc00;\r\n content: \"\";\r\n height: 50px;\r\n width: 50px;\r\n position: absolute;\r\n top: 0;\r\n left: 0;\r\n background-image: url('https://github.com/amidaware/reporting-templates/blob/471b2d34fae8029d8c05b6c3d000c027648a07e4/assets/2orig1%20(256).png?raw=true');\r\n background-size: cover;\r\n background-repeat: no-repeat;\r\n background-position: center;\r\n }\r\n @top-center {\r\n background: #ffcc00;\r\n content: '';\r\n display: block;\r\n height: .05cm;\r\n opacity: .5;\r\n width: 100%;\r\n }\r\n \r\n @bottom-left {\r\n background: #ffcc00;\r\n content: counter(page);\r\n height: 1cm;\r\n text-align: center;\r\n width: 1cm;\r\n }\r\n @bottom-center {\r\n background: #ffcc00;\r\n content: '';\r\n display: block;\r\n height: .05cm;\r\n opacity: .5;\r\n width: 100%;\r\n }\r\n @bottom-right {\r\n content: string(heading);\r\n font-size: 9pt;\r\n height: 1cm;\r\n vertical-align: middle;\r\n width: 100%;\r\n }\r\n}\r\n@page :blank {\r\n @top-left { background: none; content: '' }\r\n @top-center { content: none }\r\n @top-right { content: none }\r\n}\r\n@page no-chapter {\r\n @top-left { background: none; content: none }\r\n @top-center { content: none }\r\n @top-right { content: none }\r\n}\r\n@page :first {\r\n background: url(https://raw.githubusercontent.com/CourtBouillon/weasyprint-samples/master/report/report-cover.jpg) no-repeat center;\r\n background-size: cover;\r\n margin: 0;\r\n}\r\n@page chapter {\r\n background: #ffcc00;\r\n margin: 0;\r\n @top-left { content: none }\r\n @top-center { content: none }\r\n @top-right { content: none }\r\n}\r\n.page-break {\r\n page-break-before: always; /* For older browsers */\r\n break-before: page; /* For newer browsers */\r\n}\r\n\r\n\r\nhtml {\r\n color: #393939;\r\n font-family: Fira Sans;\r\n font-size: 11pt;\r\n font-weight: 300;\r\n line-height: 1.5;\r\n}\r\n\r\nh1 {\r\n color: #ffcc00;\r\n font-size: 38pt;\r\n margin: 5cm 2cm 0 2cm;\r\n page: no-chapter;\r\n width: 100%;\r\n}\r\nh2, h3, h4 {\r\n color: black;\r\n font-weight: 400;\r\n}\r\nh2 {\r\n break-before: always;\r\n font-size: 28pt;\r\n string-set: heading content();\r\n}\r\nh3 {\r\n font-weight: 300;\r\n font-size: 15pt;\r\n}\r\nh4 {\r\n font-size: 13pt;\r\n}\r\n\r\n#cover {\r\n align-content: space-between;\r\n display: flex;\r\n flex-wrap: wrap;\r\n}\r\n#cover address {\r\n position: absolute; /* Absolute positioning */\r\n bottom: 0; /* Stick to the bottom */\r\n width: 100%; /* Full width */\r\n text-align: center; /* Center the text */\r\n background: transparent; /* Optional: make background transparent or adjust as needed */\r\n margin: 0; /* Remove margins */\r\n padding: 20px 0; /* Add padding at the top and bottom */\r\n}\r\n#cover address:first-of-type {\r\n padding-left: 3cm;\r\n}\r\n#contents {\r\n page: no-chapter;\r\n}\r\n#contents h2 {\r\n font-size: 20pt;\r\n font-weight: 400;\r\n margin-bottom: 3cm;\r\n}\r\n#contents h3 {\r\n font-weight: 500;\r\n margin: 3em 0 1em;\r\n}\r\n#contents h3::before {\r\n background: #ffcc00;\r\n content: '';\r\n display: block;\r\n height: .08cm;\r\n margin-bottom: .25cm;\r\n width: 2cm;\r\n}\r\n#contents ul {\r\n list-style: none;\r\n padding-left: 0;\r\n}\r\n#contents ul li {\r\n border-top: .25pt solid #c1c1c1;\r\n margin: .25cm 0;\r\n padding-top: .25cm;\r\n}\r\n#contents ul li::before {\r\n color: #ffcc00;\r\n content: '• ';\r\n font-size: 40pt;\r\n line-height: 16pt;\r\n vertical-align: bottom;\r\n}\r\n#contents ul li a {\r\n color: inherit;\r\n text-decoration-line: inherit;\r\n}\r\n#contents ul li a::before {\r\n content: target-text(attr(href));\r\n}\r\n#contents ul li a::after {\r\n color: #ffcc00;\r\n content: target-counter(attr(href), page);\r\n float: right;\r\n}\r\n\r\n#columns section {\r\n columns: 2;\r\n column-gap: 1cm;\r\n padding-top: 1cm;\r\n}\r\n#columns section p {\r\n text-align: justify;\r\n}\r\n#columns section p:first-of-type {\r\n font-weight: 700;\r\n}\r\n\r\n#skills h3 {\r\n background: #ffcc00;\r\n margin: 0 -3cm 1cm;\r\n padding: 1cm 1cm 1cm 3cm;\r\n width: 21cm;\r\n}\r\n#skills section {\r\n padding: .5cm 0;\r\n}\r\ntable.GeneratedTable {\r\n width: 100%;\r\n background-color: #ffffff;\r\n border-collapse: collapse;\r\n border-width: 2px;\r\n border-color: #ffcc00;\r\n border-style: solid;\r\n color: #000000;\r\n}\r\n\r\ntable.GeneratedTable td, table.GeneratedTable th {\r\n border-width: 2px;\r\n border-color: #ffcc00;\r\n border-style: solid;\r\n padding: 3px;\r\n}\r\n\r\ntable.GeneratedTable thead {\r\n background-color: #ffcc00;\r\n}\r\n#skills section#tablecontent::before {\r\n background: url(https://raw.githubusercontent.com/CourtBouillon/weasyprint-samples/master/report/table-content.svg) no-repeat center #ffcc00;\r\n background-size: 50%;\r\n content: '';\r\n display: inline-block;\r\n float: left;\r\n height: 2cm;\r\n margin-right: .5cm;\r\n vertical-align: middle;\r\n width: 2cm;\r\n}\r\n#skills section#heading::before {\r\n background: url(https://raw.githubusercontent.com/CourtBouillon/weasyprint-samples/master/report/heading.svg) no-repeat center #ffcc00;\r\n background-size: 50%;\r\n content: '';\r\n display: inline-block;\r\n float: left;\r\n height: 2cm;\r\n margin-right: .5cm;\r\n vertical-align: middle;\r\n width: 2cm;\r\n}\r\n#skills section#multicolumns::before {\r\n background: url(https://raw.githubusercontent.com/CourtBouillon/weasyprint-samples/master/report/multi-columns.svg) no-repeat center #ffcc00;\r\n background-size: 50%;\r\n content: '';\r\n display: inline-block;\r\n float: left;\r\n height: 2cm;\r\n margin-right: .5cm;\r\n vertical-align: middle;\r\n width: 2cm;\r\n}\r\n#skills section#internallinks::before {\r\n background: url(https://raw.githubusercontent.com/CourtBouillon/weasyprint-samples/master/report/internal-links.svg) no-repeat center #ffcc00;\r\n background-size: 50%;\r\n content: '';\r\n display: inline-block;\r\n float: left;\r\n height: 2cm;\r\n margin-right: .5cm;\r\n vertical-align: middle;\r\n width: 2cm;\r\n}\r\n#skills section#style::before {\r\n background: url(https://raw.githubusercontent.com/CourtBouillon/weasyprint-samples/master/report/style.svg) no-repeat center #ffcc00;\r\n background-size: 50%;\r\n content: '';\r\n display: inline-block;\r\n float: left;\r\n height: 2cm;\r\n margin-right: .5cm;\r\n vertical-align: middle;\r\n width: 2cm;\r\n}\r\n#skills section h4 {\r\n margin: 0;\r\n}\r\n#skills section p {\r\n margin-top: 0;\r\n}\r\n\r\n#offers {\r\n display: flex;\r\n flex-wrap: wrap;\r\n justify-content: space-between;\r\n}\r\n#offers h2, #offers h3 {\r\n width: 100%;\r\n}\r\n#offers section {\r\n width: 30%;\r\n}\r\n#offers section h4 {\r\n margin-bottom: 0;\r\n}\r\n#offers section ul {\r\n list-style: none;\r\n margin: 0;\r\n padding-left: 0;\r\n}\r\n#offers section ul li:not(:last-of-type) {\r\n margin: .5cm 0;\r\n}\r\n#offers section p {\r\n background: #ffcc00;\r\n display: block;\r\n font-size: 15pt;\r\n font-weight: 700;\r\n margin-bottom: 0;\r\n padding: .25cm 0;\r\n text-align: center;\r\n}\r\n\r\n#chapter {\r\n align-items: center;\r\n display: flex;\r\n height: 297mm;\r\n justify-content: center;\r\n page: chapter;\r\n}\r\n\r\n#typography section {\r\n display: flex;\r\n flex-wrap: wrap;\r\n margin: 1cm 0;\r\n}\r\n#typography section h4 {\r\n border-top: 1pt solid;\r\n flex: 1 25%;\r\n margin: 0;\r\n}\r\n#typography section h4 + * {\r\n flex: 1 75%;\r\n margin: 0;\r\n padding-left: .5cm;\r\n}\r\n#typography section p {\r\n text-align: justify;\r\n}\r\n#typography section ul {\r\n line-height: 2;\r\n list-style: none;\r\n}\r\n#typography section#smallcaps p {\r\n font-variant: small-caps;\r\n}\r\n#typography section#ligatures dl {\r\n display: flex;\r\n flex-wrap: wrap;\r\n}\r\n#typography section#ligatures dl dt {\r\n font-weight: 400;\r\n width: 30%;\r\n}\r\n#typography section#ligatures dl dd {\r\n flex: 1 70%;\r\n margin: 0;\r\n padding: 0;\r\n}\r\n#typography section#ligatures .none {\r\n font-variant-ligatures: none;\r\n}\r\n#typography section#ligatures .common {\r\n font-variant-ligatures: common-ligatures;\r\n}\r\n#typography section#ligatures .discretionary {\r\n font-variant-ligatures: discretionary-ligatures;\r\n}\r\n#typography section#ligatures .contextual {\r\n font-variant-ligatures: contextual;\r\n}\r\n#typography section#numbers dl {\r\n display: flex;\r\n flex-wrap: wrap;\r\n}\r\n#typography section#numbers dl dt {\r\n font-weight: 400;\r\n width: 30%;\r\n}\r\n#typography section#numbers dl dd {\r\n flex: 1 70%;\r\n margin: 0;\r\n padding: 0;\r\n}\r\n#typography section#numbers #fractions {\r\n font-variant-numeric: diagonal-fractions;\r\n}\r\n#typography section#numbers #ordinals {\r\n font-variant-numeric: ordinal;\r\n}\r\n#typography section#numbers #slashed {\r\n font-variant-numeric: slashed-zero;\r\n}\r\n#typography section#numbers #super {\r\n font-variant-position: super;\r\n}\r\n#typography section#numbers #sub {\r\n font-variant-position: sub;\r\n}\r\n#typography section#figures dl {\r\n columns: 4;\r\n}\r\n#typography section#figures dl dt {\r\n font-weight: 400;\r\n}\r\n#typography section#figures dl dd {\r\n display: flex;\r\n margin: 0;\r\n padding: 0;\r\n}\r\n#typography section#figures dl dd ul {\r\n padding: 0 1em 0 0;\r\n}\r\n#typography section#figures #oldstyle {\r\n font-variant-numeric: oldstyle-nums;\r\n}", + "template_md": "{% block content %}\r\n~~A cover~~\r\n# Agent List for {{client.name}}\r\n
\r\nCompany\r\n123 anywhere st\r\nCity, State zip\r\n
\r\n
\r\nme@here.com\r\nhttps://example.com\r\n
\r\n~~/A~~\r\n~~A~~\r\n{{ client.name }} Agents List\r\n
\r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n {% for item in data_sources.agentAllFields %}\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n {% endfor %}\r\n \r\n
Agent InfoSite Name
\r\n Name:
\r\n User:
\r\n OS:
\r\n Last Seen:
\r\n
\r\n {{ item.hostname }}
\r\n {{ item.last_logged_in_user }}
\r\n {{ item.operating_system.split(',')[0] if item.operating_system else 'N/A' }}
\r\n {{ item.last_seen.strftime('%Y-%m-%d %H:%M') }}
\r\n
\r\n CPU:
\r\n RAM:
\r\n Disks:
\r\n
\r\n {{ item.wmi_detail.cpu[0][0].Name.replace('(R)', '').replace('(TM)', '').split('@')[0].strip() if item.wmi_detail and item.wmi_detail.cpu and item.wmi_detail.cpu[0][0].Name else 'N/A' }}
\r\n {{ item.total_ram }}GB
\r\n {% for disk in item.disks %}\r\n {% if not loop.previtem or loop.previtem.device != disk.device %}\r\n {{ disk.device }} {{ disk.total }}
\r\n {% endif %}\r\n {% else %}\r\n N/A
\r\n {% endfor %}\r\n
{{ item.site__name }}
\r\n~~/A~~\r\n{% endblock %}", "type": "markdown", "depends_on": [ "client" @@ -14,4 +14,4 @@ "template_variables": "data_sources:\n agentAllFields:\n only:\n - hostname\n - operating_system\n - last_seen\n - last_logged_in_user\n - site__name\n - wmi_detail\n - total_ram\n - disks\n filter:\n site__client_id: \"{{client.id}}\"\n model: agent" }, "assets": [] -} +} \ No newline at end of file diff --git a/templates/Agent List_By Client with Specs MultiColour(pdf).json b/templates/Agent List_By Client with Specs MultiColour(pdf).json deleted file mode 100644 index 69a24bf..0000000 --- a/templates/Agent List_By Client with Specs MultiColour(pdf).json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "base_template": { - "name": "Base Template", - "html": "\n \n \n \n \n {% block content %}{% endblock %}\n \n" - }, - "template": { - "name": "Agent List_By Client with Specs v2(pdf)", - "template_css": "@font-face {\r\n font-family: Fira Sans;\r\n font-weight: 400;\r\n src: url(https://raw.githubusercontent.com/CourtBouillon/weasyprint-samples/master/report/firasans-regular.otf);\r\n}\r\n@font-face {\r\n font-family: Fira Sans;\r\n font-style: italic;\r\n font-weight: 400;\r\n src: url(https://raw.githubusercontent.com/CourtBouillon/weasyprint-samples/master/report/firasans-italic.otf);\r\n}\r\n@font-face {\r\n font-family: Fira Sans;\r\n font-weight: 300;\r\n src: url(https://raw.githubusercontent.com/CourtBouillon/weasyprint-samples/master/report/firasans-light.otf);\r\n}\r\n@font-face {\r\n font-family: Fira Sans;\r\n font-style: italic;\r\n font-weight: 300;\r\n src: url(https://raw.githubusercontent.com/CourtBouillon/weasyprint-samples/master/report/firasans-lightitalic.otf);\r\n}\r\n@font-face {\r\n font-family: Fira Sans;\r\n font-weight: 700;\r\n src: url(https://raw.githubusercontent.com/CourtBouillon/weasyprint-samples/master/report/firasans-bold.otf);\r\n}\r\n\r\n@page {\r\n \r\n @top-left {\r\n background: #fafaf9;\r\n content: \"\";\r\n height: 50px;\r\n width: 50px;\r\n position: absolute;\r\n top: 0;\r\n left: 0;\r\n background-image: url('https://github.com/silversword411/tacticalrmm-web/blob/b8c4dc2671d5d45d1c0ec557aeea3eb33f271fd7/src/assets/alt-logos/2orig1%20(256).png?raw=true');\r\n background-size: cover;\r\n background-repeat: no-repeat;\r\n background-position: center;\r\n }\r\n @top-center {\r\n background: #ffcc00;\r\n content: '';\r\n display: block;\r\n height: .05cm;\r\n opacity: .5;\r\n width: 100%;\r\n }\r\n \r\n @bottom-left {\r\n background: #ffcc00;\r\n content: counter(page);\r\n height: 1cm;\r\n text-align: center;\r\n width: 1cm;\r\n }\r\n @bottom-center {\r\n background: #ffcc00;\r\n content: '';\r\n display: block;\r\n height: .05cm;\r\n opacity: .5;\r\n width: 100%;\r\n }\r\n @bottom-right {\r\n content: string(heading);\r\n font-size: 9pt;\r\n height: 1cm;\r\n vertical-align: middle;\r\n width: 100%;\r\n }\r\n}\r\n@page :blank {\r\n @top-left { background: none; content: '' }\r\n @top-center { content: none }\r\n @top-right { content: none }\r\n}\r\n@page no-chapter {\r\n @top-left { background: none; content: none }\r\n @top-center { content: none }\r\n @top-right { content: none }\r\n}\r\n@page :first {\r\n background: url(https://raw.githubusercontent.com/CourtBouillon/weasyprint-samples/master/report/report-cover.jpg) no-repeat center;\r\n background-size: cover;\r\n margin: 0;\r\n}\r\n@page chapter {\r\n background: #1100ff;\r\n margin: 0;\r\n @top-left { content: none }\r\n @top-center { content: none }\r\n @top-right { content: none }\r\n}\r\n\r\nhtml {\r\n color: #393939;\r\n font-family: Fira Sans;\r\n font-size: 11pt;\r\n font-weight: 300;\r\n line-height: 1.5;\r\n}\r\n\r\nh1 {\r\n color: #f7f5ef;\r\n font-size: 38pt;\r\n margin: 5cm 2cm 0 2cm;\r\n page: no-chapter;\r\n width: 100%;\r\n}\r\nh2, h3, h4 {\r\n color: black;\r\n font-weight: 400;\r\n}\r\nh2 {\r\n break-before: always;\r\n font-size: 28pt;\r\n string-set: heading content();\r\n}\r\nh3 {\r\n font-weight: 300;\r\n font-size: 15pt;\r\n}\r\nh4 {\r\n font-size: 13pt;\r\n}\r\n\r\n#cover {\r\n align-content: space-between;\r\n display: flex;\r\n flex-wrap: wrap;\r\n height: 297mm;\r\n}\r\n#cover address {\r\n background: #a1a0a0;\r\n flex: 1 50%;\r\n margin: 0 -2cm;\r\n padding: 1cm 0;\r\n white-space: pre-wrap;\r\n}\r\n#cover address:first-of-type {\r\n padding-left: 3cm;\r\n}\r\n#contents {\r\n page: no-chapter;\r\n}\r\n#contents h2 {\r\n font-size: 20pt;\r\n font-weight: 400;\r\n margin-bottom: 3cm;\r\n}\r\n#contents h3 {\r\n font-weight: 500;\r\n margin: 3em 0 1em;\r\n}\r\n#contents h3::before {\r\n background: #ffcc00;\r\n content: '';\r\n display: block;\r\n height: .08cm;\r\n margin-bottom: .25cm;\r\n width: 2cm;\r\n}\r\n#contents ul {\r\n list-style: none;\r\n padding-left: 0;\r\n}\r\n#contents ul li {\r\n border-top: .25pt solid #c1c1c1;\r\n margin: .25cm 0;\r\n padding-top: .25cm;\r\n}\r\n#contents ul li::before {\r\n color: #ffcc00;\r\n content: '• ';\r\n font-size: 40pt;\r\n line-height: 16pt;\r\n vertical-align: bottom;\r\n}\r\n#contents ul li a {\r\n color: inherit;\r\n text-decoration-line: inherit;\r\n}\r\n#contents ul li a::before {\r\n content: target-text(attr(href));\r\n}\r\n#contents ul li a::after {\r\n color: #ffcc00;\r\n content: target-counter(attr(href), page);\r\n float: right;\r\n}\r\n\r\n#columns section {\r\n columns: 2;\r\n column-gap: 1cm;\r\n padding-top: 1cm;\r\n}\r\n#columns section p {\r\n text-align: justify;\r\n}\r\n#columns section p:first-of-type {\r\n font-weight: 700;\r\n}\r\n\r\n#skills h3 {\r\n background: #ffcc00;\r\n margin: 0 -3cm 1cm;\r\n padding: 1cm 1cm 1cm 3cm;\r\n width: 21cm;\r\n}\r\n#skills section {\r\n padding: .5cm 0;\r\n}\r\ntable.GeneratedTable {\r\n width: 100%;\r\n background-color: #ffffff;\r\n border-collapse: collapse;\r\n border-width: 2px;\r\n border-color: #030301;\r\n border-style: solid;\r\n color: #000000;\r\n}\r\n\r\ntable.GeneratedTable td, table.GeneratedTable th {\r\n border-width: 2px;\r\n border-color: #080808;\r\n border-style: solid;\r\n padding: 3px;\r\n}\r\n\r\ntable.GeneratedTable thead {\r\n background-color: #0059ff;\r\n}\r\n#skills section#tablecontent::before {\r\n background: url(https://raw.githubusercontent.com/CourtBouillon/weasyprint-samples/master/report/table-content.svg) no-repeat center #ffcc00;\r\n background-size: 50%;\r\n content: '';\r\n display: inline-block;\r\n float: left;\r\n height: 2cm;\r\n margin-right: .5cm;\r\n vertical-align: middle;\r\n width: 2cm;\r\n}\r\n#skills section#heading::before {\r\n background: url(https://raw.githubusercontent.com/CourtBouillon/weasyprint-samples/master/report/heading.svg) no-repeat center #ffcc00;\r\n background-size: 50%;\r\n content: '';\r\n display: inline-block;\r\n float: left;\r\n height: 2cm;\r\n margin-right: .5cm;\r\n vertical-align: middle;\r\n width: 2cm;\r\n}\r\n#skills section#multicolumns::before {\r\n background: url(https://raw.githubusercontent.com/CourtBouillon/weasyprint-samples/master/report/multi-columns.svg) no-repeat center #ffcc00;\r\n background-size: 50%;\r\n content: '';\r\n display: inline-block;\r\n float: left;\r\n height: 2cm;\r\n margin-right: .5cm;\r\n vertical-align: middle;\r\n width: 2cm;\r\n}\r\n#skills section#internallinks::before {\r\n background: url(https://raw.githubusercontent.com/CourtBouillon/weasyprint-samples/master/report/internal-links.svg) no-repeat center #ffcc00;\r\n background-size: 50%;\r\n content: '';\r\n display: inline-block;\r\n float: left;\r\n height: 2cm;\r\n margin-right: .5cm;\r\n vertical-align: middle;\r\n width: 2cm;\r\n}\r\n#skills section#style::before {\r\n background: url(https://raw.githubusercontent.com/CourtBouillon/weasyprint-samples/master/report/style.svg) no-repeat center #ffcc00;\r\n background-size: 50%;\r\n content: '';\r\n display: inline-block;\r\n float: left;\r\n height: 2cm;\r\n margin-right: .5cm;\r\n vertical-align: middle;\r\n width: 2cm;\r\n}\r\n#skills section h4 {\r\n margin: 0;\r\n}\r\n#skills section p {\r\n margin-top: 0;\r\n}\r\n\r\n#offers {\r\n display: flex;\r\n flex-wrap: wrap;\r\n justify-content: space-between;\r\n}\r\n#offers h2, #offers h3 {\r\n width: 100%;\r\n}\r\n#offers section {\r\n width: 30%;\r\n}\r\n#offers section h4 {\r\n margin-bottom: 0;\r\n}\r\n#offers section ul {\r\n list-style: none;\r\n margin: 0;\r\n padding-left: 0;\r\n}\r\n#offers section ul li:not(:last-of-type) {\r\n margin: .5cm 0;\r\n}\r\n#offers section p {\r\n background: #ffcc00;\r\n display: block;\r\n font-size: 15pt;\r\n font-weight: 700;\r\n margin-bottom: 0;\r\n padding: .25cm 0;\r\n text-align: center;\r\n}\r\n\r\n#chapter {\r\n align-items: center;\r\n display: flex;\r\n height: 297mm;\r\n justify-content: center;\r\n page: chapter;\r\n}\r\n\r\n#typography section {\r\n display: flex;\r\n flex-wrap: wrap;\r\n margin: 1cm 0;\r\n}\r\n#typography section h4 {\r\n border-top: 1pt solid;\r\n flex: 1 25%;\r\n margin: 0;\r\n}\r\n#typography section h4 + * {\r\n flex: 1 75%;\r\n margin: 0;\r\n padding-left: .5cm;\r\n}\r\n#typography section p {\r\n text-align: justify;\r\n}\r\n#typography section ul {\r\n line-height: 2;\r\n list-style: none;\r\n}\r\n#typography section#smallcaps p {\r\n font-variant: small-caps;\r\n}\r\n#typography section#ligatures dl {\r\n display: flex;\r\n flex-wrap: wrap;\r\n}\r\n#typography section#ligatures dl dt {\r\n font-weight: 400;\r\n width: 30%;\r\n}\r\n#typography section#ligatures dl dd {\r\n flex: 1 70%;\r\n margin: 0;\r\n padding: 0;\r\n}\r\n#typography section#ligatures .none {\r\n font-variant-ligatures: none;\r\n}\r\n#typography section#ligatures .common {\r\n font-variant-ligatures: common-ligatures;\r\n}\r\n#typography section#ligatures .discretionary {\r\n font-variant-ligatures: discretionary-ligatures;\r\n}\r\n#typography section#ligatures .contextual {\r\n font-variant-ligatures: contextual;\r\n}\r\n#typography section#numbers dl {\r\n display: flex;\r\n flex-wrap: wrap;\r\n}\r\n#typography section#numbers dl dt {\r\n font-weight: 400;\r\n width: 30%;\r\n}\r\n#typography section#numbers dl dd {\r\n flex: 1 70%;\r\n margin: 0;\r\n padding: 0;\r\n}\r\n#typography section#numbers #fractions {\r\n font-variant-numeric: diagonal-fractions;\r\n}\r\n#typography section#numbers #ordinals {\r\n font-variant-numeric: ordinal;\r\n}\r\n#typography section#numbers #slashed {\r\n font-variant-numeric: slashed-zero;\r\n}\r\n#typography section#numbers #super {\r\n font-variant-position: super;\r\n}\r\n#typography section#numbers #sub {\r\n font-variant-position: sub;\r\n}\r\n#typography section#figures dl {\r\n columns: 4;\r\n}\r\n#typography section#figures dl dt {\r\n font-weight: 400;\r\n}\r\n#typography section#figures dl dd {\r\n display: flex;\r\n margin: 0;\r\n padding: 0;\r\n}\r\n#typography section#figures dl dd ul {\r\n padding: 0 1em 0 0;\r\n}\r\n#typography section#figures #oldstyle {\r\n font-variant-numeric: oldstyle-nums;\r\n}", - "template_md": "{% block content %}\r\n~~A cover~~\r\n# Agent List for {{client.name}}\r\n
\r\nCompany\r\n123 anywhere st\r\nCity, State zip\r\n
\r\n
\r\nme@here.com\r\nhttps://example.com\r\n
\r\n~~/A~~\r\n~~A~~\r\n{{ client.name }} Agents List\r\n\r\n \r\n\r\n\r\n\r\n\r\n \r\n \r\n {% for item in data_sources.agentAllFields %}\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n {% endfor %}\r\n \r\n
Agent\r\nInfo
\r\n
Site Name
\r\n
Name:\r\nUser:\r\nOS:\r\nLast Seen:
\r\n
\r\n{{ item.hostname }}
\r\n{{ item.last_logged_in_user }}
\r\n{{ (item.operating_system.split(',')[0] if item.operating_system else 'N/A') }}
\r\n{{ item.last_seen.strftime('%Y-%m-%d %H:%M') }}
\r\n
\r\nCPU:
\r\n\r\nRAM:
\r\n\r\nDisks:
\r\n
\r\n{{ (item.wmi_detail.cpu[0][0].Name.replace('(R)', '').replace('(TM)', '').split('@')[0].strip() if item.wmi_detail and item.wmi_detail.cpu and item.wmi_detail.cpu[0][0].Name else 'N/A') }}
\r\n{{ item.total_ram }}GB
\r\n{% for disk in item.disks %}{% if not loop.previtem or loop.previtem.device != disk.device %} {{disk.device}} {{disk.total}}{% endif %}{% else %}N/A{% endfor %}
\r\n
{{item.site__name}}
\r\n~~/A~~\r\n{% endblock %}", - "type": "markdown", - "depends_on": [ - "client" - ], - "template_variables": "data_sources:\n agentAllFields:\n only:\n - hostname\n - operating_system\n - last_seen\n - last_logged_in_user\n - site__name\n - wmi_detail\n - total_ram\n - disks\n filter:\n site__client_id: \"{{client.id}}\"\n model: agent" - }, - "assets": [] -} diff --git a/templates/All Fields - Windows Update_Per Site (csv).json b/templates/All Fields - Windows Update_By Site (csv).json similarity index 96% rename from templates/All Fields - Windows Update_Per Site (csv).json rename to templates/All Fields - Windows Update_By Site (csv).json index 6430b8e..04ab8c5 100644 --- a/templates/All Fields - Windows Update_Per Site (csv).json +++ b/templates/All Fields - Windows Update_By Site (csv).json @@ -1,7 +1,7 @@ { "base_template": null, "template": { - "name": "All Fields - Windows Update: Per Site (csv)", + "name": "All Fields - Windows Update_By Site (csv)", "template_css": "", "template_md": "Device Name, ID, Agent ID, GUID, KB, Title, Installed, Downloaded, Description, Severity, Categories, Category_ids, KB Article IDs, More Info Urls, Support Url, Revision Number, Action, Result, Date Installed\r\n{% for item in data_sources.allFieldsWindowsUpdates %}{{item.agent__hostname if item.agent__hostname else 'N/A'}},{{item.id if item.id else 'N/A'}},{{item.agent_id if item.agent_id else 'N/A'}},{{item.guid if item.guid else 'N/A'}},{{item.kb if item.kb else 'N/A'}},{{item.title if item.title else 'N/A'}},{{item.installed if item.installed else 'N/A'}},{{item.downloaded if item.downloaded else 'N/A'}},{{item.description if item.description else 'N/A'}},{{item.severity if item.severity else 'N/A'}},{{item.categories if item.categories else 'N/A'}},{{item.category_ids if item.category_ids else 'N/A'}},{{item.kb_article_ids if item.kb_article_ids else 'N/A'}},{{item.more_info_urls if item.more_info_urls else 'N/A'}},{{item.support_url if item.support_url else 'N/A'}},{{item.revision_number if item.revision_number else 'N/A'}},{{item.action if item.action else 'N/A'}},{{item.result if item.result else 'N/A'}},{{item.date_installed if item.date_installed else 'N/A'}},\r\n{% endfor %}", "type": "plaintext", diff --git a/templates/All Fields Windows Update_Per Device (csv).json b/templates/All Fields Windows Update_By Device (csv).json similarity index 96% rename from templates/All Fields Windows Update_Per Device (csv).json rename to templates/All Fields Windows Update_By Device (csv).json index c291eca..7079ce0 100644 --- a/templates/All Fields Windows Update_Per Device (csv).json +++ b/templates/All Fields Windows Update_By Device (csv).json @@ -1,7 +1,7 @@ { "base_template": null, "template": { - "name": "All Fields Windows Update_Per Device (csv)", + "name": "All Fields Windows Update_By Device (csv)", "template_css": "", "template_md": "Device Name, ID, Agent ID, GUID, KB, Title, Installed, Downloaded, Description, Severity, Categories, Category_ids, KB Article IDs, More Info Urls, Support Url, Revision Number, Action, Result, Date Installed\r\n{% for item in data_sources.allFieldsWindowsUpdates %}{{item.agent__hostname if item.agent__hostname else 'N/A'}},{{item.id if item.id else 'N/A'}},{{item.agent_id if item.agent_id else 'N/A'}},{{item.guid if item.guid else 'N/A'}},{{item.kb if item.kb else 'N/A'}},{{item.title if item.title else 'N/A'}},{{item.installed if item.installed else 'N/A'}},{{item.downloaded if item.downloaded else 'N/A'}},{{item.description if item.description else 'N/A'}},{{item.severity if item.severity else 'N/A'}},{{item.categories if item.categories else 'N/A'}},{{item.category_ids if item.category_ids else 'N/A'}},{{item.kb_article_ids if item.kb_article_ids else 'N/A'}},{{item.more_info_urls if item.more_info_urls else 'N/A'}},{{item.support_url if item.support_url else 'N/A'}},{{item.revision_number if item.revision_number else 'N/A'}},{{item.action if item.action else 'N/A'}},{{item.result if item.result else 'N/A'}},{{item.date_installed if item.date_installed else 'N/A'}},\r\n{% endfor %}", "type": "plaintext", diff --git a/templates/All Fields Windows Update_Per Site (csv).json b/templates/All Fields Windows Update_By Site (csv).json similarity index 96% rename from templates/All Fields Windows Update_Per Site (csv).json rename to templates/All Fields Windows Update_By Site (csv).json index 0403e68..5163b9e 100644 --- a/templates/All Fields Windows Update_Per Site (csv).json +++ b/templates/All Fields Windows Update_By Site (csv).json @@ -1,7 +1,7 @@ { "base_template": null, "template": { - "name": "All Fields Windows Update_Per Site (csv)", + "name": "All Fields Windows Update_By Site (csv)", "template_css": "", "template_md": "Device Name, ID, Agent ID, GUID, KB, Title, Installed, Downloaded, Description, Severity, Categories, Category_ids, KB Article IDs, More Info Urls, Support Url, Revision Number, Action, Result, Date Installed\r\n{% for item in data_sources.allFieldsWindowsUpdates %}{{item.agent__hostname if item.agent__hostname else 'N/A'}},{{item.id if item.id else 'N/A'}},{{item.agent_id if item.agent_id else 'N/A'}},{{item.guid if item.guid else 'N/A'}},{{item.kb if item.kb else 'N/A'}},{{item.title if item.title else 'N/A'}},{{item.installed if item.installed else 'N/A'}},{{item.downloaded if item.downloaded else 'N/A'}},{{item.description if item.description else 'N/A'}},{{item.severity if item.severity else 'N/A'}},{{item.categories if item.categories else 'N/A'}},{{item.category_ids if item.category_ids else 'N/A'}},{{item.kb_article_ids if item.kb_article_ids else 'N/A'}},{{item.more_info_urls if item.more_info_urls else 'N/A'}},{{item.support_url if item.support_url else 'N/A'}},{{item.revision_number if item.revision_number else 'N/A'}},{{item.action if item.action else 'N/A'}},{{item.result if item.result else 'N/A'}},{{item.date_installed if item.date_installed else 'N/A'}},\r\n{% endfor %}", "type": "plaintext", diff --git a/templates/All Fields Windows Update_Per Site w-sort (csv).json b/templates/All Fields Windows Update_By Site w-sort (csv).json similarity index 96% rename from templates/All Fields Windows Update_Per Site w-sort (csv).json rename to templates/All Fields Windows Update_By Site w-sort (csv).json index 40eabe7..bbda645 100644 --- a/templates/All Fields Windows Update_Per Site w-sort (csv).json +++ b/templates/All Fields Windows Update_By Site w-sort (csv).json @@ -1,7 +1,7 @@ { "base_template": null, "template": { - "name": "All Fields Windows Update Site n Date (csv)", + "name": "All Fields Windows Update_By Site w-sort (csv)", "template_css": "", "template_md": "Device Name, ID, Agent ID, GUID, KB, Title, Installed, Downloaded, Description, Severity, Categories, Category_ids, KB Article IDs, More Info Urls, Support Url, Revision Number, Action, Result, Date Installed\r\n{% set filtered_items = data_sources.allFieldsWindowsUpdates|selectattr('date_installed', 'ne', None)|selectattr('date_installed', 'ne', '')|list %}{% for item in filtered_items %}{{item.agent__hostname if item.agent__hostname else 'N/A'}},{{item.id if item.id else 'N/A'}},{{item.agent_id if item.agent_id else 'N/A'}},{{item.guid if item.guid else 'N/A'}},{{item.kb if item.kb else 'N/A'}},{{item.title if item.title else 'N/A'}},{{item.installed if item.installed else 'N/A'}},{{item.downloaded if item.downloaded else 'N/A'}},{{item.description if item.description else 'N/A'}},{{item.severity if item.severity else 'N/A'}},{{item.categories if item.categories else 'N/A'}},{{item.category_ids if item.category_ids else 'N/A'}},{{item.kb_article_ids if item.kb_article_ids else 'N/A'}},{{item.more_info_urls if item.more_info_urls else 'N/A'}},{{item.support_url if item.support_url else 'N/A'}},{{item.revision_number if item.revision_number else 'N/A'}},{{item.action if item.action else 'N/A'}},{{item.result if item.result else 'N/A'}},{{item.date_installed if item.date_installed else 'N/A'}},\r\n{% endfor %}", "type": "plaintext", diff --git a/templates/Audit Logs (csv).json b/templates/Audit Logs (csv).json index e2c5941..b65aa23 100644 --- a/templates/Audit Logs (csv).json +++ b/templates/Audit Logs (csv).json @@ -1,7 +1,7 @@ { "base_template": null, "template": { - "name": "Audit Logs", + "name": "Audit Logs (csv)", "template_css": "", "template_md": "Device Name, Action, User, Time\r\n{% set filtered_items = data_sources.auditlogList|selectattr('entry_time', 'ge', monthdays)|list %}{% for item in filtered_items %}{{item.agent}},{{item.action}},{{item.username}},{{item.entry_time}}\r\n{% endfor %}", "type": "plaintext", diff --git a/templates/Custom Fields Example1.json b/templates/Custom Fields Example1.json index 81feee9..1fae157 100644 --- a/templates/Custom Fields Example1.json +++ b/templates/Custom Fields Example1.json @@ -1,7 +1,7 @@ { "base_template": null, "template": { - "name": "Custom Fields", + "name": "Custom Fields Example1", "template_css": "", "template_md": "# Agents\r\n\r\n> There needs to be an Agent custom fields named: **Agent Test Field** and **Agent Test Field 2**\r\n\r\n\r\n \r\n \r\n\t\r\n \r\n \r\n \r\n \r\n \r\n {% for item in data_sources.agents %}\r\n \r\n\t\r\n\t\r\n \r\n \r\n {% endfor %}\r\n \r\n
HostnameTest Field 1Test Field 2
{{ item.hostname }}{{ item.custom_fields.AgentTestField }}{{ item.custom_fields[\"Agent Test Field 2\"] }}
\r\n\r\n\r\n# Clients\r\n\r\n> There needs to be an Client custom fields named: **Client Test Field** and **Client Test Field 2**\r\n\r\n\r\n \r\n \r\n\t\r\n \r\n \r\n \r\n \r\n \r\n {% for item in data_sources.clients %}\r\n \r\n\t\r\n\t\r\n \r\n \r\n {% endfor %}\r\n \r\n
NameTest Field 1Test Field 2
{{ item.name }}{{ item.custom_fields.ClientTestField }}{{ item.custom_fields[\"Client Test Field 2\"] }}
\r\n\r\n\r\n# Sites\r\n\r\n> There needs to be an Site custom fields named: **Site Test Field** and **Site Test Field 2**\r\n\r\n\r\n \r\n \r\n\t\r\n \r\n \r\n \r\n \r\n \r\n {% for item in data_sources.sites %}\r\n \r\n\t\r\n\t\r\n \r\n \r\n {% endfor %}\r\n \r\n
NameTest Field 1Test Field 2
{{ item.name }}{{ item.custom_fields.SiteTestField }}{{ item.custom_fields[\"Site Test Field 2\"] }}
", "type": "markdown", diff --git a/templates/Software Report Full_By Agent (csv).json b/templates/Software Report Full_By Agent (csv).json index 89369ec..51919dc 100644 --- a/templates/Software Report Full_By Agent (csv).json +++ b/templates/Software Report Full_By Agent (csv).json @@ -1,7 +1,7 @@ { "base_template": null, "template": { - "name": "Agent Full Software Report (csv)", + "name": "Software Report Full_By Agent (csv)", "template_css": "", "template_md": "Software Audit Report - {{agent.hostname}}\r\nSoftware Name, Version, Publisher\r\n{% for record in data_sources.agentSoftware %}{% for software in record.software %}{{ software.name or 'N/A' }}, {{ software.version or 'N/A' }}, {{ software.publisher or 'N/A' }}\r\n{% endfor %}{% endfor %}", "type": "plaintext", diff --git a/templates/Windows 11 Compatible List fixed (csv).json b/templates/Windows 11 Compatible List_By Client (csv).json similarity index 92% rename from templates/Windows 11 Compatible List fixed (csv).json rename to templates/Windows 11 Compatible List_By Client (csv).json index ab88f67..b941184 100644 --- a/templates/Windows 11 Compatible List fixed (csv).json +++ b/templates/Windows 11 Compatible List_By Client (csv).json @@ -1,7 +1,7 @@ { "base_template": null, "template": { - "name": "Windows 11 Compatible List fixed (csv)", + "name": "Windows 11 Compatible List_By Client (csv)", "template_css": "", "template_md": "Device Name, Device OS, Windows 11 Compatible\r\n{% for item in data_sources.agentsList %}{{item.hostname if item.hostname else 'N/A'}},{{item.operating_system|replace(\",\", \"\") if item.operating_system else 'N/A'}},{{item.custom_fields.Windows11Comp|replace(\"\\n\", \" \")|replace(\"\\r\", \"\") if item.custom_fields.Windows11Comp else 'N/A'}}\r\n{% endfor %}", "type": "plaintext", diff --git a/templates/Windows 11 Compatible List_By Client (html) v1.8.json b/templates/Windows 11 Compatible List_By Client (html) v1.8.json index ea95b1b..220cd4a 100644 --- a/templates/Windows 11 Compatible List_By Client (html) v1.8.json +++ b/templates/Windows 11 Compatible List_By Client (html) v1.8.json @@ -4,7 +4,7 @@ "html": "\n\n\n \n\n\n\n {% block content %}{% endblock %}\n\n\n" }, "template": { - "name": "Windows 11 Compatible List (html) v1.8", + "name": "Windows 11 Compatible List_By Client (html) v1.8", "template_css": "", "template_md": "{% block content %}\r\n\r\n
\r\n
\r\n \"Amidaware\r\n
\r\n
\r\n

Windows 11 Compatibility Report

\r\n

Client: {{ client.name }}

\r\n
\r\n
\r\n

Report Date:
{{ report_run_timestamp.strftime('%B %d, %Y') }}

\r\n
\r\n
\r\n\r\n
\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n {% set not_ready_devices, ready_devices, already_devices = [], [], [] %}\r\n {% for device in data_sources.agentsList %}\r\n {% if device.plat and device.plat|lower == \"windows\" %}\r\n {% if device.custom_fields.Windows11Comp %}\r\n {% if device.custom_fields.Windows11Comp == \"Windows 11 Ready\" %}\r\n {% set _ = ready_devices.append(device) %}\r\n {% elif device.custom_fields.Windows11Comp == \"Already Windows 11\" %}\r\n {% set _ = already_devices.append(device) %}\r\n {% else %}\r\n {% set _ = not_ready_devices.append(device) %}\r\n {% endif %}\r\n {% else %}\r\n {% set _ = not_ready_devices.append(device) %}\r\n {% endif %}\r\n {% endif %}\r\n {% endfor %}\r\n {% set sorted_devices = (not_ready_devices | sort(attribute='hostname') | sort(attribute='site__name')) +\r\n (ready_devices | sort(attribute='hostname') | sort(attribute='site__name')) +\r\n (already_devices | sort(attribute='hostname') | sort(attribute='site__name')) %}\r\n\r\n {% for device in sorted_devices %}\r\n {% set row_class = 'status-unknown' %}\r\n {% set badge_class = 'badge-unknown' %}\r\n {% set status_text = 'Update custom_field' %}\r\n {% if device.custom_fields.Windows11Comp %}\r\n {% if device.custom_fields.Windows11Comp == \"Windows 11 Ready\" %}\r\n {% set row_class = 'status-ready' %}\r\n {% set badge_class = 'badge-ready' %}\r\n {% set status_text = 'Ready' %}\r\n {% elif device.custom_fields.Windows11Comp == \"Already Windows 11\" %}\r\n {% set row_class = 'status-ready' %}\r\n {% set badge_class = 'badge-already' %}\r\n {% set status_text = 'Already Windows 11' %}\r\n {% else %}\r\n {% set row_class = 'status-not-ready' %}\r\n {% set badge_class = 'badge-not-ready' %}\r\n {% set status_text = 'Not Ready - ' ~ device.custom_fields.Windows11Comp %}\r\n {% endif %}\r\n {% endif %}\r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n {% endfor %}\r\n \r\n
ClientSiteDevice NameUserOperating SystemWindows 11 Compatibility
{{ device.site__client__name or 'N/A' }}{{ device.site__name or 'N/A' }}\r\n {{ device.hostname or 'N/A' }}
\r\n {% if device.last_seen %}\r\n 30 %} class=\"text-danger\" {% endif %}>\r\n Last Seen: {{ device.last_seen.astimezone(ZoneInfo('America/New_York')).strftime('%Y-%m-%d %H:%M:%S') }}\r\n \r\n {% else %}\r\n N/A\r\n {% endif %}\r\n
{{ device.last_logged_in_user or 'N/A' }}{{ device.operating_system or 'N/A' }}\r\n {{ status_text }}\r\n
\r\n
\r\n{% endblock %}", "type": "html", diff --git a/templates/Windows Update Not Installed _By Client (csv).json b/templates/Windows Update Not Installed_By Client (csv).json similarity index 93% rename from templates/Windows Update Not Installed _By Client (csv).json rename to templates/Windows Update Not Installed_By Client (csv).json index e11deb8..051af67 100644 --- a/templates/Windows Update Not Installed _By Client (csv).json +++ b/templates/Windows Update Not Installed_By Client (csv).json @@ -1,7 +1,7 @@ { "base_template": null, "template": { - "name": "Windows Update Not Installed Client (csv)", + "name": "Windows Update Not Installed_By Client (csv)", "template_css": "", "template_md": "Device Name, Title, Installed, Severity,\r\n{% set filtered_items = data_sources.allFieldsWindowsUpdates|selectattr('installed', 'ne', True)|list %}{% for item in filtered_items %}{{item.agent__hostname if item.agent__hostname else 'N/A'}},{{item.title if item.title else 'N/A'}},{{item.installed if item.installed else 'False'}},{{item.severity if item.severity else 'N/A'}}\r\n{% endfor %}", "type": "plaintext", diff --git a/templates/Windows Update Not Installed _By Client.json b/templates/Windows Update Not Installed_By Client.json similarity index 96% rename from templates/Windows Update Not Installed _By Client.json rename to templates/Windows Update Not Installed_By Client.json index 72231bc..3d16d61 100644 --- a/templates/Windows Update Not Installed _By Client.json +++ b/templates/Windows Update Not Installed_By Client.json @@ -4,7 +4,7 @@ "html": "\n\n \n \n \n \n \n {% block content %}{% endblock %}\n {% block header %}{% endblock %}\n \n" }, "template": { - "name": "Windows Update Not Installed _By Client", + "name": "Windows Update Not Installed_By Client", "template_css": "", "template_md": "{% block content %}\r\n

Not Installed Windows Updates

\r\n\r\n\r\n \r\n \r\n\t\r\n\t\r\n\t\r\n\t\r\n \r\n \r\n \r\n{% set filtered_items = data_sources.allFieldsWindowsUpdates|selectattr('installed', 'ne', True)|list %}\r\n{% for item in filtered_items %}\r\n \r\n\t\r\n\t\r\n\t\r\n\t\r\n\r\n \r\n {% endfor %}\r\n \r\n
Device NameTitleInstalledSeverity
{{ item.agent__hostname if item.agent__hostname else 'N/A' }}{{ item.title if item.title else 'N/A' }}{{ item.installed if item.installed else 'False' }}{{ item.severity if item.severity else 'N/A' }}
\r\n\r\n\r\n{% endblock %}", "type": "markdown", diff --git a/test_index.py b/test_index.py index 4931142..a2c3a74 100644 --- a/test_index.py +++ b/test_index.py @@ -1,15 +1,56 @@ import json +from pathlib import Path + +import pytest import validators -def test_index(): - with open("index.json") as f: - index = json.load(f) - - names = [] - for i in index: - assert validators.url(i["download_url"]) - assert i["download_url"].startswith("https://raw.githubusercontent.com/amidaware/reporting-templates/master") - names.append(i["name"]) - - # make sure names are all unique - assert len(names) == len(set(names)) \ No newline at end of file +# Adjust these paths as needed +ROOT = Path(__file__).parent +TEMPLATE_DIR = ROOT / "templates" +INDEX_FILE = ROOT / "index.json" + +# Gather all .json files in the templates directory +TEMPLATE_FILES = list(TEMPLATE_DIR.glob("*.json")) + + +@pytest.mark.parametrize( + "template_file", + TEMPLATE_FILES, + ids=[f.stem for f in TEMPLATE_FILES] +) +def test_template_name_matches_filename(template_file: Path): + """ + Verify that the 'template.name' inside each JSON equals the filename (without .json). + When this fails, pytest will show a string diff between expected vs actual. + """ + content = json.loads(template_file.read_text(encoding="utf-8")) + actual_name = content["template"]["name"] + expected_name = template_file.stem + + # Plain assert gives VSCode a diff view on mismatch + assert actual_name == expected_name + + +def test_index_integrity(): + """ + Validate index.json entries: + - download_url is a valid URL + - download_url starts with the expected base path + - no duplicate names + """ + index = json.loads(INDEX_FILE.read_text(encoding="utf-8")) + seen_names = [] + + for entry in index: + url = entry.get("download_url", "") + # URL format check + assert validators.url(url), f"Invalid URL: {url}" + # Base path check + assert url.startswith( + "https://raw.githubusercontent.com/amidaware/reporting-templates/master" + ), f"URL does not start with expected base: {url}" + # Collect names for duplicate detection + seen_names.append(entry.get("name", "")) + + # Duplicate check + assert len(seen_names) == len(set(seen_names)), "Duplicate names found in index.json"