diff --git a/data_import/import.js b/data_import/import.js
index 24a0292..aa84bf3 100644
--- a/data_import/import.js
+++ b/data_import/import.js
@@ -30,8 +30,8 @@ const docs = [
const errors = [];
const nmDocs = 'C:\\Users\\vle2fe\\Documents\\Data\\All_200717\\nmDocs'; // NormMaster Documents
const dptFiles = 'C:\\Users\\vle2fe\\Documents\\Data\\All_200717\\DPT'; // Spectrum files
-// const host = 'http://localhost:3000';
-const host = 'https://definma-api.apps.de1.bosch-iot-cloud.com';
+const host = 'http://localhost:3000';
+// const host = 'https://definma-api.apps.de1.bosch-iot-cloud.com';
const requiredProperties = ['samplenumber','materialnumber','materialname','supplier','reinforcementmaterial','material','granulate/part','color','charge/batch','comments'];
dict = { // dictionary
'Granulat': 'granulate',
diff --git a/package-lock.json b/package-lock.json
index 34fb53e..6749f0a 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -3773,17 +3773,9 @@
}
},
"swagger-ui-dist": {
- "version": "3.24.3",
- "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-3.24.3.tgz",
- "integrity": "sha512-kB8qobP42Xazaym7sD9g5mZuRL4416VIIYZMqPEIskkzKqbPLQGEiHA3ga31bdzyzFLgr6Z797+6X1Am6zYpbg=="
- },
- "swagger-ui-express": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/swagger-ui-express/-/swagger-ui-express-4.1.2.tgz",
- "integrity": "sha512-bVT16qj6WdNlEKFkSLOoTeGuqEm2lfOFRq6mVHAx+viA/ikORE+n4CS3WpVcYmQzM4HE6+DUFgAWcMRBJNpjcw==",
- "requires": {
- "swagger-ui-dist": "^3.18.1"
- }
+ "version": "3.30.2",
+ "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-3.30.2.tgz",
+ "integrity": "sha512-hAu/ig5N8i0trXXbrC7rwbXV4DhpEAsZhYXDs1305OjmDgjGC0thINbb0197idy3Pp+B6w7u426SUM43GAP7qw=="
},
"term-size": {
"version": "2.2.0",
diff --git a/package.json b/package.json
index ae69e4f..7bf20ea 100644
--- a/package.json
+++ b/package.json
@@ -37,7 +37,7 @@
"lodash": "^4.17.15",
"mongo-sanitize": "^1.1.0",
"mongoose": "^5.8.7",
- "swagger-ui-express": "4.1.2"
+ "swagger-ui-dist": "^3.30.2"
},
"devDependencies": {
"@types/bcrypt": "^3.0.0",
diff --git a/src/api.ts b/src/api.ts
index aab7b80..d82a99e 100644
--- a/src/api.ts
+++ b/src/api.ts
@@ -1,48 +1,131 @@
-import swagger from 'swagger-ui-express';
+import express from 'express';
+import swaggerUi from 'swagger-ui-dist';
import jsonRefParser, {JSONSchema} from '@apidevtools/json-schema-ref-parser';
import oasParser from '@apidevtools/swagger-parser';
-// modifies the normal swagger-ui-express package
+// modified from https://github.com/scottie1984/swagger-ui-express
// usage: app.use('/api-doc', api.serve(), api.setup());
// the paths property can be split using allOf
// further route documentation can be included in the x-doc property
-export default class api {
- static serve () {
- return swagger.serve;
- }
- static setup () {
- let apiDoc: JSONSchema = {};
- jsonRefParser.bundle('api/api.yaml', (err, doc) => { // parse yaml
- if (err) throw err;
- apiDoc = doc;
- apiDoc.servers.splice(process.env.NODE_ENV === 'production', 1);
- apiDoc.paths = apiDoc.paths.allOf.reduce((s, e) => Object.assign(s, e)); // bundle routes
- apiDoc = this.resolveXDoc(apiDoc);
- oasParser.validate(apiDoc, (err, api) => { // validate oas schema
- if (err) {
- console.error(err);
- }
- else {
- console.info(process.env.NODE_ENV === 'test' ? '' : 'API ok, version ' + api.info.version);
- swagger.setup(apiDoc);
- }
- });
- });
- return swagger.setup(apiDoc, {customCssUrl: '/static/styles/swagger.css'})
- }
-
- private static resolveXDoc (doc) { // resolve x-doc properties recursively
- Object.keys(doc).forEach(key => {
- if (doc[key] !== null && doc[key].hasOwnProperty('x-doc')) { // add x-doc to description, is styled via css
- doc[key].description += 'docs
' + doc[key]['x-doc'] + ' ';
+export default function api () {
+ // generate apiDoc
+ let apiDoc: JSONSchema = {};
+ jsonRefParser.bundle('api/api.yaml', (err, doc) => { // parse yaml
+ if (err) throw err;
+ apiDoc = doc;
+ apiDoc.servers.splice(process.env.NODE_ENV === 'production', 1);
+ apiDoc.paths = apiDoc.paths.allOf.reduce((s, e) => Object.assign(s, e)); // bundle routes
+ apiDoc = resolveXDoc(apiDoc);
+ oasParser.validate(apiDoc, (err, api) => { // validate oas schema
+ if (err) {
+ console.error(err);
}
- else if (typeof doc[key] === 'object' && doc[key] !== null) { // go deeper into recursion
- doc[key] = this.resolveXDoc(doc[key]);
+ else {
+ console.info(process.env.NODE_ENV === 'test' ? '' : 'API ok, version ' + api.info.version);
}
});
- return doc;
- }
-}
\ No newline at end of file
+ });
+
+ return [
+ (req, res, next) => { // serve init js and apiDoc file
+ switch (req.url) {
+ case '/swagger-ui-init.js':
+ res.set('Content-Type', 'application/javascript');
+ res.send(jsTplString);
+ break;
+ case '/apidoc.json':
+ res.set('Content-Type', 'application/json');
+ res.send(apiDoc);
+ break;
+ default:
+ next();
+ }
+ }, // serve swagger files
+ express.static(swaggerUi.getAbsoluteFSPath(), {index: false}),
+ (req, res) => { // serve html file as default
+ res.send(htmlTplString);
+ }
+ ];
+}
+
+
+function resolveXDoc (doc) { // resolve x-doc properties recursively
+ Object.keys(doc).forEach(key => {
+ if (doc[key] !== null && doc[key].hasOwnProperty('x-doc')) { // add x-doc to description, is styled via css
+ doc[key].description += 'docs
' + doc[key]['x-doc'] + ' ';
+ }
+ else if (typeof doc[key] === 'object' && doc[key] !== null) { // go deeper into recursion
+ doc[key] = resolveXDoc(doc[key]);
+ }
+ });
+ return doc;
+}
+
+
+// templates
+
+const htmlTplString = `
+
+
+
+
+ API documentation
+
+
+
+
+
+
+
+
+
+
+
+
+`;
+
+const jsTplString = `
+window.onload = function() {
+ // Build a system
+ window.ui = SwaggerUIBundle({
+ url: '/api-doc/apidoc.json',
+ dom_id: '#swagger-ui',
+ deepLinking: true,
+ presets: [
+ SwaggerUIBundle.presets.apis,
+ SwaggerUIStandalonePreset
+ ],
+ plugins: [
+ SwaggerUIBundle.plugins.DownloadUrl
+ ],
+ layout: 'StandaloneLayout'
+ });
+}
+`;
\ No newline at end of file
diff --git a/src/index.ts b/src/index.ts
index d6ea865..b7b5e2e 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -24,8 +24,38 @@ app.disable('x-powered-by');
// get port from environment, defaults to 3000
const port = process.env.PORT || 3000;
-//middleware
-app.use(helmet());
+// security headers
+app.use(helmet({
+ contentSecurityPolicy: {
+ directives: {
+ defaultSrc: [`'none'`],
+ baseUri: [`'self'`],
+ formAction: [`'none'`],
+ frameAncestors: [`'none'`]
+ }
+ }
+}));
+// special CSP header for api-doc
+app.use('/api-doc', helmet.contentSecurityPolicy({
+ directives: {
+ defaultSrc: [`'none'`],
+ scriptSrc: [`'self'`],
+ connectSrc: [`'self'`],
+ styleSrc: [`'self'`, `'unsafe-inline'`],
+ imgSrc: [`'self'`, 'data:'],
+ baseUri: [`'self'`],
+ formAction: [`'none'`],
+ frameAncestors: [`'none'`]
+ }
+}));
+// special CSP header for the bosch-logo.svg
+app.use('/static/img/bosch-logo.svg', helmet.contentSecurityPolicy({
+ directives: {
+ styleSrc: [`'unsafe-inline'`]
+ }
+}));
+
+// middleware
app.use(contentFilter()); // filter URL query attacks
app.use(express.json({ limit: '5mb'}));
app.use(express.urlencoded({ extended: false, limit: '5mb' }));
@@ -71,7 +101,7 @@ app.use('/', require('./routes/measurement'));
app.use('/static', express.static('static'));
// Swagger UI
-app.use('/api-doc', api.serve(), api.setup());
+app.use('/api-doc', api());
app.use((req, res) => { // 404 error handling
res.status(404).json({status: 'Not found'});
diff --git a/src/routes/template.ts b/src/routes/template.ts
index 20f1b3b..5641d1b 100644
--- a/src/routes/template.ts
+++ b/src/routes/template.ts
@@ -44,7 +44,14 @@ router.put('/template/:collection(measurement|condition|material)/' + IdValidate
const {error, value: template} = TemplateValidate.input(req.body, 'change');
if (error) return res400(error, res);
- const templateData = await model(req).findById(req.params.id).lean().exec().catch(err => {next(err);}) as any;
+ // find given template
+ const templateRef = await model(req).findById(req.params.id).lean().exec().catch(err => {next(err);}) as any;
+ if (templateRef instanceof Error) return;
+ if (!templateRef) {
+ return res.status(404).json({status: 'Not found'});
+ }
+ // find latest version
+ const templateData = await model(req).findOne({first_id: templateRef.first_id}).sort({version: -1}).lean().exec().catch(err => {next(err);}) as any;
if (templateData instanceof Error) return;
if (!templateData) {
return res.status(404).json({status: 'Not found'});
diff --git a/static/img/favicon.ico b/static/img/favicon.ico
new file mode 100644
index 0000000..41ab513
Binary files /dev/null and b/static/img/favicon.ico differ
diff --git a/static/styles/swagger-ui.css b/static/styles/swagger-ui.css
new file mode 100644
index 0000000..9372efb
--- /dev/null
+++ b/static/styles/swagger-ui.css
@@ -0,0 +1,323 @@
+/*Bosch styling for swagger*/
+
+/*GET: dark blue*/
+/*POST: dark green*/
+/*PUT: turquoise*/
+/*DELETE: fuchsia*/
+
+:root {
+ --red: #ea0016;
+ --dark-blue: #005691;
+ --dark-blue-w75: #bfd5e3;
+ --dark-green: #006249;
+ --dark-green-w75: #bfd8d1;
+ --turquoise: #00a8b0;
+ --turquoise-w75: #bfe9eb;
+ --fuchsia: #b90276;
+ --fuchsia-w75: #edc0dd;
+ --light-grey: #bfc0c2;
+ --light-grey-w75: #efeff0;
+ --light-green: #78be20;
+}
+
+body {
+ background: #fff;
+}
+
+body:before {
+ position: absolute;
+ left: 0;
+ top: 0;
+ width: 100%;
+ height: 16px;
+ content: '';
+ background-repeat: no-repeat;
+ background-size: cover;
+ background-image: url(/static/img/header.svg);
+}
+
+body:after {
+ position: absolute;
+ right: 25px;
+ top: 36px;
+ width: 135px;
+ height: 48px;
+ content: '';
+ background-repeat: no-repeat;
+ background-size: cover;
+ background-image: url(/static/img/bosch-logo.svg);
+}
+
+.swagger-ui {
+ font-family: "Bosch Sans", sans-serif;
+}
+
+/*custom docs*/
+.docs {
+ position: relative;
+ font-size: 14px;
+}
+
+.docs > summary {
+ position: absolute;
+ right: 0;
+ top: -25px;
+ cursor: pointer;
+}
+
+.docs-open:hover {
+ text-decoration: underline;
+}
+
+/*Remove topbar*/
+.swagger-ui .topbar {
+ display: none
+}
+
+/*Remove models view*/
+.swagger-ui .models {
+ display: none;
+}
+
+/*Remove application/json select*/
+.swagger-ui .opblock .opblock-section-header > label, .swagger-ui .response-controls {
+ display: none;
+}
+
+/*Remove border radius*/
+.swagger-ui .opblock, .swagger-ui .opblock .opblock-summary-method, .swagger-ui select {
+ border-radius: 0;
+ box-shadow: none;
+}
+
+/*remove links in response*/
+.swagger-ui .response-col_links {
+ display: none;
+}
+
+/*remove version*/
+.swagger-ui .info .title span {
+ display: none;
+}
+
+/*separator before methods*/
+.swagger-ui .scheme-container {
+ box-shadow: none;
+ border-bottom: 1px solid var(--light-grey);
+}
+
+/*tag separator*/
+.swagger-ui .opblock-tag {
+ border-bottom: 1px solid var(--light-grey);
+}
+
+/*parameters/responses bar*/
+.swagger-ui .opblock .opblock-section-header {
+ box-shadow: none;
+ background: #fff;
+}
+
+/*select*/
+.swagger-ui select {
+ background-color: var(--light-grey-w75);
+ border: none;
+ height: 36px;
+}
+
+/*button*/
+.swagger-ui .btn {
+ border-radius: 0;
+ box-shadow: none;
+}
+
+.swagger-ui .btn:hover {
+ box-shadow: none;
+}
+
+/*authorize button */
+.swagger-ui .btn.authorize {
+ color: var(--light-green);
+ border-color: var(--light-green);
+}
+
+.swagger-ui .btn.authorize svg {
+ fill: var(--light-green);
+}
+
+/*auth inputs*/
+.swagger-ui .auth-container input[type="password"], .swagger-ui .auth-container input[type="text"] {
+ border-radius: 0;
+ box-shadow: none;
+ border-color: var(--light-grey);
+}
+
+.swagger-ui .dialog-ux .modal-ux {
+ border-radius: 0;
+}
+
+/*cancel button*/
+.swagger-ui .btn.cancel {
+ color: var(--red);
+ border-color: var(--red);
+}
+
+/*download button*/
+.swagger-ui .download-contents {
+ border-radius: 0;
+ height: 28px;
+ width: 80px;
+}
+
+/*model*/
+.swagger-ui .model-box {
+ border-radius: 0;
+}
+
+/*execute button*/
+.swagger-ui .btn.execute {
+ background-color: var(--dark-blue);
+ border-color: var(--dark-blue);
+ height: 30px;
+ line-height: 0.7;
+}
+
+.swagger-ui .btn-group .btn:last-child {
+ border-radius: 0;
+ height: 30px;
+ border-color: var(--dark-blue);
+}
+
+.swagger-ui .btn-group .btn:first-child {
+ border-radius: 0;
+}
+
+.swagger-ui .btn-group {
+ padding: 0 20px;
+}
+
+/*parameter input*/
+.swagger-ui .parameters-col_description input[type="text"] {
+ border-radius: 0;
+}
+
+/*required label*/
+.swagger-ui .parameter__name.required > span {
+ color: var(--red) !important;
+}
+
+.swagger-ui .parameter__name.required::after {
+ color: var(--red);
+}
+/*Remove colored parameters bar*/
+.swagger-ui .opblock.opblock-get .tab-header .tab-item.active h4 span::after, .swagger-ui .opblock.opblock-post .tab-header .tab-item.active h4 span::after, .swagger-ui .opblock.opblock-put .tab-header .tab-item.active h4 span::after, .swagger-ui .opblock.opblock-delete .tab-header .tab-item.active h4 span::after {
+ background: none;
+}
+
+/*code*/
+.swagger-ui .opblock-body pre.microlight {
+ border-radius: 0;
+}
+
+.swagger-ui .highlight-code > .microlight {
+ min-height: 0;
+}
+
+/*request body*/
+.swagger-ui textarea {
+ border-radius: 0;
+}
+
+/*parameters smaller padding*/
+.swagger-ui .execute-wrapper {
+ padding-top: 0;
+ padding-bottom: 0;
+}
+
+.swagger-ui .btn.execute {
+ margin-bottom: 20px;
+}
+
+.swagger-ui .opblock-description-wrapper {
+ margin-top: 20px;
+}
+
+.swagger-ui .opblock-description-wrapper {
+ margin-top: 5px;
+}
+
+.opblock-section .opblock-section-request-body > div > div {
+ padding-top: 18px;
+}
+
+/*response element positions*/
+.swagger-ui .model-example {
+ position: relative;
+ margin-top: 0;
+}
+
+.swagger-ui .tab {
+ position: absolute;
+ top: -35px;
+ right: 0;
+}
+
+.swagger-ui table tbody tr td {
+ padding: 0;
+}
+
+.swagger-ui .renderedMarkdown p {
+ margin: 8px auto;
+}
+
+/*Method colors*/
+.swagger-ui .opblock.opblock-get .opblock-summary-method {
+ background: var(--dark-blue);
+}
+
+.swagger-ui .opblock.opblock-get .opblock-summary {
+ border-color: var(--dark-blue);
+}
+
+.swagger-ui .opblock.opblock-get {
+ background: var(--dark-blue-w75);
+ border-color: var(--dark-blue);
+}
+
+.swagger-ui .opblock.opblock-post .opblock-summary-method {
+ background: var(--dark-green);
+}
+
+.swagger-ui .opblock.opblock-post .opblock-summary {
+ border-color: var(--dark-green);
+}
+
+.swagger-ui .opblock.opblock-post {
+ background: var(--dark-green-w75);
+ border-color: var(--dark-green);
+}
+
+.swagger-ui .opblock.opblock-put .opblock-summary-method {
+ background: var(--turquoise);
+}
+
+.swagger-ui .opblock.opblock-put .opblock-summary {
+ border-color: var(--turquoise);
+}
+
+.swagger-ui .opblock.opblock-put {
+ background: var(--turquoise-w75);
+ border-color: var(--turquoise);
+}
+
+.swagger-ui .opblock.opblock-delete .opblock-summary-method {
+ background: var(--fuchsia);
+}
+
+.swagger-ui .opblock.opblock-delete .opblock-summary {
+ border-color: var(--fuchsia);
+}
+
+.swagger-ui .opblock.opblock-delete {
+ background: var(--fuchsia-w75);
+ border-color: var(--fuchsia);
+}
\ No newline at end of file
diff --git a/static/styles/swagger.css b/static/styles/swagger.css
deleted file mode 100644
index 9760ed4..0000000
--- a/static/styles/swagger.css
+++ /dev/null
@@ -1,323 +0,0 @@
-/*Bosch styling for swagger*/
-
-/*GET: dark blue*/
-/*POST: dark green*/
-/*PUT: turquoise*/
-/*DELETE: fuchsia*/
-
-:root {
- --red: #ea0016;
- --dark-blue: #005691;
- --dark-blue-w75: #bfd5e3;
- --dark-green: #006249;
- --dark-green-w75: #bfd8d1;
- --turquoise: #00a8b0;
- --turquoise-w75: #bfe9eb;
- --fuchsia: #b90276;
- --fuchsia-w75: #edc0dd;
- --light-grey: #bfc0c2;
- --light-grey-w75: #efeff0;
- --light-green: #78be20;
-}
-
-body {
- background: #fff;
-}
-
-body:before {
- position: absolute;
- left: 0;
- top: 0;
- width: 100%;
- height: 16px;
- content: '';
- background-repeat: no-repeat;
- background-size: cover;
- background-image: url(data:image/svg+xml;base64,PHN2ZwogIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICB4bWw6c3BhY2U9InByZXNlcnZlIgogIGhlaWdodD0iMzAwIgogIHdpZHRoPSI3MjAiCiAgdmVyc2lvbj0iMS4xIgogIHk9IjAiCiAgeD0iMCIKICB2aWV3Qm94PSIwIDAgNzIwIDMwMCI+CiAgPHN0eWxlIHR5cGU9InRleHQvY3NzIj4KICAgIC5zdDAgewogICAgICBmaWxsOiB1cmwoIiNTVkdJRF8xXyIpOwogICAgfQogICAgLnN0MSB7CiAgICAgIGZpbGw6IHVybCgiI1NWR0lEXzJfIik7CiAgICB9CiAgICAuc3QyIHsKICAgICAgZmlsbDogdXJsKCIjU1ZHSURfM18iKTsKICAgIH0KICAgIC5zdDMgewogICAgICBmaWxsOiB1cmwoIiNTVkdJRF80XyIpOwogICAgfQogICAgLnN0NCB7CiAgICAgIGZpbGw6IHVybCgiI1NWR0lEXzVfIik7CiAgICB9CiAgICAuc3Q1IHsKICAgICAgZmlsbDogI0FGMjAyNDsKICAgIH0KICAgIC5zdDYgewogICAgICBmaWxsOiB1cmwoIiNTVkdJRF82XyIpOwogICAgfQogICAgLnN0NyB7CiAgICAgIGZpbGw6ICM5NDFCMUU7CiAgICB9CiAgICAuc3Q4IHsKICAgICAgZmlsbDogI0IxMjczOTsKICAgIH0KICAgIC5zdDkgewogICAgICBmaWxsOiAjOTUyNDMyOwogICAgfQogICAgLnN0MTAgewogICAgICBmaWxsOiAjRDQyMDI3OwogICAgfQogICAgLnN0MTEgewogICAgICBmaWxsOiB1cmwoIiNTVkdJRF83XyIpOwogICAgfQogICAgLnN0MTIgewogICAgICBmaWxsOiB1cmwoIiNTVkdJRF84XyIpOwogICAgfQogICAgLnN0MTMgewogICAgICBmaWxsOiAjMUM5QTQ4OwogICAgfQogICAgLnN0MTQgewogICAgICBmaWxsOiB1cmwoIiNTVkdJRF85XyIpOwogICAgfQogICAgLnN0MTUgewogICAgICBmaWxsOiB1cmwoIiNTVkdJRF8xMF8iKTsKICAgIH0KICAgIC5zdDE2IHsKICAgICAgZmlsbDogIzJBMzg4NjsKICAgIH0KICAgIC5zdDE3IHsKICAgICAgZmlsbDogdXJsKCIjU1ZHSURfMTFfIik7CiAgICB9CiAgICAuc3QxOCB7CiAgICAgIGZpbGw6IHVybCgiI1NWR0lEXzEyXyIpOwogICAgfQogICAgLnN0MTkgewogICAgICBmaWxsOiB1cmwoIiNTVkdJRF8xM18iKTsKICAgIH0KICAgIC5zdDIwIHsKICAgICAgZmlsbDogdXJsKCIjU1ZHSURfMTRfIik7CiAgICB9CiAgPC9zdHlsZT4KICA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMS41NSwtMy4zKSI+CiAgICA8bGluZWFyR3JhZGllbnQgaWQ9IlNWR0lEXzFfIiB5Mj0iLTMyLjY2MyIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiIHkxPSItMzIuNjYzIiBncmFkaWVudFRyYW5zZm9ybT0ibWF0cml4KDEgMCAwIC0xIC0xMTguOTggMTIwLjU0KSIgeDI9Ijg0Mi4wOCIgeDE9IjExOC45OCI+PHN0b3Agc3RvcC1jb2xvcj0iIzk1MjMzMSIgb2Zmc2V0PSIwIi8+PHN0b3Agc3RvcC1jb2xvcj0iIzkyMUMxRCIgb2Zmc2V0PSIuMDM2MDk0Ii8+PHN0b3Agc3RvcC1jb2xvcj0iI0IwMjczOSIgb2Zmc2V0PSIuMDg0NjQ5Ii8+PHN0b3Agc3RvcC1jb2xvcj0iI0FEMUYyNCIgb2Zmc2V0PSIuMTIzNyIvPjxzdG9wIHN0b3AtY29sb3I9IiNDNzIwMjYiIG9mZnNldD0iLjE1MDkiLz48c3RvcCBzdG9wLWNvbG9yPSIjRDQyMDI3IiBvZmZzZXQ9Ii4xNjk3Ii8+PHN0b3Agc3RvcC1jb2xvcj0iI0NDMjQzMSIgb2Zmc2V0PSIuMTc1OCIvPjxzdG9wIHN0b3AtY29sb3I9IiNCNzJCNEMiIG9mZnNldD0iLjE4ODgiLz48c3RvcCBzdG9wLWNvbG9yPSIjOTUzMzcxIiBvZmZzZXQ9Ii4yMDc0Ii8+PHN0b3Agc3RvcC1jb2xvcj0iIzg4MzU3RiIgb2Zmc2V0PSIuMjE0MiIvPjxzdG9wIHN0b3AtY29sb3I9IiM4NTM2ODEiIG9mZnNldD0iLjI0MzYiLz48c3RvcCBzdG9wLWNvbG9yPSIjNkYzNjhCIiBvZmZzZXQ9Ii4yNjM4Ii8+PHN0b3Agc3RvcC1jb2xvcj0iIzM5NDI4RiIgb2Zmc2V0PSIuMjkxMSIvPjxzdG9wIHN0b3AtY29sb3I9IiMyMzNEN0QiIG9mZnNldD0iLjMyNDIiLz48c3RvcCBzdG9wLWNvbG9yPSIjMzIyQzZGIiBvZmZzZXQ9Ii40MTgxIi8+PHN0b3Agc3RvcC1jb2xvcj0iIzJBMzg4NSIgb2Zmc2V0PSIuNDk0Ii8+PHN0b3Agc3RvcC1jb2xvcj0iIzFENjJBMSIgb2Zmc2V0PSIuNTU4MSIvPjxzdG9wIHN0b3AtY29sb3I9IiMyNzZDQTUiIG9mZnNldD0iLjU3MDIiLz48c3RvcCBzdG9wLWNvbG9yPSIjNDM4RUIzIiBvZmZzZXQ9Ii42MTAzIi8+PHN0b3Agc3RvcC1jb2xvcj0iIzU1QTVCQyIgb2Zmc2V0PSIuNjM5OSIvPjxzdG9wIHN0b3AtY29sb3I9IiM1Q0FGQkYiIG9mZnNldD0iLjY1NTYiLz48c3RvcCBzdG9wLWNvbG9yPSIjNTZBQkJEIiBvZmZzZXQ9Ii42Nzc3Ii8+PHN0b3Agc3RvcC1jb2xvcj0iIzQzOUZCOCIgb2Zmc2V0PSIuNzA1OCIvPjxzdG9wIHN0b3AtY29sb3I9IiMxODhFQUYiIG9mZnNldD0iLjczNzIiLz48c3RvcCBzdG9wLWNvbG9yPSIjMDM4QkFFIiBvZmZzZXQ9Ii43NDI2Ii8+PHN0b3Agc3RvcC1jb2xvcj0iIzA2OTI5MiIgb2Zmc2V0PSIuNzg5OCIvPjxzdG9wIHN0b3AtY29sb3I9IiMwNUExNEIiIG9mZnNldD0iLjg4NzUiLz48c3RvcCBzdG9wLWNvbG9yPSIjMDM5MjdFIiBvZmZzZXQ9IjEiLz48L2xpbmVhckdyYWRpZW50PjxyZWN0IHdpZHRoPSI3MjMuMSIgeT0iMCIgeD0iMCIgaGVpZ2h0PSIzMDYuNCIgY2xhc3M9InN0MCIgZmlsbD0idXJsKCNTVkdJRF8xXykiLz4KICAgIDxsaW5lYXJHcmFkaWVudCBpZD0iU1ZHSURfMl8iIHkyPSItMTA5LjI2IiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeTE9Ii0xMDkuMjYiIGdyYWRpZW50VHJhbnNmb3JtPSJtYXRyaXgoMSAwIDAgLTEgLTExOC45OCAxMjAuNTQpIiB4Mj0iMjM1Ljk4IiB4MT0iMzI1LjA4Ij48c3RvcCBzdG9wLWNvbG9yPSIjODkzNjgwIiBvZmZzZXQ9IjAiLz48c3RvcCBzdG9wLWNvbG9yPSIjODkzNjgwIiBvZmZzZXQ9Ii4zMzU0Ii8+PHN0b3Agc3RvcC1jb2xvcj0iIzhEMzE2RCIgb2Zmc2V0PSIuNTAyNSIvPjxzdG9wIHN0b3AtY29sb3I9IiM5MDI5NEQiIG9mZnNldD0iLjgzOTgiLz48c3RvcCBzdG9wLWNvbG9yPSIjOTAyNTQxIiBvZmZzZXQ9IjEiLz48L2xpbmVhckdyYWRpZW50Pjxwb2x5Z29uIHBvaW50cz0iMTc1LjEgMTUzLjIgMTE3IDMwNi40IDIwNi4xIDMwNi40IiBmaWxsPSJ1cmwoI1NWR0lEXzJfKSIgY2xhc3M9InN0MSIvPgogICAgPGxpbmVhckdyYWRpZW50IGlkPSJTVkdJRF8zXyIgeTI9Ii04Mi4yODQiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIiB5MT0iMTIwLjI0IiBncmFkaWVudFRyYW5zZm9ybT0ibWF0cml4KDEgMCAwIC0xIC0xMTguOTggMTIwLjU0KSIgeDI9IjQ0Ni41NSIgeDE9IjQ3OC45MyI+PHN0b3Agc3RvcC1jb2xvcj0iIzMyMkM2RiIgb2Zmc2V0PSIwIi8+PHN0b3Agc3RvcC1jb2xvcj0iIzMyMkM2RiIgb2Zmc2V0PSIuMjQyNyIvPjxzdG9wIHN0b3AtY29sb3I9IiMzMDJGNzIiIG9mZnNldD0iLjQ1OTkiLz48c3RvcCBzdG9wLWNvbG9yPSIjMkEzQTdFIiBvZmZzZXQ9Ii43MTU1Ii8+PHN0b3Agc3RvcC1jb2xvcj0iIzE1NEE5MyIgb2Zmc2V0PSIuOTg5NiIvPjxzdG9wIHN0b3AtY29sb3I9IiMxMzRCOTQiIG9mZnNldD0iMSIvPjwvbGluZWFyR3JhZGllbnQ+PHBvbHlnb24gcG9pbnRzPSIyODguNCAxNTMuMiAzMTAuNyAzMDYuNCAzNTguMSAzMDYuNCAzNTguMSAwIDMxMi45IDAiIGZpbGw9InVybCgjU1ZHSURfM18pIiBjbGFzcz0ic3QyIi8+CiAgICA8bGluZWFyR3JhZGllbnQgaWQ9IlNWR0lEXzRfIiB5Mj0iLTMyLjY2MyIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiIHkxPSItMzIuNjYzIiBncmFkaWVudFRyYW5zZm9ybT0ibWF0cml4KDEgMCAwIC0xIC0xMTguOTggMTIwLjU0KSIgeDI9IjM3Mi44OCIgeDE9IjI5NC4wOCI+PHN0b3Agc3RvcC1jb2xvcj0iIzZGMzc4RCIgb2Zmc2V0PSIwIi8+PHN0b3Agc3RvcC1jb2xvcj0iIzNBNDI5MSIgb2Zmc2V0PSIxIi8+PC9saW5lYXJHcmFkaWVudD48cG9seWdvbiBwb2ludHM9IjE3NS4xIDE1My4yIDIwNi4xIDMwNi40IDI1My45IDE1My4yIDIwOS40IDAgMjA5LjQgMCIgZmlsbD0idXJsKCNTVkdJRF80XykiIGNsYXNzPSJzdDMiLz4KICAgIDxsaW5lYXJHcmFkaWVudCBpZD0iU1ZHSURfNV8iIHkyPSItMzIuNjYzIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeTE9Ii0zMi42NjMiIGdyYWRpZW50VHJhbnNmb3JtPSJtYXRyaXgoMSAwIDAgLTEgLTExOC45OCAxMjAuNTQpIiB4Mj0iMzI1LjA4IiB4MT0iNDMxLjg4Ij48c3RvcCBzdG9wLWNvbG9yPSIjMjMzRDdEIiBvZmZzZXQ9IjAiLz48c3RvcCBzdG9wLWNvbG9yPSIjMjkzRDdEIiBvZmZzZXQ9Ii4yNDk1Ii8+PHN0b3Agc3RvcC1jb2xvcj0iIzNBM0M4MCIgb2Zmc2V0PSIuNTQ0NiIvPjxzdG9wIHN0b3AtY29sb3I9IiM1MTNCODQiIG9mZnNldD0iLjg2MTYiLz48c3RvcCBzdG9wLWNvbG9yPSIjNUQzQTg2IiBvZmZzZXQ9IjEiLz48L2xpbmVhckdyYWRpZW50Pjxwb2x5Z29uIHBvaW50cz0iMjUzLjkgMTUzLjIgMjA2LjEgMzA2LjQgMzEwLjcgMzA2LjQgMjg4LjQgMTUzLjIgMzEyLjkgMCAyMDkuNCAwIiBmaWxsPSJ1cmwoI1NWR0lEXzVfKSIgY2xhc3M9InN0NCIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LjEgMCA1NS43IDAgNTUuNyA5NC44IDg5LjkgMTUzLjIgNTUuNyAyMTEuNiA1NS43IDMwNi40IDExNyAzMDYuNCA5NS4yIDE1My4yIiBmaWxsPSIjYWYyMDI0IiBjbGFzcz0ic3Q1Ii8+CiAgICA8bGluZWFyR3JhZGllbnQgaWQ9IlNWR0lEXzZfIiB5Mj0iNDMuOTM3IiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeTE9IjQzLjkzNyIgZ3JhZGllbnRUcmFuc2Zvcm09Im1hdHJpeCgxIDAgMCAtMSAtMTE4Ljk4IDEyMC41NCkiIHgyPSIyMzIuNjciIHgxPSIzMjkuMTEiPjxzdG9wIHN0b3AtY29sb3I9IiM4OTM2ODAiIG9mZnNldD0iMCIvPjxzdG9wIHN0b3AtY29sb3I9IiM4OTM2ODAiIG9mZnNldD0iLjMzNTQiLz48c3RvcCBzdG9wLWNvbG9yPSIjOEQzMTZEIiBvZmZzZXQ9Ii41MDI1Ii8+PHN0b3Agc3RvcC1jb2xvcj0iIzkwMjk0RCIgb2Zmc2V0PSIuODM5OCIvPjxzdG9wIHN0b3AtY29sb3I9IiM5MDI1NDEiIG9mZnNldD0iMSIvPjwvbGluZWFyR3JhZGllbnQ+PHBvbHlnb24gcG9pbnRzPSIxNzUuMSAxNTMuMiAyMDkuNCAwIDExNi4xIDAiIGZpbGw9InVybCgjU1ZHSURfNl8pIiBjbGFzcz0ic3Q2Ii8+PHBvbHlnb24gcG9pbnRzPSI1NS43IDk0LjggNTUuNyAwIDAgMCIgZmlsbD0iIzk0MWIxZSIgY2xhc3M9InN0NyIvPjxwb2x5Z29uIHBvaW50cz0iNTUuNyAyMTEuNiA4OS45IDE1My4yIDU1LjcgOTQuOCIgZmlsbD0iI2IxMjczOSIgY2xhc3M9InN0OCIvPjxwb2x5Z29uIHBvaW50cz0iNTUuNyAyMTEuNiAwIDMwNi40IDU1LjcgMzA2LjQiIGZpbGw9IiM5NDFiMWUiIGNsYXNzPSJzdDciLz48cG9seWdvbiBwb2ludHM9IjU1LjcgOTQuOCAwIDAgMCAzMDYuNCA1NS43IDIxMS42IiBmaWxsPSIjOTUyNDMyIiBjbGFzcz0ic3Q5Ii8+PHBvbHlnb24gcG9pbnRzPSIxMTYuMSAwIDk1LjIgMTUzLjIgMTE3IDMwNi40IDE3NS4xIDE1My4yIiBmaWxsPSIjZDQyMDI3IiBjbGFzcz0ic3QxMCIvPgogICAgPGxpbmVhckdyYWRpZW50IGlkPSJTVkdJRF83XyIgeTI9Ii0xODYuMDYiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIiB5MT0iMTIwLjQ0IiBncmFkaWVudFRyYW5zZm9ybT0ibWF0cml4KDEgMCAwIC0xIC0xMTguOTggMTIwLjU0KSIgeDI9Ijc0OC45NiIgeDE9Ijc0OC45NiI+PHN0b3Agc3RvcC1jb2xvcj0iIzk0QkU1NSIgb2Zmc2V0PSIwIi8+PHN0b3Agc3RvcC1jb2xvcj0iIzkzQkQ1OCIgb2Zmc2V0PSIuMDQ0MzQwIi8+PHN0b3Agc3RvcC1jb2xvcj0iIzhCQkM2QSIgb2Zmc2V0PSIuMzg5MSIvPjxzdG9wIHN0b3AtY29sb3I9IiM4NkJDNzUiIG9mZnNldD0iLjcxNDkiLz48c3RvcCBzdG9wLWNvbG9yPSIjODRCQzc5IiBvZmZzZXQ9IjEiLz48L2xpbmVhckdyYWRpZW50PjxwYXRoCiAgICAgIGQ9Im02NDEuNiAyNTkuNmMxLjctMjUuNCAxMC01NC42IDE4LjgtODUuNiAxLjQtNSAyLjgtMTAgNC4yLTE1LjEtMS40LTUuNS0yLjgtMTAuOS00LjItMTYuMi04LjgtMzMuMy0xNy02NC43LTE4LjgtOTItMS40LTIxLjIgMS40LTM3IDguOS01MC42aC00NS45Yy03LjUgMTguMy0xMC4zIDI5LjEtOC45IDUwLjMgMS43IDI3LjMgMTAgNTguNyAxOC44IDkyIDEzIDQ5LjMgMjggMTA2LjIgMjMuMiAxNjQuMmgxMi45Yy03LjYtMTIuOC0xMC40LTI3LjMtOS00N3oiCiAgICAgIGNsYXNzPSJzdDExIgogICAgICBmaWxsPSJ1cmwoI1NWR0lEXzdfKSIvPgogICAgPGxpbmVhckdyYWRpZW50IGlkPSJTVkdJRF84XyIgeTI9Ii0xODQuNDUiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIiB5MT0iMTE3LjI5IiBncmFkaWVudFRyYW5zZm9ybT0ibWF0cml4KDEgMCAwIC0xIC0xMTguOTggMTIwLjU0KSIgeDI9IjczMy40OSIgeDE9IjY1My43NiI+PHN0b3Agc3RvcC1jb2xvcj0iIzA4QTI0QiIgb2Zmc2V0PSIwIi8+PHN0b3Agc3RvcC1jb2xvcj0iIzBBQTE0RSIgb2Zmc2V0PSIuMTY3OCIvPjxzdG9wIHN0b3AtY29sb3I9IiMwQjlFNTciIG9mZnNldD0iLjQwNDciLz48c3RvcCBzdG9wLWNvbG9yPSIjMDk5QTY3IiBvZmZzZXQ9Ii42ODI3Ii8+PHN0b3Agc3RvcC1jb2xvcj0iIzA0OTQ3RCIgb2Zmc2V0PSIuOTg5OCIvPjxzdG9wIHN0b3AtY29sb3I9IiMwNDkzN0UiIG9mZnNldD0iMSIvPjwvbGluZWFyR3JhZGllbnQ+PHBhdGggZD0ibTYxNC41IDE0Mi4zYy04LjgtMzMuMy0xNy02NC43LTE4LjgtOTItMS40LTIxLjIgMS40LTMyIDguOS01MC4zaC0zNS40YzUuNyA1My45LTMuOCAxMDYuNy0xMy42IDE2Ni44LTUuNyAzNS0xMS43IDcxLjMtMTMuMiAxMDAuNi0xLjEgMjEuMSAwLjQgMzIuOCAxLjggMzloOTMuNWM0LjgtNTcuOS0xMC4zLTExNC44LTIzLjItMTY0LjF6IiBjbGFzcz0ic3QxMiIgZmlsbD0idXJsKCNTVkdJRF84XykiLz48cGF0aCBjbGFzcz0ic3QxMyIgZmlsbD0iIzFjOWE0OCIgZD0ibTY2NC42IDE1OC45Yy0xLjQgNS4xLTIuOCAxMC4xLTQuMiAxNS4xLTguOCAzMS0xNyA2MC4yLTE4LjggODUuNi0xLjQgMTkuNyAxLjQgMzQuMiA5IDQ2LjloMzNjNC4yLTUxLjgtNy4yLTEwMi4zLTE5LTE0Ny42eiIvPgogICAgPGxpbmVhckdyYWRpZW50IGlkPSJTVkdJRF85XyIgeTI9Ii0xODUuOTYiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIiB5MT0iMTIwLjU0IiBncmFkaWVudFRyYW5zZm9ybT0ibWF0cml4KDEgMCAwIC0xIC0xMTguOTggMTIwLjU0KSIgeDI9IjgxMi44MyIgeDE9IjgxMi44MyI+PHN0b3Agc3RvcC1jb2xvcj0iIzY5QTA2MCIgb2Zmc2V0PSIwIi8+PHN0b3Agc3RvcC1jb2xvcj0iIzYzOUQ1QyIgb2Zmc2V0PSIuMDM5ODk1Ii8+PHN0b3Agc3RvcC1jb2xvcj0iIzRDOTQ0RiIgb2Zmc2V0PSIuMjE5MiIvPjxzdG9wIHN0b3AtY29sb3I9IiMzNzhFNDciIG9mZnNldD0iLjQxODQiLz48c3RvcCBzdG9wLWNvbG9yPSIjMjk4QjQ0IiBvZmZzZXQ9Ii42NTE1Ii8+PHN0b3Agc3RvcC1jb2xvcj0iIzIzOEE0MyIgb2Zmc2V0PSIxIi8+PC9saW5lYXJHcmFkaWVudD48cGF0aCBkPSJtNjgwLjUgMGMxMC43IDU1LjMtMi41IDExMC40LTE1LjkgMTU4LjkgMTEuNyA0NS4zIDIzLjIgOTUuOCAxOC45IDE0Ny42aDM5LjZ2LTMwNi41aC00Mi42eiIgY2xhc3M9InN0MTQiIGZpbGw9InVybCgjU1ZHSURfOV8pIi8+CiAgICA8bGluZWFyR3JhZGllbnQgaWQ9IlNWR0lEXzEwXyIgeTI9Ii0xODUuODYiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIiB5MT0iMTIwLjU0IiBncmFkaWVudFRyYW5zZm9ybT0ibWF0cml4KDEgMCAwIC0xIC0xMTguOTggMTIwLjU0KSIgeDI9IjY1Mi40NSIgeDE9IjY1Mi40NSI+PHN0b3Agc3RvcC1jb2xvcj0iIzA1QjVEQyIgb2Zmc2V0PSIwIi8+PHN0b3Agc3RvcC1jb2xvcj0iIzA0QjBENyIgb2Zmc2V0PSIuMjE5NyIvPjxzdG9wIHN0b3AtY29sb3I9IiMwNUE0QzkiIG9mZnNldD0iLjUzNzEiLz48c3RvcCBzdG9wLWNvbG9yPSIjMDU5MUI0IiBvZmZzZXQ9Ii45MTIyIi8+PHN0b3Agc3RvcC1jb2xvcj0iIzA1OENBRSIgb2Zmc2V0PSIxIi8+PC9saW5lYXJHcmFkaWVudD48cGF0aCBkPSJtNTQyLjMgMjY3LjRjMS41LTI5LjQgNy41LTY1LjYgMTMuMi0xMDAuNiA5LjgtNjAuMSAxOS4zLTExMi44IDEzLjYtMTY2LjhoLTcwLjhjLTEuNCAxMS40LTIuOSAxOS4yLTEuOCA0MS44IDEuNSAzMS42IDcuNSA3MC41IDEzLjIgMTA4LjIgOC40IDU1LjQgMTYuNiAxMDguOCAxNS4xIDE1Ni40aDE5LjJjLTEuMy02LjItMi44LTE3LjktMS43LTM5eiIgY2xhc3M9InN0MTUiIGZpbGw9InVybCgjU1ZHSURfMTBfKSIvPjxwb2x5Z29uIHBvaW50cz0iMzc1LjcgMTUzLjIgMzU4LjEgMCAzNTguMSAzMDYuNCIgZmlsbD0iIzJhMzg4NiIgY2xhc3M9InN0MTYiLz4KICAgIDxsaW5lYXJHcmFkaWVudCBpZD0iU1ZHSURfMTFfIiB5Mj0iNzcuMTM2IiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeTE9Ii00LjMyODEiIGdyYWRpZW50VHJhbnNmb3JtPSJtYXRyaXgoMSAwIDAgLTEgLTExOC45OCAxMjAuNTQpIiB4Mj0iNzk2LjcxIiB4MT0iNzUxLjA1Ij48c3RvcCBzdG9wLWNvbG9yPSIjNjJCMTZFIiBvZmZzZXQ9IjAiLz48c3RvcCBzdG9wLWNvbG9yPSIjODdCOTU3IiBvZmZzZXQ9IjEiLz48L2xpbmVhckdyYWRpZW50PjxwYXRoIGQ9Im02NDEuNiA1MC42YzEuNyAyNy4zIDEwIDU4LjcgMTguOCA5MiAxLjQgNS4zIDIuOCAxMC43IDQuMiAxNi4yIDEzLjUtNDguNCAyNi42LTEwMy41IDE1LjktMTU4LjhoLTMwYy03LjUgMTMuNi0xMC4zIDI5LjQtOC45IDUwLjZ6IiBjbGFzcz0ic3QxNyIgZmlsbD0idXJsKCNTVkdJRF8xMV8pIi8+CiAgICA8bGluZWFyR3JhZGllbnQgaWQ9IlNWR0lEXzEyXyIgeTI9Ii0xODkuMjgiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIiB5MT0iMTEzLjcxIiBncmFkaWVudFRyYW5zZm9ybT0ibWF0cml4KDEgMCAwIC0xIC0xMTguOTggMTIwLjU0KSIgeDI9IjYzMS41OSIgeDE9IjU1MC40Ij48c3RvcCBzdG9wLWNvbG9yPSIjMDY5QUQ0IiBvZmZzZXQ9IjAiLz48c3RvcCBzdG9wLWNvbG9yPSIjMzBBMENFIiBvZmZzZXQ9Ii4zNTI1Ii8+PHN0b3Agc3RvcC1jb2xvcj0iIzVCQjBDMCIgb2Zmc2V0PSIxIi8+PC9saW5lYXJHcmFkaWVudD48cGF0aCBkPSJtNTA5LjggMTUwYy01LjctMzcuNy0xMS43LTc2LjYtMTMuMi0xMDguMi0xLjEtMjIuNyAwLjQtMzAuNCAxLjgtNDEuOGgtNDEuNWMxLjUgNDAuMS0xLjUgODUuMy03IDE2MC44LTMuMSA0My41LTggMTEwLjUtNyAxNDUuN2g4Mi4xYzEuNC00Ny43LTYuOC0xMDEuMS0xNS4yLTE1Ni41eiIgY2xhc3M9InN0MTgiIGZpbGw9InVybCgjU1ZHSURfMTJfKSIvPgogICAgPGxpbmVhckdyYWRpZW50IGlkPSJTVkdJRF8xM18iIHkyPSItMTg1Ljg2IiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeTE9IjEyMC41NCIgZ3JhZGllbnRUcmFuc2Zvcm09Im1hdHJpeCgxIDAgMCAtMSAtMTE4Ljk4IDEyMC41NCkiIHgyPSI1MDUuMzMiIHgxPSI1MDUuMzMiPjxzdG9wIHN0b3AtY29sb3I9IiMxRTQ1OEUiIG9mZnNldD0iMCIvPjxzdG9wIHN0b3AtY29sb3I9IiMxRjRGOTYiIG9mZnNldD0iLjI0MTEiLz48c3RvcCBzdG9wLWNvbG9yPSIjMkI2QUFCIiBvZmZzZXQ9Ii43MjkyIi8+PHN0b3Agc3RvcC1jb2xvcj0iIzMzN0JCOSIgb2Zmc2V0PSIxIi8+PC9saW5lYXJHcmFkaWVudD48cG9seWdvbiBwb2ludHM9IjM1OC4xIDMwNi40IDQxNC42IDMwNi40IDQxNC42IDAgMzU4LjEgMCAzNzUuNyAxNTMuMiIgZmlsbD0idXJsKCNTVkdJRF8xM18pIiBjbGFzcz0ic3QxOSIvPgogICAgPGxpbmVhckdyYWRpZW50IGlkPSJTVkdJRF8xNF8iIHkyPSIxMjAuNTQiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIiB5MT0iLTE4NS44NiIgZ3JhZGllbnRUcmFuc2Zvcm09Im1hdHJpeCgxIDAgMCAtMSAtMTE4Ljk4IDEyMC41NCkiIHgyPSI1NTQuOTIiIHgxPSI1NTQuOTIiPjxzdG9wIHN0b3AtY29sb3I9IiMzRjlBQzkiIG9mZnNldD0iMCIvPjxzdG9wIHN0b3AtY29sb3I9IiMyMDYyQTIiIG9mZnNldD0iMSIvPjwvbGluZWFyR3JhZGllbnQ+PHBhdGggZD0ibTQ0OS45IDE2MC44YzUuNS03NS41IDguNS0xMjAuNiA3LTE2MC44aC00Mi4ybC0wLjEgMzA2LjRoMjguM2MtMS0zNS4xIDMuOC0xMDIuMSA3LTE0NS42eiIgY2xhc3M9InN0MjAiIGZpbGw9InVybCgjU1ZHSURfMTRfKSIvPjwvZz4KPC9zdmc+Cg==);
-}
-
-body:after {
- position: absolute;
- right: 25px;
- top: 36px;
- width: 135px;
- height: 48px;
- content: '';
- background-repeat: no-repeat;
- background-size: cover;
- background-image: url(/static/img/bosch-logo.svg);
-}
-
-.swagger-ui {
- font-family: "Bosch Sans", sans-serif;
-}
-
-/*custom docs*/
-.docs {
- position: relative;
- font-size: 14px;
-}
-
-.docs > summary {
- position: absolute;
- right: 0;
- top: -25px;
- cursor: pointer;
-}
-
-.docs-open:hover {
- text-decoration: underline;
-}
-
-/*Remove topbar*/
-.swagger-ui .topbar {
- display: none
-}
-
-/*Remove models view*/
-.swagger-ui .models {
- display: none;
-}
-
-/*Remove application/json select*/
-.swagger-ui .opblock .opblock-section-header > label, .swagger-ui .response-controls {
- display: none;
-}
-
-/*Remove border radius*/
-.swagger-ui .opblock, .swagger-ui .opblock .opblock-summary-method, .swagger-ui select {
- border-radius: 0;
- box-shadow: none;
-}
-
-/*remove links in response*/
-.swagger-ui .response-col_links {
- display: none;
-}
-
-/*remove version*/
-.swagger-ui .info .title span {
- display: none;
-}
-
-/*separator before methods*/
-.swagger-ui .scheme-container {
- box-shadow: none;
- border-bottom: 1px solid var(--light-grey);
-}
-
-/*tag separator*/
-.swagger-ui .opblock-tag {
- border-bottom: 1px solid var(--light-grey);
-}
-
-/*parameters/responses bar*/
-.swagger-ui .opblock .opblock-section-header {
- box-shadow: none;
- background: #fff;
-}
-
-/*select*/
-.swagger-ui select {
- background-color: var(--light-grey-w75);
- border: none;
- height: 36px;
-}
-
-/*button*/
-.swagger-ui .btn {
- border-radius: 0;
- box-shadow: none;
-}
-
-.swagger-ui .btn:hover {
- box-shadow: none;
-}
-
-/*authorize button */
-.swagger-ui .btn.authorize {
- color: var(--light-green);
- border-color: var(--light-green);
-}
-
-.swagger-ui .btn.authorize svg {
- fill: var(--light-green);
-}
-
-/*auth inputs*/
-.swagger-ui .auth-container input[type="password"], .swagger-ui .auth-container input[type="text"] {
- border-radius: 0;
- box-shadow: none;
- border-color: var(--light-grey);
-}
-
-.swagger-ui .dialog-ux .modal-ux {
- border-radius: 0;
-}
-
-/*cancel button*/
-.swagger-ui .btn.cancel {
- color: var(--red);
- border-color: var(--red);
-}
-
-/*download button*/
-.swagger-ui .download-contents {
- border-radius: 0;
- height: 28px;
- width: 80px;
-}
-
-/*model*/
-.swagger-ui .model-box {
- border-radius: 0;
-}
-
-/*execute button*/
-.swagger-ui .btn.execute {
- background-color: var(--dark-blue);
- border-color: var(--dark-blue);
- height: 30px;
- line-height: 0.7;
-}
-
-.swagger-ui .btn-group .btn:last-child {
- border-radius: 0;
- height: 30px;
- border-color: var(--dark-blue);
-}
-
-.swagger-ui .btn-group .btn:first-child {
- border-radius: 0;
-}
-
-.swagger-ui .btn-group {
- padding: 0 20px;
-}
-
-/*parameter input*/
-.swagger-ui .parameters-col_description input[type="text"] {
- border-radius: 0;
-}
-
-/*required label*/
-.swagger-ui .parameter__name.required > span {
- color: var(--red) !important;
-}
-
-.swagger-ui .parameter__name.required::after {
- color: var(--red);
-}
-/*Remove colored parameters bar*/
-.swagger-ui .opblock.opblock-get .tab-header .tab-item.active h4 span::after, .swagger-ui .opblock.opblock-post .tab-header .tab-item.active h4 span::after, .swagger-ui .opblock.opblock-put .tab-header .tab-item.active h4 span::after, .swagger-ui .opblock.opblock-delete .tab-header .tab-item.active h4 span::after {
- background: none;
-}
-
-/*code*/
-.swagger-ui .opblock-body pre.microlight {
- border-radius: 0;
-}
-
-.swagger-ui .highlight-code > .microlight {
- min-height: 0;
-}
-
-/*request body*/
-.swagger-ui textarea {
- border-radius: 0;
-}
-
-/*parameters smaller padding*/
-.swagger-ui .execute-wrapper {
- padding-top: 0;
- padding-bottom: 0;
-}
-
-.swagger-ui .btn.execute {
- margin-bottom: 20px;
-}
-
-.swagger-ui .opblock-description-wrapper {
- margin-top: 20px;
-}
-
-.swagger-ui .opblock-description-wrapper {
- margin-top: 5px;
-}
-
-.opblock-section .opblock-section-request-body > div > div {
- padding-top: 18px;
-}
-
-/*response element positions*/
-.swagger-ui .model-example {
- position: relative;
- margin-top: 0;
-}
-
-.swagger-ui .tab {
- position: absolute;
- top: -35px;
- right: 0;
-}
-
-.swagger-ui table tbody tr td {
- padding: 0;
-}
-
-.swagger-ui .renderedMarkdown p {
- margin: 8px auto;
-}
-
-/*Method colors*/
-.swagger-ui .opblock.opblock-get .opblock-summary-method {
- background: var(--dark-blue);
-}
-
-.swagger-ui .opblock.opblock-get .opblock-summary {
- border-color: var(--dark-blue);
-}
-
-.swagger-ui .opblock.opblock-get {
- background: var(--dark-blue-w75);
- border-color: var(--dark-blue);
-}
-
-.swagger-ui .opblock.opblock-post .opblock-summary-method {
- background: var(--dark-green);
-}
-
-.swagger-ui .opblock.opblock-post .opblock-summary {
- border-color: var(--dark-green);
-}
-
-.swagger-ui .opblock.opblock-post {
- background: var(--dark-green-w75);
- border-color: var(--dark-green);
-}
-
-.swagger-ui .opblock.opblock-put .opblock-summary-method {
- background: var(--turquoise);
-}
-
-.swagger-ui .opblock.opblock-put .opblock-summary {
- border-color: var(--turquoise);
-}
-
-.swagger-ui .opblock.opblock-put {
- background: var(--turquoise-w75);
- border-color: var(--turquoise);
-}
-
-.swagger-ui .opblock.opblock-delete .opblock-summary-method {
- background: var(--fuchsia);
-}
-
-.swagger-ui .opblock.opblock-delete .opblock-summary {
- border-color: var(--fuchsia);
-}
-
-.swagger-ui .opblock.opblock-delete {
- background: var(--fuchsia-w75);
- border-color: var(--fuchsia);
-}
\ No newline at end of file