website: add comparison based on vector.dev's site
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
		| @ -195,9 +195,12 @@ info = openapi.Info( | |||||||
| ) | ) | ||||||
| SchemaView = get_schema_view(info, public=True, permission_classes=(AllowAny,)) | SchemaView = get_schema_view(info, public=True, permission_classes=(AllowAny,)) | ||||||
|  |  | ||||||
| urlpatterns = [ | urlpatterns = ( | ||||||
|  |     [ | ||||||
|         path("", SwaggerView.as_view(), name="swagger"), |         path("", SwaggerView.as_view(), name="swagger"), | ||||||
| ] + router.urls + [ |     ] | ||||||
|  |     + router.urls | ||||||
|  |     + [ | ||||||
|         path( |         path( | ||||||
|             "flows/executor/<slug:flow_slug>/", |             "flows/executor/<slug:flow_slug>/", | ||||||
|             FlowExecutorView.as_view(), |             FlowExecutorView.as_view(), | ||||||
| @ -208,4 +211,5 @@ urlpatterns = [ | |||||||
|             SchemaView.without_ui(cache_timeout=0), |             SchemaView.without_ui(cache_timeout=0), | ||||||
|             name="schema-json", |             name="schema-json", | ||||||
|         ), |         ), | ||||||
| ] |     ] | ||||||
|  | ) | ||||||
|  | |||||||
							
								
								
									
										11
									
								
								website/docs/development/api.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								website/docs/development/api.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | |||||||
|  | --- | ||||||
|  | title: API | ||||||
|  | --- | ||||||
|  |  | ||||||
|  | Starting with 2021.3.5, every authentik instance has a built-in API browser, which can be accessed at https://authentik.company/api/v2beta/. | ||||||
|  |  | ||||||
|  | To generate an API client, you can use the Swagger schema at https://authentik.company/api/v2beta/swagger.json. | ||||||
|  |  | ||||||
|  | While testing, the API requests are authenticated by your browser session. To send an API request from outside the browser, you need to set an `Authorization` header. | ||||||
|  |  | ||||||
|  | The value needs to be set to the base64-encoded token key. | ||||||
| @ -31,6 +31,20 @@ Most functions and classes have type-hints and docstrings, so it is recommended | |||||||
|  |  | ||||||
| By default, no transpiled bundle of the frontend is included. To build the UI, you need Node 12 or newer. | By default, no transpiled bundle of the frontend is included. To build the UI, you need Node 12 or newer. | ||||||
|  |  | ||||||
|  | The Frontend also uses a generated API client to talk with the backend. To generate this client, you can use the [openapitools/openapi-generator-cli](https://github.com/OpenAPITools/openapi-generator) CLI tool. | ||||||
|  |  | ||||||
|  | If you want to generate the client without installing anything, run this command: | ||||||
|  |  | ||||||
|  | ```shell | ||||||
|  | docker run \ | ||||||
|  |   --rm -v $(pwd):/local \ | ||||||
|  |   openapitools/openapi-generator-cli generate \ | ||||||
|  |   -i /local/swagger.yaml \ | ||||||
|  |   -g typescript-fetch \ | ||||||
|  |   -o /local/web/api \ | ||||||
|  |   --additional-properties=typescriptThreePlus=true,supportsES6=true,npmName=authentik-api,npmVersion=1.0.0 | ||||||
|  | ``` | ||||||
|  |  | ||||||
| To build the UI, run these commands: | To build the UI, run these commands: | ||||||
|  |  | ||||||
| ``` | ``` | ||||||
|  | |||||||
| @ -65,8 +65,7 @@ module.exports = { | |||||||
|             { |             { | ||||||
|                 docs: { |                 docs: { | ||||||
|                     sidebarPath: require.resolve("./sidebars.js"), |                     sidebarPath: require.resolve("./sidebars.js"), | ||||||
|                     editUrl: |                     editUrl: "https://github.com/beryju/authentik/edit/master/website/", | ||||||
|                         "https://github.com/beryju/authentik/edit/master/website/", |  | ||||||
|                 }, |                 }, | ||||||
|                 theme: { |                 theme: { | ||||||
|                     customCss: require.resolve("./src/css/custom.css"), |                     customCss: require.resolve("./src/css/custom.css"), | ||||||
|  | |||||||
							
								
								
									
										17
									
								
								website/package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										17
									
								
								website/package-lock.json
									
									
									
										generated
									
									
									
								
							| @ -7609,6 +7609,15 @@ | |||||||
|             "resolved": "https://registry.npmjs.org/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz", |             "resolved": "https://registry.npmjs.org/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz", | ||||||
|             "integrity": "sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ==" |             "integrity": "sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ==" | ||||||
|         }, |         }, | ||||||
|  |         "feather-icons": { | ||||||
|  |             "version": "4.28.0", | ||||||
|  |             "resolved": "https://registry.npmjs.org/feather-icons/-/feather-icons-4.28.0.tgz", | ||||||
|  |             "integrity": "sha512-gRdqKESXRBUZn6Nl0VBq2wPHKRJgZz7yblrrc2lYsS6odkNFDnA4bqvrlEVRUPjE1tFax+0TdbJKZ31ziJuzjg==", | ||||||
|  |             "requires": { | ||||||
|  |                 "classnames": "^2.2.5", | ||||||
|  |                 "core-js": "^3.1.3" | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|         "feed": { |         "feed": { | ||||||
|             "version": "4.2.2", |             "version": "4.2.2", | ||||||
|             "resolved": "https://registry.npmjs.org/feed/-/feed-4.2.2.tgz", |             "resolved": "https://registry.npmjs.org/feed/-/feed-4.2.2.tgz", | ||||||
| @ -14843,6 +14852,14 @@ | |||||||
|             "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.0.tgz", |             "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.0.tgz", | ||||||
|             "integrity": "sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA==" |             "integrity": "sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA==" | ||||||
|         }, |         }, | ||||||
|  |         "react-feather": { | ||||||
|  |             "version": "2.0.9", | ||||||
|  |             "resolved": "https://registry.npmjs.org/react-feather/-/react-feather-2.0.9.tgz", | ||||||
|  |             "integrity": "sha512-yMfCGRkZdXwIs23Zw/zIWCJO3m3tlaUvtHiXlW+3FH7cIT6fiK1iJ7RJWugXq7Fso8ZaQyUm92/GOOHXvkiVUw==", | ||||||
|  |             "requires": { | ||||||
|  |                 "prop-types": "^15.7.2" | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|         "react-helmet": { |         "react-helmet": { | ||||||
|             "version": "6.1.0", |             "version": "6.1.0", | ||||||
|             "resolved": "https://registry.npmjs.org/react-helmet/-/react-helmet-6.1.0.tgz", |             "resolved": "https://registry.npmjs.org/react-helmet/-/react-helmet-6.1.0.tgz", | ||||||
|  | |||||||
| @ -18,7 +18,8 @@ | |||||||
|         "postcss": "^8.2.8", |         "postcss": "^8.2.8", | ||||||
|         "react": "^17.0.1", |         "react": "^17.0.1", | ||||||
|         "react-before-after-slider": "^1.0.4", |         "react-before-after-slider": "^1.0.4", | ||||||
|         "react-dom": "^17.0.1" |         "react-dom": "^17.0.1", | ||||||
|  |         "react-feather": "^2.0.9" | ||||||
|     }, |     }, | ||||||
|     "browserslist": { |     "browserslist": { | ||||||
|         "production": [ |         "production": [ | ||||||
|  | |||||||
| @ -162,7 +162,10 @@ module.exports = { | |||||||
|         { |         { | ||||||
|             type: "category", |             type: "category", | ||||||
|             label: "Development", |             label: "Development", | ||||||
|             items: ["development/local-dev-environment"], |             items: [ | ||||||
|  |                 "development/local-dev-environment", | ||||||
|  |                 "development/api" | ||||||
|  |             ], | ||||||
|         }, |         }, | ||||||
|     ], |     ], | ||||||
| }; | }; | ||||||
|  | |||||||
							
								
								
									
										149
									
								
								website/src/comparison.jsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										149
									
								
								website/src/comparison.jsx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,149 @@ | |||||||
|  | import React from "react"; | ||||||
|  | import { Check, X, AlertTriangle } from "react-feather"; | ||||||
|  |  | ||||||
|  | function Comparison() { | ||||||
|  |     return ( | ||||||
|  |         <section className=""> | ||||||
|  |             <div className="container"> | ||||||
|  |                 <h2 id="correctness">Why authentik?</h2> | ||||||
|  |                 <div className="table-responsive"> | ||||||
|  |                     <table className="comparison"> | ||||||
|  |                         <thead> | ||||||
|  |                             <tr> | ||||||
|  |                                 <th></th> | ||||||
|  |                                 <th className="authentik">authentik</th> | ||||||
|  |                                 <th>Keycloak</th> | ||||||
|  |                                 <th>Microsoft ADFS</th> | ||||||
|  |                                 <th>Microsoft Azure AD</th> | ||||||
|  |                                 <th>Okta</th> | ||||||
|  |                                 <th>Duo</th> | ||||||
|  |                             </tr> | ||||||
|  |                         </thead> | ||||||
|  |                         <thead className="group"> | ||||||
|  |                             <tr> | ||||||
|  |                                 <th>Protocol Support</th> | ||||||
|  |                                 <th></th> | ||||||
|  |                                 <th></th> | ||||||
|  |                                 <th></th> | ||||||
|  |                                 <th></th> | ||||||
|  |                                 <th></th> | ||||||
|  |                                 <th></th> | ||||||
|  |                             </tr> | ||||||
|  |                         </thead> | ||||||
|  |                         <tbody> | ||||||
|  |                             <tr> | ||||||
|  |                                 <td className="row-label">SAML2</td> | ||||||
|  |                                 <td className="result passed authentik"><Check></Check></td> | ||||||
|  |                                 <td className="result passed"><Check></Check></td> | ||||||
|  |                                 <td className="result passed"><Check></Check></td> | ||||||
|  |                                 <td className="result passed"><Check></Check></td> | ||||||
|  |                                 <td className="result passed"><Check></Check></td> | ||||||
|  |                                 <td className="result passed"><Check></Check></td> | ||||||
|  |                             </tr> | ||||||
|  |                             <tr> | ||||||
|  |                                 <td className="row-label">OAuth2 and OIDC</td> | ||||||
|  |                                 <td className="result passed authentik"><Check></Check></td> | ||||||
|  |                                 <td className="result passed"><Check></Check></td> | ||||||
|  |                                 <td className="result passed"><Check></Check></td> | ||||||
|  |                                 <td className="result passed"><Check></Check></td> | ||||||
|  |                                 <td className="result passed"><Check></Check></td> | ||||||
|  |                                 <td className="result passed"><Check></Check></td> | ||||||
|  |                             </tr> | ||||||
|  |                         </tbody> | ||||||
|  |                         <thead className="group"> | ||||||
|  |                             <tr> | ||||||
|  |                                 <th>Use-cases</th> | ||||||
|  |                                 <th></th> | ||||||
|  |                                 <th></th> | ||||||
|  |                                 <th></th> | ||||||
|  |                                 <th></th> | ||||||
|  |                                 <th></th> | ||||||
|  |                                 <th></th> | ||||||
|  |                             </tr> | ||||||
|  |                         </thead> | ||||||
|  |                         <tbody> | ||||||
|  |                             <tr> | ||||||
|  |                                 <td className="row-label">Authentication</td> | ||||||
|  |                                 <td className="result passed authentik"><Check></Check></td> | ||||||
|  |                                 <td className="result passed"><Check></Check></td> | ||||||
|  |                                 <td className="result passed"><Check></Check></td> | ||||||
|  |                                 <td className="result passed"><Check></Check></td> | ||||||
|  |                                 <td className="result passed"><Check></Check></td> | ||||||
|  |                                 <td className="result passed"><Check></Check></td> | ||||||
|  |                             </tr> | ||||||
|  |                             <tr> | ||||||
|  |                                 <td className="row-label">Enrollment</td> | ||||||
|  |                                 <td className="result passed authentik"><Check></Check></td> | ||||||
|  |                                 <td className="result passed"><X></X></td> | ||||||
|  |                                 <td className="result failed"><X></X></td> | ||||||
|  |                                 <td className="result failed"><X></X></td> | ||||||
|  |                                 <td className="result failed"><X></X></td> | ||||||
|  |                                 <td className="result passed"><X></X></td> | ||||||
|  |                             </tr> | ||||||
|  |                             <tr> | ||||||
|  |                                 <td className="row-label">Self-service</td> | ||||||
|  |                                 <td className="result passed authentik"><Check></Check></td> | ||||||
|  |                                 <td className="result passed"><Check></Check></td> | ||||||
|  |                                 <td className="result passed"><Check></Check></td> | ||||||
|  |                                 <td className="result passed"><Check></Check></td> | ||||||
|  |                                 <td className="result passed"><Check></Check></td> | ||||||
|  |                                 <td className="result passed"><Check></Check></td> | ||||||
|  |                             </tr> | ||||||
|  |                         </tbody> | ||||||
|  |                         <thead className="group"> | ||||||
|  |                             <tr> | ||||||
|  |                                 <th>Features</th> | ||||||
|  |                                 <th></th> | ||||||
|  |                                 <th></th> | ||||||
|  |                                 <th></th> | ||||||
|  |                                 <th></th> | ||||||
|  |                                 <th></th> | ||||||
|  |                                 <th></th> | ||||||
|  |                             </tr> | ||||||
|  |                         </thead> | ||||||
|  |                         <tbody> | ||||||
|  |                             <tr> | ||||||
|  |                                 <td className="row-label">MFA</td> | ||||||
|  |                                 <td className="result passed authentik"><Check></Check></td> | ||||||
|  |                                 <td className="result passed"><Check></Check></td> | ||||||
|  |                                 <td className="result failed"><X></X></td> | ||||||
|  |                                 <td className="result failed"><Check></Check></td> | ||||||
|  |                                 <td className="result failed"><Check></Check></td> | ||||||
|  |                                 <td className="result passed"><Check></Check></td> | ||||||
|  |                             </tr> | ||||||
|  |                             <tr> | ||||||
|  |                                 <td className="row-label">Conditional Access</td> | ||||||
|  |                                 <td className="result passed authentik"><Check></Check></td> | ||||||
|  |                                 <td className="result passed"><Check></Check></td> | ||||||
|  |                                 <td className="result passed"><Check></Check></td> | ||||||
|  |                                 <td className="result warning"><AlertTriangle></AlertTriangle></td> | ||||||
|  |                                 <td className="result passed"><Check></Check></td> | ||||||
|  |                                 <td className="result warning"><AlertTriangle></AlertTriangle></td> | ||||||
|  |                             </tr> | ||||||
|  |                             <tr> | ||||||
|  |                                 <td className="row-label">Open-source</td> | ||||||
|  |                                 <td className="result passed authentik"><Check></Check></td> | ||||||
|  |                                 <td className="result passed"><Check></Check></td> | ||||||
|  |                                 <td className="result failed"><X></X></td> | ||||||
|  |                                 <td className="result failed"><X></X></td> | ||||||
|  |                                 <td className="result failed"><X></X></td> | ||||||
|  |                                 <td className="result failed"><X></X></td> | ||||||
|  |                             </tr> | ||||||
|  |                             <tr> | ||||||
|  |                                 <td className="row-label">Application Proxy</td> | ||||||
|  |                                 <td className="result passed authentik"><Check></Check></td> | ||||||
|  |                                 <td className="result warning"><AlertTriangle></AlertTriangle></td> | ||||||
|  |                                 <td className="result warning"><AlertTriangle></AlertTriangle></td> | ||||||
|  |                                 <td className="result failed"><X></X></td> | ||||||
|  |                                 <td className="result failed"><X></X></td> | ||||||
|  |                                 <td className="result failed"><X></X></td> | ||||||
|  |                             </tr> | ||||||
|  |                         </tbody> | ||||||
|  |                     </table> | ||||||
|  |                 </div> | ||||||
|  |             </div> | ||||||
|  |         </section> | ||||||
|  |     ); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | export default Comparison; | ||||||
| @ -35,3 +35,153 @@ | |||||||
| .hero_image > img { | .hero_image > img { | ||||||
|     max-height: 200px; |     max-height: 200px; | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | table { | ||||||
|  |     display: table; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .table-responsive { | ||||||
|  |     overflow-x: auto; | ||||||
|  | } | ||||||
|  | /** | ||||||
|  | * comparison | ||||||
|  | * | ||||||
|  | * Comparison table used in both the performance and correctness tables. | ||||||
|  | */ | ||||||
|  |  | ||||||
|  | table.comparison { | ||||||
|  |     width: 100%; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | table.comparison [title], | ||||||
|  | table.comparison [title] { | ||||||
|  |     text-decoration: underline; | ||||||
|  |     text-decoration-style: dotted; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | table.comparison th, | ||||||
|  | table.comparison td, | ||||||
|  | table.comparison tr { | ||||||
|  |     border: 0px none; | ||||||
|  |     white-space: nowrap; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | table.comparison th { | ||||||
|  |     padding-left: 0; | ||||||
|  |     padding-right: 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | table.comparison tr th.authentik { | ||||||
|  |     color: var(--ifm-color-primary); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | table.comparison thead.group tr { | ||||||
|  |     border-bottom: 1px; | ||||||
|  |     border-bottom-color: var(--ifm-table-head-color); | ||||||
|  |     border-bottom-style: solid; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | table.comparison thead.group th:first-child { | ||||||
|  |     text-align: left; | ||||||
|  |     font-weight: 800; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | table.comparison tr td { | ||||||
|  |     border-left: 10px solid transparent; | ||||||
|  |     min-width: 90px; | ||||||
|  |     text-align: center; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | table.comparison tr td:first-child { | ||||||
|  |     font-weight: bold; | ||||||
|  |     padding-left: 0; | ||||||
|  |     text-align: left; | ||||||
|  |     white-space: nowrap; | ||||||
|  |     width: 25%; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | table.comparison tr td.description { | ||||||
|  |     font-weight: normal; | ||||||
|  |     min-width: 250px; | ||||||
|  |     padding-top: 0; | ||||||
|  |     vertical-align: top; | ||||||
|  |     white-space: normal; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | table.comparison tr td.description .label { | ||||||
|  |     color: var(--ifm-heading-color); | ||||||
|  |     font-weight: bold; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | table.comparison tr td.description .text { | ||||||
|  |     color: var(--ifm-color-emphasis-600); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | table.comparison tr td.description .links { | ||||||
|  |     font-size: 0.9em; | ||||||
|  |     margin-top: var(--ifm-spacing-vertical); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | table.comparison tr td.result { | ||||||
|  |     background-color: var(--ifm-panel-background-color); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | table.comparison tr td.result.failed { | ||||||
|  |     color: var(--ifm-color-danger); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | table.comparison tr td.result.lost { | ||||||
|  |     background: var(--ifm-color-emphasis-1000); | ||||||
|  |     color: transparent; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | table.comparison tr td.result.not-applicable { | ||||||
|  |     background: var(--ifm-color-emphasis-1000); | ||||||
|  |     color: rgba(var(--ifm-background-color-rgb), 0.5); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | table.comparison tr td.result.passed { | ||||||
|  |     color: var(--ifm-color-success); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | table.comparison tr td.result.warning { | ||||||
|  |     color: var(--ifm-color-warning); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | table.comparison tr td.result.passed.authentik { | ||||||
|  |     background: var(--ifm-color-primary); | ||||||
|  |     color: var(--ifm-background-color); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | table.comparison tr td.bar { | ||||||
|  |     padding: 0; | ||||||
|  |     vertical-align: bottom; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | table.comparison tr td.bar .place { | ||||||
|  |     font-size: 0.9em; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | table.comparison tr td.bar .measurement { | ||||||
|  |     font-weight: bold; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | table.comparison tr td.bar .bar { | ||||||
|  |     background: var(--ifm-color-emphasis-1000); | ||||||
|  |     margin: 0 auto; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | table.comparison tr td.bar.authentik { | ||||||
|  |     color: var(--ifm-color-primary); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | table.comparison tr td.bar.authentik .bar { | ||||||
|  |     background: var(--ifm-color-primary); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @media (max-width: 996px) { | ||||||
|  |     table.comparison td.description { | ||||||
|  |         display: none; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | |||||||
| @ -6,6 +6,7 @@ import useDocusaurusContext from "@docusaurus/useDocusaurusContext"; | |||||||
| import useBaseUrl from "@docusaurus/useBaseUrl"; | import useBaseUrl from "@docusaurus/useBaseUrl"; | ||||||
| import styles from "./styles.module.css"; | import styles from "./styles.module.css"; | ||||||
| import BeforeAfterSlider from 'react-before-after-slider' | import BeforeAfterSlider from 'react-before-after-slider' | ||||||
|  | import Comparison from "../comparison"; | ||||||
|  |  | ||||||
| const features = [ | const features = [ | ||||||
|     { |     { | ||||||
| @ -150,6 +151,9 @@ function Home() { | |||||||
|                         </div> |                         </div> | ||||||
|                     </div> |                     </div> | ||||||
|                 </section> |                 </section> | ||||||
|  |                 <section> | ||||||
|  |                     <Comparison></Comparison> | ||||||
|  |                 </section> | ||||||
|             </main> |             </main> | ||||||
|         </Layout> |         </Layout> | ||||||
|     ); |     ); | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user
	 Jens Langhammer
					Jens Langhammer