Commit dfa7c7e7 authored by Rafael's avatar Rafael

Adiciona cliente web e simulador.

parent e6096014
/node_modules/**
/dist/**
/public/**
*.min.js
server.js
setEnvironment.js
webpack.config.js
postcss.config.ts
\ No newline at end of file
{
"parser": "@typescript-eslint/parser",
"plugins": ["@typescript-eslint"],
"parserOptions": {
"project": "./tsconfig.json",
"sourceType": "module"
},
"rules": {
"@typescript-eslint/no-explicit-any": 0,
"@typescript-eslint/no-var-requires": 0,
"@typescript-eslint/no-unsafe-member-access": 0,
"@typescript-eslint/explicit-module-boundary-types": 0,
"@typescript-eslint/unbound-method": 0,
"@typescript-eslint/no-unsafe-assignment": 0,
"@typescript-eslint/restrict-template-expressions": 0,
"@typescript-eslint/no-non-null-assertion": 0,
"@typescript-eslint/no-unused-vars": 0,
"@typescript-eslint/no-empty-interface": 0,
"@typescript-eslint/no-unsafe-call": 0,
"@typescript-eslint/no-unsafe-return": 0,
"@typescript-eslint/no-empty-function": 0
},
"extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended", "plugin:@typescript-eslint/recommended-requiring-type-checking"]
}
**/node_modules
**/lib
*.tar.gz
*.zip
*.log
*.tsbuildinfo
.prettierrc
example\.xml
/dist/**
/test/**
/.vscode/
\ No newline at end of file
/src
/public
/typings
/.vscode
.prettierrc
.babelrc
*.png
*.json
*.md
*.log
*.tsbuildinfo
init.author.name = admin
init.author.email = suporte@evologica.com.br
# an email is required to publish npm packages
email=suporte@evologica.com.br
always-auth=true
# _auth is a base64 encode of 'username:password'
# if you need to generate a new one: echo -n 'username:password' | openssl base64
_auth=YWRtaW46amo1OFBkMDI=
\ No newline at end of file
--registry "https://registry.npmjs.org/"
"@curio:registry" "https://nexus.dev.evologica.com.br/repository/npm"
"@dynamo:registry" "https://nexus.dev.evologica.com.br/repository/npm"
\ No newline at end of file
{
"presets": [
[
"@babel/preset-env",
{
"modules": false,
"corejs": {
"version": "3",
"proposals": true
},
"useBuiltIns": "usage",
"targets": {
"ie": "11",
"browsers": [
"edge >= 16",
"safari >= 9",
"firefox >= 57",
"ie >= 11",
"ios >= 9",
"chrome >= 49"
]
}
}
],
"@babel/preset-react"
],
"plugins": [
[
"babel-plugin-import",
{
"libraryName": "@material-ui/core",
"libraryDirectory": "esm",
"camel2DashComponentName": false
},
"core"
],
[
"babel-plugin-import",
{
"libraryName": "@material-ui/lab",
"libraryDirectory": "esm",
"camel2DashComponentName": false
},
"lab"
],
[
"babel-plugin-import",
{
"libraryName": "@material-ui/icons",
"libraryDirectory": "esm",
"camel2DashComponentName": false
},
"icons"
],
"@babel/plugin-proposal-optional-chaining",
"@babel/plugin-proposal-nullish-coalescing-operator",
"@babel/plugin-proposal-object-rest-spread",
"@babel/plugin-proposal-class-properties",
"@babel/plugin-transform-async-to-generator",
"@babel/plugin-syntax-dynamic-import",
"@babel/plugin-transform-arrow-functions"
]
}
{
"service": {
"url": "https://srvd1.dev.evologica.com.br/cxClient/cxIsapiClient.dll/gatewayJSON?version=4",
"server": "192.168.0.34",
"system": 19,
"port": 9801,
"module": 1,
"version": 3
},
"accessToken": "ab4dfc4ab84517f900193f8a2530680c73ad3539f75e1f5661bee7065cfcdd32",
"resources": {
"get": "https://mdk.dev.evologica.com.br/cxClient/cxIsapiClient.dll/getpr",
"put": "https://mdk.dev.evologica.com.br/cxClient/cxIsapiClient.dll/putpr"
},
"logs": true
}
{
"service": {
"url": "https://mdk.evologica.com.br/cxClient/cxIsapiClient.dll/gatewayJSONBalanced?version=4",
"server": "mdk.evologica.com.br",
"system": 94,
"port": 7902
},
"accessToken": "ed296c1d9dc3d3eb41a29077bd715278cc985849e0df51da0c2653996055d19f",
"resources": {
"get": "https://mdk.dev.evologica.com.br/cxClient/cxIsapiClient.dll/getpr",
"put": "https://mdk.dev.evologica.com.br/cxClient/cxIsapiClient.dll/putpr"
},
"logs": true
}
{
"service": {
"url": "https://mdk.dev.evologica.com.br/cxClient/cxIsapiClient.dll/gatewayJSON?version=4",
"server": "srvp4",
"system": 94,
"port": 7901
},
"accessToken": "ab4dfc4ab84517f900193f8a2530680c73ad3539f75e1f5661bee7065cfcdd32",
"resources": {
"get": "https://mdk.dev.evologica.com.br/cxClient/cxIsapiClient.dll/getpr",
"put": "https://mdk.dev.evologica.com.br/cxClient/cxIsapiClient.dll/putpr"
},
"logs": true
}
{
"name": "agiliza",
"version": "0.0.1",
"license": "ISC",
"repository": "https://gitlab.dev.evologica.com.br/evologica/agiliza",
"author": "Rafael Igor <rafaelrios@evologica.com.br>",
"eslintConfig": {
"env": {
"browser": true,
"node": true
}
},
"scripts": {
"env:dev": "node ./setEnvironment.js dev",
"env:prod": "node ./setEnvironment.js prod",
"env:staging": "node ./setEnvironment.js staging",
"start": "yarn env:dev && webpack-dev-server",
"start:staging": "yarn env:staging && webpack-dev-server",
"start:prod": "yarn env:prod && webpack-dev-server",
"serve": "ts-node ./server",
"build": "yarn clean && yarn test && yarn env:prod && webpack --env.production --config webpack.config.js --progress -p",
"build:staging": "yarn clean && yarn test && yarn env:staging && webpack --env.production --config webpack.config.js --progress -p",
"clean": "rimraf ./dist",
"test": "tsc --noEmit"
},
"devDependencies": {
"@babel/compat-data": "^7.8.0",
"@babel/core": "7.14.3",
"@babel/plugin-proposal-class-properties": "7.13.0",
"@babel/plugin-proposal-nullish-coalescing-operator": "7.14.2",
"@babel/plugin-proposal-object-rest-spread": "7.14.2",
"@babel/plugin-proposal-optional-chaining": "7.14.2",
"@babel/plugin-syntax-dynamic-import": "7.8.3",
"@babel/plugin-transform-async-to-generator": "7.13.0",
"@babel/preset-env": "^7.8.0",
"@babel/preset-react": "7.13.13",
"@types/classnames": "^2.2.10",
"@types/compression-webpack-plugin": "6.0.5",
"@types/copy-webpack-plugin": "8.0.0",
"@types/express": "4.17.11",
"@types/fork-ts-checker-webpack-plugin": "0.4.5",
"@types/html-webpack-plugin": "3.2.5",
"@types/mini-css-extract-plugin": "1.4.3",
"@types/node": "15.6.1",
"@types/react": "17.0.7",
"@types/react-dom": "17.0.5",
"@types/react-redux": "7.1.16",
"@types/react-router": "5.1.14",
"@types/react-router-dom": "5.1.7",
"@types/redux-logger": "^3.0.7",
"@types/webpack": "5.28.0",
"@types/webpack-bundle-analyzer": "4.4.0",
"@types/webpack-dev-server": "3.11.4",
"@typescript-eslint/eslint-plugin": "^4.25.0",
"@typescript-eslint/parser": "^4.25.0",
"autoprefixer": "^10.2.5",
"babel-eslint": "^10.1.0",
"babel-loader": "8.2.2",
"clean-webpack-plugin": "4.0.0-alpha.0",
"copy-webpack-plugin": "9.0.0",
"css-loader": "5.2.6",
"css-minimizer-webpack-plugin": "^3.0.0",
"ejs-loader": "0.5.0",
"eslint": "^7.27.0",
"eslint-plugin-react-hooks": "^4.2.0",
"express": "4.17.1",
"file-loader": "6.2.0",
"fork-ts-checker-webpack-plugin": "6.2.10",
"html-webpack-plugin": "5.3.1",
"mini-css-extract-plugin": "1.6.0",
"postcss": "^8.3.0",
"postcss-cli": "^8.3.1",
"postcss-loader": "^5.3.0",
"postcss-url": "^10.1.3",
"process": "^0.11.10",
"style-loader": "2.0.0",
"ts-loader": "9.2.2",
"ts-node": "10.0.0",
"typescript": "^4.0.0"
},
"dependencies": {
"@curio/client": "1.3.3",
"@curio/components": "^0.1.3",
"@curio/ui": "^0.1.0",
"@date-io/date-fns": "^1.0.0",
"@dynamo/components": "0.70.1",
"@dynamo/curio": "0.70.1",
"@dynamo/material-ui": "0.70.1",
"@material-ui/core": "4.11.4",
"@material-ui/icons": "^4.11.2",
"@material-ui/lab": "4.0.0-alpha.58",
"@material-ui/pickers": "^3.3.10",
"@reduxjs/toolkit": "^1.2.5",
"@types/react-swipeable-views": "^0.13.1",
"@types/react-swipeable-views-utils": "^0.13.3",
"@xstate/react": "^1.3.3",
"babel-plugin-import": "^1.13.0",
"bowser": "^2.11.0",
"classnames": "^2.2.6",
"core-js": "3.12.1",
"date-fns": "^2.11.0",
"deepmerge": "^4.2.2",
"normalizr": "^3.6.1",
"p-min-delay": "^4.0.0",
"react": "^16.0.0",
"react-dom": "^16.0.0",
"react-loading-skeleton": "^2.0.1",
"react-redux": "^7.2.0",
"react-router": "5.2.0",
"react-router-dom": "5.2.0",
"redux": "^4.0.5",
"redux-logger": "^3.0.6",
"redux-observable": "^1.2.0",
"reselect": "^4.0.0",
"rxjs": "^6.5.4",
"webpack": "5.37.1",
"webpack-cli": "^3.0.0",
"webpack-dev-server": "3.11.2",
"xstate": "^4.19.1"
}
}
module.exports = ({ env }) => ({
plugins: [
// [
// 'postcss-url',
// {
// filter: '**/fonts/**',
// url: (asset) => asset.url
// // env === 'production' ? `..${asset.url}` : `..${asset.url}`
// }
// ],
require('autoprefixer'), // aplica prefixadores de acordo com a lista de browsers a serem suportados
],
})
{
"service": {
"url": "https://srvd1.dev.evologica.com.br/cxClient/cxIsapiClient.dll/gatewayJSON?version=4",
"server": "192.168.0.34",
"system": 19,
"port": 9801,
"module": 1,
"version": 3
},
"accessToken": "ab4dfc4ab84517f900193f8a2530680c73ad3539f75e1f5661bee7065cfcdd32",
"resources": {
"get": "https://mdk.dev.evologica.com.br/cxClient/cxIsapiClient.dll/getpr",
"put": "https://mdk.dev.evologica.com.br/cxClient/cxIsapiClient.dll/putpr"
},
"logs": true
}
\ No newline at end of file
Copyright 2014 The Heebo Project Authors (https://github.com/OdedEzer/heebo)
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
http://scripts.sil.org/OFL
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.
Heebo Variable Font
===================
This download contains Heebo as both a variable font and static fonts.
Heebo is a variable font with this axis:
wght
This means all the styles are contained in a single file:
Heebo-VariableFont_wght.ttf
If your app fully supports variable fonts, you can now pick intermediate styles
that aren’t available as static fonts. Not all apps support variable fonts, and
in those cases you can use the static font files for Heebo:
static/Heebo-Thin.ttf
static/Heebo-ExtraLight.ttf
static/Heebo-Light.ttf
static/Heebo-Regular.ttf
static/Heebo-Medium.ttf
static/Heebo-SemiBold.ttf
static/Heebo-Bold.ttf
static/Heebo-ExtraBold.ttf
static/Heebo-Black.ttf
Get started
-----------
1. Install the font files you want to use
2. Use your app's font picker to view the font family and all the
available styles
Learn more about variable fonts
-------------------------------
https://developers.google.com/web/fundamentals/design-and-ux/typography/variable-fonts
https://variablefonts.typenetwork.com
https://medium.com/variable-fonts
In desktop apps
https://theblog.adobe.com/can-variable-fonts-illustrator-cc
https://helpx.adobe.com/nz/photoshop/using/fonts.html#variable_fonts
Online
https://developers.google.com/fonts/docs/getting_started
https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Fonts/Variable_Fonts_Guide
https://developer.microsoft.com/en-us/microsoft-edge/testdrive/demos/variable-fonts
Installing fonts
MacOS: https://support.apple.com/en-us/HT201749
Linux: https://www.google.com/search?q=how+to+install+a+font+on+gnu%2Blinux
Windows: https://support.microsoft.com/en-us/help/314960/how-to-install-or-remove-a-font-in-windows
Android Apps
https://developers.google.com/fonts/docs/android
https://developer.android.com/guide/topics/ui/look-and-feel/downloadable-fonts
License
-------
Please read the full license text (OFL.txt) to understand the permissions,
restrictions and requirements for usage, redistribution, and modification.
You can use them freely in your products & projects - print or digital,
commercial or otherwise. However, you can't sell the fonts on their own.
This isn't legal advice, please consider consulting a lawyer and see the full
license for all details.
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Copyright 2015 The Rubik Project Authors (https://github.com/googlefonts/rubik),
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
http://scripts.sil.org/OFL
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.
Rubik Variable Font
===================
This download contains Rubik as both variable fonts and static fonts.
Rubik is a variable font with this axis:
wght
This means all the styles are contained in these files:
Rubik/Rubik-VariableFont_wght.ttf
Rubik/Rubik-Italic-VariableFont_wght.ttf
If your app fully supports variable fonts, you can now pick intermediate styles
that aren’t available as static fonts. Not all apps support variable fonts, and
in those cases you can use the static font files for Rubik:
Rubik/static/Rubik-Light.ttf
Rubik/static/Rubik-Regular.ttf
Rubik/static/Rubik-Medium.ttf
Rubik/static/Rubik-SemiBold.ttf
Rubik/static/Rubik-Bold.ttf
Rubik/static/Rubik-ExtraBold.ttf
Rubik/static/Rubik-Black.ttf
Rubik/static/Rubik-LightItalic.ttf
Rubik/static/Rubik-Italic.ttf
Rubik/static/Rubik-MediumItalic.ttf
Rubik/static/Rubik-SemiBoldItalic.ttf
Rubik/static/Rubik-BoldItalic.ttf
Rubik/static/Rubik-ExtraBoldItalic.ttf
Rubik/static/Rubik-BlackItalic.ttf
Get started
-----------
1. Install the font files you want to use
2. Use your app's font picker to view the font family and all the
available styles
Learn more about variable fonts
-------------------------------
https://developers.google.com/web/fundamentals/design-and-ux/typography/variable-fonts
https://variablefonts.typenetwork.com
https://medium.com/variable-fonts
In desktop apps
https://theblog.adobe.com/can-variable-fonts-illustrator-cc
https://helpx.adobe.com/nz/photoshop/using/fonts.html#variable_fonts
Online
https://developers.google.com/fonts/docs/getting_started
https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Fonts/Variable_Fonts_Guide
https://developer.microsoft.com/en-us/microsoft-edge/testdrive/demos/variable-fonts
Installing fonts
MacOS: https://support.apple.com/en-us/HT201749
Linux: https://www.google.com/search?q=how+to+install+a+font+on+gnu%2Blinux
Windows: https://support.microsoft.com/en-us/help/314960/how-to-install-or-remove-a-font-in-windows
Android Apps
https://developers.google.com/fonts/docs/android
https://developer.android.com/guide/topics/ui/look-and-feel/downloadable-fonts
License
-------
Please read the full license text (OFL.txt) to understand the permissions,
restrictions and requirements for usage, redistribution, and modification.
You can use them freely in your products & projects - print or digital,
commercial or otherwise. However, you can't sell the fonts on their own.
This isn't legal advice, please consider consulting a lawyer and see the full
license for all details.
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generator: Adobe Illustrator 22.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="svg2" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 594.3 140.8" style="enable-background:new 0 0 594.3 140.8;" xml:space="preserve">
<style type="text/css">
.st0{clip-path:url(#SVGID_2_);}
.st1{fill:#00998B;}
.st2{fill:#193A60;}
.st3{fill:#59585C;}
.st4{display:none;}
.st5{display:inline;}
.st6{clip-path:url(#SVGID_4_);}
.st7{fill:#153A61;}
.st8{fill:#133B61;}
.st9{fill:#113C61;}
.st10{fill:#0E3D62;}
.st11{fill:#0F3D63;}
.st12{fill:#0C3E63;}
.st13{fill:#063F64;}
.st14{fill:#083F64;}
.st15{fill:#044065;}
.st16{fill:#004165;}
.st17{fill:#004265;}
.st18{fill:#004266;}
.st19{fill:#004366;}
.st20{fill:#004467;}
.st21{fill:#004568;}
.st22{fill:#004668;}
.st23{fill:#004667;}
.st24{fill:#004768;}
.st25{fill:#004769;}
.st26{fill:#004869;}
.st27{fill:#004969;}
.st28{fill:#004A6A;}
.st29{fill:#004B6A;}
.st30{fill:#004D6B;}
.st31{fill:#004C6B;}
.st32{fill:#004E6B;}
.st33{fill:#00506C;}
.st34{fill:#004F6C;}
.st35{fill:#00516D;}
.st36{fill:#00526D;}
.st37{fill:#00526E;}
.st38{fill:#00536E;}
.st39{fill:#00546E;}
.st40{fill:#00556F;}
.st41{fill:#00566F;}
.st42{fill:#00576F;}
.st43{fill:#005870;}
.st44{fill:#005970;}
.st45{fill:#005A70;}
.st46{fill:#005A71;}
.st47{fill:#005B71;}
.st48{fill:#005C71;}
.st49{fill:#005C72;}
.st50{fill:#005D72;}
.st51{fill:#005E72;}
.st52{fill:#005F72;}
.st53{fill:#005F73;}
.st54{fill:#006073;}
.st55{fill:#006172;}
.st56{fill:#006273;}
.st57{fill:#006374;}
.st58{fill:#006474;}
.st59{fill:#006575;}
.st60{fill:#006675;}
.st61{fill:#006876;}
.st62{fill:#006976;}
.st63{fill:#006A76;}
.st64{fill:#006A77;}
.st65{fill:#006B77;}
.st66{fill:#006C77;}
.st67{fill:#006D77;}
.st68{fill:#006D78;}
.st69{fill:#006E78;}
.st70{fill:#006F78;}
.st71{fill:#006F79;}
.st72{fill:#007079;}
.st73{fill:#007179;}
.st74{fill:#007279;}
.st75{fill:#00727A;}
.st76{fill:#00737A;}
.st77{fill:#00747A;}
.st78{fill:#00757B;}
.st79{fill:#00767B;}
.st80{fill:#00777A;}
.st81{fill:#00777C;}
.st82{fill:#00787B;}
.st83{fill:#00797B;}
.st84{fill:#007A7C;}
.st85{fill:#007C7D;}
.st86{fill:#007D7C;}
.st87{fill:#007D7D;}
.st88{fill:#007E7E;}
.st89{fill:#007F7E;}
.st90{fill:#00807E;}
.st91{fill:#00807F;}
.st92{fill:#00817F;}
.st93{fill:#00827F;}
.st94{fill:#008280;}
.st95{fill:#008380;}
.st96{fill:#008480;}
.st97{fill:#008581;}
.st98{fill:#008681;}
.st99{fill:#008781;}
.st100{fill:#008882;}
.st101{fill:#008982;}
.st102{fill:#008A81;}
.st103{fill:#008983;}
.st104{fill:#008A82;}
.st105{fill:#008B82;}
.st106{fill:#008B84;}
.st107{fill:#008C83;}
.st108{fill:#008D83;}
.st109{fill:#008E83;}
.st110{fill:#008E84;}
.st111{fill:#008F84;}
.st112{fill:#009084;}
.st113{fill:#009185;}
.st114{fill:#009284;}
.st115{fill:#009385;}
.st116{fill:#009486;}
.st117{fill:#009586;}
.st118{fill:#009686;}
.st119{fill:#009687;}
.st120{fill:#009887;}
.st121{fill:#009988;}
.st122{fill:#009A88;}
.st123{fill:#009B88;}
.st124{fill:#009C88;}
</style>
<g id="g10" transform="matrix(1.3333333,0,0,-1.3333333,0,595.28)">
<g id="g12">
<g>
<g>
<g>
<defs>
<rect id="SVGID_1_" x="-717.9" y="-67.4" width="1881.5" height="1058.3"/>
</defs>
<clipPath id="SVGID_2_">
<use xlink:href="#SVGID_1_" style="overflow:visible;"/>
</clipPath>
<g id="g14" class="st0">
<g id="g20" transform="translate(238.412,93.8064)">
<path id="path22" class="st1" d="M-174,238.5h1.8v2.2l1.9,0.7v-2.9h2.4v-1.4h-2.4v-6.5c0-0.6,0.1-1,0.3-1.1 c0.2-0.2,0.5-0.3,1.1-0.3c0.1,0,0.3,0,0.4,0c0.2,0,0.3,0.1,0.5,0.1v-1.5c-0.3-0.1-0.6-0.1-0.9-0.2c-0.3,0-0.5-0.1-0.7-0.1 c-1,0-1.7,0.2-2.1,0.5c-0.3,0.5-0.5,1-0.5,1.9v7.2h-1.8V238.5z"/>
</g>
<g id="g24" transform="translate(253.9043,89.5309)">
<path id="path26" class="st1" d="M-174,238.5h5.4v0.2c0,0.9-0.2,1.6-0.7,2.1c-0.5,0.6-1.1,0.9-1.9,0.9s-1.5-0.3-2-0.9 C-173.7,240.2-174,239.5-174,238.5 M-166.8,235.5c0-1.1-0.4-2-1.2-2.7s-1.8-1-3.1-1c-1.6,0-2.9,0.5-3.7,1.4s-1.2,2.3-1.2,4 c0,1.9,0.4,3.3,1.2,4.3s2,1.5,3.6,1.5c1.4,0,2.6-0.4,3.4-1.2c0.8-0.8,1.2-2,1.2-3.4c0-0.3,0-0.6,0-0.8s0-0.3,0-0.5h-7.5v-0.2 v-0.4c0-1,0.3-1.8,0.8-2.3c0.5-0.6,1.2-0.8,2.2-0.8c0.8,0,1.4,0.2,1.8,0.6c0.4,0.3,0.7,0.9,0.7,1.5L-166.8,235.5 L-166.8,235.5z"/>
</g>
<g id="g28" transform="translate(278.2893,86.7291)">
<path id="path30" class="st1" d="M-174,238.5c-0.1-1.2-0.5-2.2-1.2-2.9s-1.7-1-2.9-1c-1.5,0-2.7,0.5-3.5,1.4s-1.2,2.3-1.2,4 c0,1.8,0.4,3.3,1.3,4.3c0.9,1,2,1.5,3.6,1.5c1.2,0,2.1-0.3,2.8-1c0.7-0.6,1.1-1.5,1.1-2.6l0,0h-2c0,0.6-0.2,1.2-0.6,1.6 c-0.4,0.4-0.9,0.7-1.5,0.7c-0.8,0-1.5-0.4-2-1.1c-0.5-0.7-0.7-1.7-0.7-2.9c0-1.4,0.2-2.5,0.7-3.2c0.4-0.8,1.1-1.2,1.9-1.2 c0.7,0,1.2,0.2,1.6,0.6c0.4,0.4,0.6,1,0.6,1.7L-174,238.5z"/>
</g>
<g id="g32" transform="translate(288.9428,92.0629)">
<path id="path34" class="st1" d="M-174,238.5c0.2,0.6,0.7,1,1.2,1.4c0.6,0.3,1.3,0.5,2.1,0.5c0.7,0,1.3-0.1,1.9-0.4 c0.6-0.3,1-0.6,1.4-1.1c0.2-0.2,0.3-0.5,0.4-0.9c0.1-0.4,0.1-1,0.1-1.8v-6.6h-1.9v6.7c0,0.9-0.2,1.6-0.6,2 c-0.4,0.4-1,0.6-1.8,0.6s-1.5-0.2-2-0.7c-0.5-0.4-0.8-1-0.8-1.7v-6.9h-2v8.5c0,0.4,0,0.8,0,1.1c0,0.4,0,0.7,0,1h2L-174,238.5 L-174,238.5z"/>
</g>
<g id="g36" transform="translate(310.1399,92.6334)">
<path id="path38" class="st1" d="M-174,238.5c-1,0-1.8-0.4-2.4-1.1c-0.6-0.8-0.9-1.8-0.9-3.2c0-1.3,0.3-2.3,0.8-3 s1.4-1,2.4-1s1.8,0.4,2.4,1.1c0.6,0.7,0.9,1.8,0.9,3.1s-0.3,2.3-0.8,3S-173,238.5-174,238.5 M-179.3,234.1 c0,1.8,0.5,3.2,1.4,4.2s2.2,1.6,3.8,1.6s2.9-0.5,3.8-1.4c0.9-1,1.4-2.3,1.4-4c0-1.8-0.5-3.2-1.4-4.2s-2.3-1.5-4-1.5 c-1.6,0-2.8,0.5-3.7,1.4C-178.8,231.2-179.3,232.5-179.3,234.1"/>
</g>
<path id="path40" class="st1" d="M151.9,321.6h-2v15.3h2V321.6z"/>
<g id="g42" transform="translate(339.5718,92.6334)">
<path id="path44" class="st1" d="M-174,238.5c-1,0-1.8-0.4-2.4-1.1c-0.6-0.8-0.9-1.8-0.9-3.2c0-1.3,0.3-2.3,0.8-3 s1.4-1,2.4-1s1.8,0.4,2.4,1.1c0.6,0.7,0.9,1.8,0.9,3.1s-0.3,2.3-0.8,3C-172.2,238.1-173,238.5-174,238.5 M-179.3,234.1 c0,1.8,0.5,3.2,1.4,4.2s2.2,1.6,3.8,1.6s2.9-0.5,3.8-1.4c0.9-1,1.4-2.3,1.4-4c0-1.8-0.5-3.2-1.4-4.2s-2.3-1.5-4-1.5 c-1.6,0-2.8,0.5-3.7,1.4C-178.8,231.2-179.3,232.5-179.3,234.1"/>
</g>
<g id="g46" transform="translate(360.7561,88.9398)">
<path id="path48" class="st1" d="M-174,238.5c0,1.1-0.3,2.1-0.8,2.7c-0.5,0.7-1.3,1-2.2,1s-1.6-0.4-2.1-1.1 c-0.5-0.7-0.8-1.7-0.8-3c0-1.2,0.3-2.1,0.8-2.7c0.5-0.7,1.3-1,2.2-1s1.6,0.4,2.1,1.1S-174,237.2-174,238.5 M-174.2,234.7 c-0.2-0.4-0.6-0.8-1.2-1.1c-0.6-0.3-1.2-0.5-1.9-0.5c-1.6,0.1-2.7,0.5-3.5,1.4s-1.2,2.2-1.2,3.9c0,1.6,0.4,2.9,1.2,3.8 c0.8,0.9,1.9,1.4,3.3,1.4c0.9,0,1.5-0.1,2.1-0.4c0.6-0.3,1-0.6,1.3-1.2l0.1,1.4h1.8c0-0.3,0-0.6-0.1-0.9c0-0.3,0-0.6,0-1 v-8.4c0-1.6-0.4-2.8-1.2-3.5s-2-1.1-3.7-1.1c-1.5,0-2.6,0.3-3.2,0.9c-0.7,0.6-1,1.5-1,2.7h2.1c0-0.7,0.2-1.3,0.6-1.6 c0.4-0.4,1-0.6,1.7-0.6c0.9,0,1.6,0.2,2.1,0.7c0.4,0.5,0.7,1.2,0.7,2.2L-174.2,234.7L-174.2,234.7z"/>
</g>
<path id="path50" class="st1" d="M197.9,332.3h2v-10.7h-2V332.3z M200,334.8h-2.3v2.2h2.3V334.8z"/>
<g id="g52" transform="translate(388.8405,88.4313)">
<path id="path54" class="st1" d="M-174,238.5h-1.6c-1,0-1.8-0.2-2.3-0.6c-0.5-0.4-0.8-0.9-0.8-1.6c0-0.5,0.2-0.9,0.6-1.3 c0.4-0.4,0.7-0.5,1.3-0.5c0.9,0,1.6,0.2,2.1,0.7c0.5,0.6,0.7,1.3,0.7,2.2V238.5z M-171.9,233.2h-1.8 c-0.1,0.2-0.1,0.8-0.2,1.6v0.1c-0.3-0.6-0.7-1.1-1.3-1.4c-0.6-0.3-1.3-0.5-2.1-0.5c-1.1,0-1.9,0.3-2.6,0.9 c-0.6,0.6-1,1.4-1,2.3c0,1.1,0.4,2,1.3,2.7c0.9,0.7,2.1,1,3.6,1h1.8v1.3c0,0.6-0.2,1-0.5,1.3c-0.4,0.3-0.9,0.4-1.6,0.4 c-0.6,0-1.2-0.2-1.5-0.5s-0.6-0.8-0.6-1.3h-1.9v0.2c0,0.9,0.3,1.7,1,2.2s1.6,0.8,2.9,0.8c1.5,0,2.5-0.3,3.2-0.8s1-1.4,1-2.5 v-6.6c0-0.1,0-0.2,0-0.4C-172,233.6-172,233.4-171.9,233.2"/>
</g>
<g id="g56" transform="translate(407.7927,89.5309)">
<path id="path58" class="st1" d="M-174,238.5h5.4v0.2c0,0.9-0.2,1.6-0.7,2.1c-0.5,0.6-1.1,0.9-1.9,0.9s-1.5-0.3-2-0.9 C-173.7,240.2-174,239.5-174,238.5 M-166.8,235.5c0-1.1-0.4-2-1.2-2.7s-1.8-1-3.1-1c-1.6,0-2.9,0.5-3.7,1.4s-1.2,2.3-1.2,4 c0,1.9,0.4,3.3,1.2,4.3s2,1.5,3.6,1.5c1.4,0,2.6-0.4,3.4-1.2c0.8-0.8,1.2-2,1.2-3.4c0-0.3,0-0.6,0-0.8s0-0.3,0-0.5h-7.5v-0.2 v-0.4c0-1,0.3-1.8,0.8-2.3c0.5-0.6,1.2-0.8,2.2-0.8c0.8,0,1.4,0.2,1.8,0.6c0.4,0.3,0.7,0.9,0.7,1.5L-166.8,235.5 L-166.8,235.5z"/>
</g>
<g id="g60" transform="translate(431.8045,88.6905)">
<path id="path62" class="st1" d="M-174,238.5c0-1.4,0.3-2.4,0.8-3.2c0.6-0.8,1.3-1.2,2.2-1.2s1.7,0.4,2.2,1.1 c0.6,0.7,0.8,1.7,0.8,3c0,1.4-0.3,2.4-0.8,3.2s-1.2,1.2-2.1,1.2c-1,0-1.7-0.4-2.3-1.1C-173.7,240.7-174,239.7-174,238.5 M-175.9,228.9v12.6c0,0.4,0,0.7,0,1.1c-0.1,0.3-0.1,0.7-0.2,1h2l0.1-1.6c0.4,0.6,0.9,1.1,1.4,1.4c0.6,0.3,1.2,0.5,2,0.5 c1.5,0,2.6-0.5,3.4-1.5c0.8-1,1.2-2.3,1.2-4.1s-0.3-3.1-1.1-4.1s-2-1.4-3.4-1.4c-0.7,0-1.4,0.2-2,0.5s-1.1,0.7-1.5,1.3v-5.7 H-175.9z"/>
</g>
<g id="g64" transform="translate(449.8494,89.5309)">
<path id="path66" class="st1" d="M-174,238.5h5.4v0.2c0,0.9-0.2,1.6-0.7,2.1c-0.5,0.6-1.1,0.9-1.9,0.9c-0.8,0-1.5-0.3-2-0.9 C-173.7,240.2-174,239.5-174,238.5 M-166.8,235.5c0-1.1-0.4-2-1.2-2.7c-0.8-0.7-1.8-1-3.1-1c-1.6,0-2.9,0.5-3.7,1.4 s-1.2,2.3-1.2,4c0,1.9,0.4,3.3,1.2,4.3s2,1.5,3.6,1.5c1.4,0,2.6-0.4,3.4-1.2c0.8-0.8,1.2-2,1.2-3.4c0-0.3,0-0.6,0-0.8 s0-0.3,0-0.5h-7.5v-0.2v-0.4c0-1,0.3-1.8,0.8-2.3c0.5-0.6,1.2-0.8,2.2-0.8c0.8,0,1.4,0.2,1.8,0.6c0.4,0.3,0.7,0.9,0.7,1.5 L-166.8,235.5L-166.8,235.5z"/>
</g>
<g id="g68" transform="translate(465.2733,86.3452)">
<path id="path70" class="st1" d="M-174,238.5h2l0,0c0-0.6,0.2-1,0.6-1.4c0.4-0.4,0.9-0.6,1.6-0.6s1.2,0.2,1.6,0.5 c0.4,0.3,0.6,0.7,0.6,1.2c0,0.4-0.1,0.7-0.3,0.9s-0.5,0.4-1,0.5l-2.2,0.5c-0.9,0.2-1.6,0.6-2.1,1c-0.5,0.5-0.7,1-0.7,1.8 c0,1,0.4,1.8,1.2,2.4c0.7,0.6,1.8,0.9,3.1,0.9c1.2,0,2.1-0.3,2.8-0.8s1-1.2,1-2.1c0-0.1,0-0.1,0-0.2V243h-2v0.1 c0,0.5-0.2,0.9-0.5,1.2c-0.4,0.4-0.9,0.5-1.5,0.5s-1.1-0.1-1.5-0.4c-0.4-0.3-0.6-0.7-0.6-1.1c0-0.3,0.1-0.6,0.4-0.8 c0.2-0.2,0.6-0.4,1.2-0.5l2.4-0.7c0.8-0.2,1.4-0.6,1.8-1c0.4-0.5,0.6-1.1,0.6-1.8c0-1-0.4-1.8-1.1-2.4 c-0.7-0.6-1.8-1.1-3.1-1.1c-1.5,0-2.6,0.3-3.3,0.8s-1,1.3-1,2.5V238.5z"/>
</g>
<g id="g72" transform="translate(489.4717,88.6905)">
<path id="path74" class="st1" d="M-174,238.5c0,1.2-0.3,2.2-0.8,3c-0.6,0.7-1.3,1.1-2.2,1.1s-1.6-0.4-2.2-1.2 c-0.6-0.8-0.8-1.9-0.8-3.2s0.3-2.2,0.8-3s1.3-1.1,2.2-1.1s1.6,0.4,2.2,1.2C-174.2,236.1-174,237.1-174,238.5 M-172,228.9h-2 v5.7c-0.4-0.6-0.9-1-1.5-1.3s-1.2-0.5-1.9-0.5c-1.5,0-2.6,0.5-3.4,1.4c-0.8,1-1.2,2.3-1.2,4.1c0,1.7,0.4,3.1,1.2,4.1 s2,1.5,3.4,1.5c0.7,0,1.4-0.2,2-0.5s1-0.8,1.4-1.4l0.1,1.6h2c-0.1-0.3-0.1-0.6-0.1-0.9s0-0.7,0-1.2V228.9z"/>
</g>
<g id="g76" transform="translate(507.5892,84.8196)">
<path id="path78" class="st1" d="M-174,238.5c-0.2-0.6-0.7-1-1.3-1.4c-0.6-0.3-1.3-0.5-2.1-0.5c-0.7,0-1.3,0.1-1.9,0.4 c-0.6,0.3-1,0.6-1.4,1.1c-0.1,0.2-0.2,0.5-0.3,0.9s-0.1,1-0.1,1.8v6.7h1.9v-6.8c0-0.9,0.2-1.6,0.6-2c0.4-0.4,1-0.6,1.8-0.6 s1.5,0.2,2,0.7c0.5,0.4,0.8,1,0.8,1.7v7h2v-8.6c0-0.4,0-0.8,0-1.1s0-0.7,0.1-1h-2L-174,238.5z"/>
</g>
<path id="path80" class="st1" d="M345.1,332.3h2v-10.7h-2V332.3z M347.2,334.8h-2.3v2.2h2.3V334.8z"/>
<g id="g82" transform="translate(529.1852,86.3452)">
<path id="path84" class="st1" d="M-174,238.5h2l0,0c0-0.6,0.2-1,0.6-1.4c0.4-0.4,0.9-0.6,1.6-0.6s1.2,0.2,1.6,0.5 c0.4,0.3,0.6,0.7,0.6,1.2c0,0.4-0.1,0.7-0.3,0.9s-0.5,0.4-1,0.5l-2.2,0.5c-0.9,0.2-1.6,0.6-2.1,1c-0.5,0.5-0.7,1-0.7,1.8 c0,1,0.4,1.8,1.2,2.4c0.7,0.6,1.8,0.9,3.1,0.9c1.2,0,2.1-0.3,2.8-0.8c0.7-0.5,1-1.2,1-2.1c0-0.1,0-0.1,0-0.2V243h-2v0.1 c0,0.5-0.2,0.9-0.5,1.2c-0.4,0.4-0.9,0.5-1.5,0.5s-1.1-0.1-1.5-0.4c-0.4-0.3-0.6-0.7-0.6-1.1c0-0.3,0.1-0.6,0.4-0.8 c0.2-0.2,0.6-0.4,1.2-0.5l2.4-0.7c0.8-0.2,1.4-0.6,1.8-1c0.4-0.5,0.6-1.1,0.6-1.8c0-1-0.4-1.8-1.1-2.4 c-0.7-0.6-1.8-1.1-3.1-1.1c-1.5,0-2.6,0.3-3.3,0.8s-1,1.3-1,2.5V238.5z"/>
</g>
<g id="g86" transform="translate(552.8224,88.4313)">
<path id="path88" class="st1" d="M-174,238.5h-1.6c-1,0-1.8-0.2-2.3-0.6c-0.5-0.4-0.8-0.9-0.8-1.6c0-0.5,0.2-0.9,0.6-1.3 c0.4-0.4,0.7-0.5,1.3-0.5c0.9,0,1.6,0.2,2.1,0.7c0.5,0.6,0.7,1.3,0.7,2.2V238.5z M-171.9,233.2h-1.8 c-0.1,0.2-0.1,0.8-0.2,1.6v0.1c-0.3-0.6-0.7-1.1-1.3-1.4c-0.6-0.3-1.3-0.5-2.1-0.5c-1.1,0-1.9,0.3-2.6,0.9 c-0.6,0.6-1,1.4-1,2.3c0,1.1,0.4,2,1.3,2.7c0.9,0.7,2.1,1,3.6,1h2v1.3c0,0.6-0.2,1-0.5,1.3c-0.4,0.3-0.9,0.4-1.6,0.4 c-0.7,0-1.2-0.2-1.5-0.5s-0.6-0.8-0.6-1.3h-1.9v0.2c0,0.9,0.3,1.7,1,2.2s1.6,0.8,2.9,0.8c1.5,0,2.5-0.3,3.2-0.8s1-1.4,1-2.5 v-6.6c0-0.1,0-0.2,0-0.4C-172,233.6-172,233.4-171.9,233.2"/>
</g>
<g id="g90" transform="translate(567.7962,93.428)">
<path id="path92" class="st2" d="M-174,238.5l6.8-4.1l-6.8-4.1v-1.6l8.3,5v1.3l-8.3,5.1V238.5z M-515.9,238.5l-6.8-4.1 l6.8-4.1v-1.6l-8.3,5v1.3l8.3,5V238.5z"/>
</g>
<g id="g94" transform="translate(364.7085,150.4445)">
<path id="path96" class="st3" d="M-174,238.5c0-7.9,2.2-15.4,8-21.4c5.5-5.6,12.5-8.1,20.6-8.1s15.1,2.5,20.6,8.1 c5.9,6,8,13.5,8,21.4s-2.2,15.5-8,21.4c-5.5,5.6-12.5,8.1-20.6,8.1s-15.1-2.5-20.6-8.1C-171.8,254-174,246.4-174,238.5 M-58.9,239.5v-1.9c-0.2-6.6-2.1-12.8-7.1-17.8c-4.8-4.9-11-7.1-18.1-7.1s-13.2,2.2-18,7.1c-5.1,5.2-7,11.7-7,18.7 s1.9,13.6,7.1,18.8c4.8,4.9,11,7.1,18,7.1c7.1,0,13.2-2.2,18.1-7.1C-61,252.3-59.1,246.1-58.9,239.5 M-107.4,208.1 c0.5-4,2.6-7.7,6.2-10.1c6.6-4.4,18.7-5.5,28.4-3.1c4.3,1.1,8,3.2,10.6,5.8c5.3,5.4,6.9,13.1,6.9,20.5v45.4h-3.6v-12.7 c-1.2,2.2-2.7,4.2-4.5,6c-5.5,5.6-12.5,8.1-20.6,8.1s-15.1-2.5-20.6-8.1c-5.9-6-8-13.5-8-21.4s2.2-15.4,8-21.4 c5.5-5.6,12.5-8.1,20.6-8.1s15.1,2.5,20.6,8.1c1.8,1.9,3.3,3.9,4.5,6v-1.9c0-10.9-2.5-20.2-14.8-23.3 c-7.3-1.9-18.1-1-23.7,1.8c-3.4,1.8-5.8,4.6-6.4,8.4L-107.4,208.1L-107.4,208.1z M78.5,210.4v25.4v3.3l0.1,11 c0.2,5.1-1.2,11-4.7,13.7c-4.5,3.6-11.1,4.7-16.4,4.7s-11.5-1.1-15.9-4.1c-3.4-2.3-4.4-5.7-5-9.3h4c0.6,3,2.2,5.6,5,7.5 c6.1,3.5,18.6,3.4,24.6-0.4c3.4-2.6,4.6-6.3,4.6-10.3v-8.2c-8.8,0-18.3,0.7-26.8-2c-2.7-0.8-5.2-1.9-7.4-3.4 c-11.6-7.4-9.2-24.1,3.7-28.1c2.5-0.8,5.2-1.1,8-1.1c4.1,0,8.1,0.8,11.7,2.7c3.5,1.9,6.2,4.5,8.3,7.8l2.4,3.8v-12.9 L78.5,210.4z M49.3,238.3c6.8,2,15.4,2.4,25.4,1.8v-4.4v-4.3c-2-5.5-7.1-13.8-13.2-17c-5.2-2.2-11.1-2.7-15.9-1 c-9.9,3.5-11.7,16.7-2.6,22.3C44.8,236.9,47,237.7,49.3,238.3 M23.2,225.3h-4.9c-0.7-8.4-8.3-12.9-17.9-12.9 c-6.4,0-12.1,1.7-16,6.6c-4.2,5.4-5.9,12.8-5.9,19.2c0,13.9,4.8,26.8,22.3,26.5c9.8-0.1,17.2-5.8,17.1-13.3h5.2 c-0.5,4.6-2.3,8.6-6.1,11.7c-4.5,3.7-10.3,4.9-16.2,4.9c-7.7,0-14.6-2-19.6-7.7c-5.4-6.2-6.9-14.8-6.9-22.5 c0-7.6,1.6-15.4,7.1-21.3c5.1-5.4,11.8-7.5,19.4-7.5c5.8,0,11.6,1.1,16.1,4.7C20.7,216.8,22.5,220.8,23.2,225.3 M-186.6,210.4h3.6v82h-3.6V210.4z M-287,210.4h4.9l23.9,56.2h-4.6l-21.8-52.8l-22.7,52.8h-4.3L-287,210.4z M-253.6,238.5 c0-7.9,2.2-15.4,8.1-21.4c5.5-5.6,12.5-8.1,20.6-8.1s15.1,2.5,20.6,8.1c5.9,6,8,13.5,8,21.4s-2.2,15.5-8,21.4 c-5.5,5.6-12.5,8.1-20.6,8.1s-15.1-2.5-20.6-8.1C-251.4,254-253.6,246.4-253.6,238.5 M-250.1,238.5c0,7,1.9,13.6,7.1,18.8 c4.9,4.9,11,7.1,18.1,7.1s13.2-2.2,18.1-7.1c5.1-5.2,7-11.8,7-18.8s-1.9-13.6-7.1-18.8c-4.9-4.9-11-7.1-18.1-7.1 s-13.2,2.2-18.1,7.1C-248.2,225-250.1,231.5-250.1,238.5 M-40.8,270.8h3.7v5.3h-3.7V270.8z M-40.7,266.6h3.5v-56.2h-3.5 V266.6z M-362.4,210.4h3.6h43.3v3.6h-43.3v35.6h35.8v3.6h-35.8v35.6h43.3v3.5h-43.3h-3.6v-3.5v-35.6v-3.6V214V210.4z M-121.9,270.6h5.2v5.6h-5.2V270.6z M-170.5,238.5c0,7,1.9,13.6,7.1,18.8c4.8,4.9,11,7.1,18.1,7.1s13.2-2.2,18-7.1 c5.2-5.2,7.1-11.8,7.1-18.8s-1.9-13.6-7.1-18.8c-4.8-4.9-11-7.1-18-7.1c-7.1,0-13.2,2.2-18.1,7.1 C-168.6,225-170.5,231.5-170.5,238.5"/>
</g>
</g>
</g>
</g>
</g>
</g>
<g id="g98" class="st4">
<g class="st5">
<g>
<g>
<defs>
<path id="SVGID_3_" d="M214.3,602c-8.2-6.9-6.8-20.6-4.9-29.9l0,0c1.4-5.8,2.8-11.6,4.1-17.4l0,0v-0.1c1-4.3,2.1-8.6,3.1-12.9 l0,0c-3.7,2-7.5,4.1-11.2,6.1l0,0c-13.7,7.6-27.5,14.9-41.6,21.7l0,0c-6.6,3.1-13.2,6.1-19.9,8.8l0,0 c-5.5,2.2-11.3,4.3-17.1,5.7l0,0c-4,1-8.2,1.6-12.3,1.2l0,0c-3.2-0.3-6.5-1.1-9.1-3.1l0,0c-2.6-1.9-4.3-4.5-5.1-7.6l0,0 c-0.9-3.2-0.7-6.6-0.1-9.8l0,0c1.7-9.2,7-19.5,11.9-27.5l0,0c6.9-11.5,15.4-22.4,24.4-32.3l0,0c14.5-16,32.6-31.7,52.1-41.8 l0,0c9-4.7,12.1-5.4,23.5-5.1l0,0c5.8,0.2,11.6,0.7,17.3,1.5l0,0c13.8,1.8,27.8,4.8,41.3,8.5l0,0c10.6,2.9,21.3,6.3,31.6,10.3 l0,0c8.5,3.4,17.5,7.3,25.2,12.4l0,0c7.7,5.1,17.2,14.5,18.3,24.1l0,0c1,8.6-3,17.1-7.8,24.1l0,0 c-7.9,11.4-20.4,21.5-31.5,29.5l0,0c-9,6.4-18.4,12.3-28,17.8l0,0c-7.5,4.2-15.1,8.3-22.9,12l0,0c-0.1,0-0.1,0.1-0.2,0.1l0,0 c-7.5,3.4-16.2,6.6-24.5,7.4l0,0c-1.2,0.1-2.4,0.2-3.7,0.2l0,0C222.7,606.1,218,605.1,214.3,602 M274,514.4 c-15.9,5.7-31.3,13.4-46.2,21.3l0,0c-0.1,0.3-0.2,0.6-0.3,0.9l0,0c-0.4,2.5-1,5-1.6,7.5l0,0c-1,4-1.9,8-2.8,12l0,0l0,0 c-1.4,5.8-2.8,11.6-4.1,17.3l0,0c-1.3,6.2-3.4,19.3,4.4,22.4l0,0c7.6,3,21.2-2.4,28.1-5.3l0,0c7.5-3.5,14.9-7.5,22.1-11.6l0,0 c9.2-5.3,18.3-11,27-17.2l0,0c10.3-7.4,21.9-16.8,29.2-27.2l0,0c4-5.6,7.5-12.9,5.8-19.9l0,0c-0.4-1.7-1-4.1-2.4-5.3l0,0 c-1.7-1.5-6-2-8.2-2.4l0,0c-3.7-0.6-7.4-0.9-11.1-0.9l0,0C300.3,506.3,286.5,509.9,274,514.4 M191.4,471.7L191.4,471.7 c-17.7,9.6-34,23.8-47.4,38.6l0,0c-8.5,9.4-16.5,19.7-23.1,30.5l0,0c-4.4,7.2-9.5,16.7-11,25.1l0,0c-0.4,2.1-0.6,4.4,0,6.5 l0,0c0.3,1.2,0.9,2.3,2,3.1l0,0c1.2,0.9,2.8,1.2,4.2,1.3l0,0c2.8,0.2,6-0.3,8.7-1l0,0c5.4-1.3,10.8-3.3,15.9-5.4l0,0 c6.5-2.6,12.8-5.4,19.1-8.4l0,0c13.9-6.6,27.5-13.9,41-21.4l0,0c6.2-3.4,12.4-6.8,18.6-10.2l0,0c2.8-12.9,2.7-28-1.4-40.6l0,0 c-2.2-6.8-5.9-13.7-11.6-18.1l0,0c-2.6-2-4.8-2.9-7-2.9l0,0C196.9,468.7,194.5,469.8,191.4,471.7 M227.2,487 c3.8,11.8,4.4,25.4,2.8,37.8l0,0c13.2-6.8,26.8-13.3,40.7-18.3l0,0c15.9-5.7,33.7-10.1,50.7-8.6l0,0 c-6.3-4.2-13.9-7.6-20.6-10.3l0,0c-10.8-4.4-22.1-7.9-33.4-11l0,0c-10-2.7-20.2-5-30.4-6.9l0,0c-7.2-1.3-14.6-2.4-21.9-2.8 l0,0C221,472.2,224.8,479.5,227.2,487"/>
</defs>
<clipPath id="SVGID_4_">
<use xlink:href="#SVGID_3_" style="overflow:visible;"/>
</clipPath>
<g id="g100" class="st6">
<g id="g106" transform="translate(538.354,311.0468)">
<path id="path108" class="st7" d="M-174,238.5l-0.1-0.2l-229.6,103.1l0.1,0.1"/>
</g>
<g id="g110" transform="translate(538.4807,311.2684)">
<path id="path112" class="st8" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g114" transform="translate(538.1324,310.5403)">
<path id="path116" class="st9" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g118" transform="translate(537.8159,309.8121)">
<path id="path120" class="st9" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g122" transform="translate(537.4676,309.084)">
<path id="path124" class="st10" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g126" transform="translate(537.151,308.3242)">
<path id="path128" class="st11" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g130" transform="translate(536.8344,307.5961)">
<path id="path132" class="st12" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g134" transform="translate(536.4862,306.8679)">
<path id="path136" class="st12" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g138" transform="translate(536.1696,306.1398)">
<path id="path140" class="st13" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g142" transform="translate(535.8214,305.4117)">
<path id="path144" class="st14" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g146" transform="translate(535.5048,304.6835)">
<path id="path148" class="st15" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g150" transform="translate(535.1882,303.9237)">
<path id="path152" class="st15" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g154" transform="translate(534.84,303.1956)">
<path id="path156" class="st16" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g158" transform="translate(534.5234,302.4674)">
<path id="path160" class="st17" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g162" transform="translate(534.1751,301.7393)">
<path id="path164" class="st18" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g166" transform="translate(533.8586,301.0111)">
<path id="path168" class="st19" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g170" transform="translate(533.5419,300.2513)">
<path id="path172" class="st19" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g174" transform="translate(533.1937,299.5232)">
<path id="path176" class="st20" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g178" transform="translate(532.8771,298.7951)">
<path id="path180" class="st20" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g182" transform="translate(532.5289,298.0669)">
<path id="path184" class="st21" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g186" transform="translate(532.2123,297.3388)">
<path id="path188" class="st21" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g190" transform="translate(531.8958,296.6106)">
<path id="path192" class="st22" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g194" transform="translate(531.5475,295.8508)">
<path id="path196" class="st23" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g198" transform="translate(531.2309,295.1227)">
<path id="path200" class="st24" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g202" transform="translate(530.8827,294.3945)">
<path id="path204" class="st25" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g206" transform="translate(530.5661,293.6664)">
<path id="path208" class="st26" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g210" transform="translate(530.2495,292.9383)">
<path id="path212" class="st27" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g214" transform="translate(529.9013,292.2102)">
<path id="path216" class="st27" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g218" transform="translate(529.5847,291.4503)">
<path id="path220" class="st28" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g222" transform="translate(529.2365,290.7222)">
<path id="path224" class="st28" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g226" transform="translate(528.9199,289.9941)">
<path id="path228" class="st29" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g230" transform="translate(528.6033,289.2659)">
<path id="path232" class="st29" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g234" transform="translate(528.255,288.5378)">
<path id="path236" class="st30" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g238" transform="translate(527.9385,287.8096)">
<path id="path240" class="st31" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g242" transform="translate(527.5902,287.0499)">
<path id="path244" class="st30" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g246" transform="translate(527.2736,286.3217)">
<path id="path248" class="st32" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g250" transform="translate(526.957,285.5936)">
<path id="path252" class="st32" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g254" transform="translate(526.6088,284.8654)">
<path id="path256" class="st33" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g258" transform="translate(526.2922,284.1373)">
<path id="path260" class="st34" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g262" transform="translate(525.944,283.4091)">
<path id="path264" class="st35" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g266" transform="translate(525.6274,282.6494)">
<path id="path268" class="st35" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g270" transform="translate(525.3108,281.9212)">
<path id="path272" class="st36" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g274" transform="translate(524.9626,281.1931)">
<path id="path276" class="st37" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g278" transform="translate(524.646,280.4649)">
<path id="path280" class="st38" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g282" transform="translate(524.2977,279.7368)">
<path id="path284" class="st38" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g286" transform="translate(523.9812,279.0086)">
<path id="path288" class="st39" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g290" transform="translate(523.6646,278.2489)">
<path id="path292" class="st39" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g294" transform="translate(523.3163,277.5207)">
<path id="path296" class="st40" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g298" transform="translate(522.9998,276.7926)">
<path id="path300" class="st40" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g302" transform="translate(522.6516,276.0644)">
<path id="path304" class="st41" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g306" transform="translate(522.335,275.3363)">
<path id="path308" class="st42" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g310" transform="translate(522.0184,274.6082)">
<path id="path312" class="st42" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g314" transform="translate(521.6701,273.8483)">
<path id="path316" class="st43" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g318" transform="translate(521.3535,273.1202)">
<path id="path320" class="st43" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g322" transform="translate(521.0053,272.3921)">
<path id="path324" class="st44" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g326" transform="translate(520.6887,271.6639)">
<path id="path328" class="st44" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g330" transform="translate(520.3721,270.9358)">
<path id="path332" class="st45" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g334" transform="translate(520.0239,270.2076)">
<path id="path336" class="st46" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g338" transform="translate(519.7073,269.4478)">
<path id="path340" class="st47" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g342" transform="translate(519.3591,268.7197)">
<path id="path344" class="st47" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g346" transform="translate(519.0425,267.9916)">
<path id="path348" class="st48" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g350" transform="translate(518.7259,267.2634)">
<path id="path352" class="st49" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g354" transform="translate(518.3777,266.5353)">
<path id="path356" class="st50" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g358" transform="translate(518.0611,265.8072)">
<path id="path360" class="st51" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g362" transform="translate(517.7128,265.0474)">
<path id="path364" class="st51" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g366" transform="translate(517.3962,264.3192)">
<path id="path368" class="st52" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g370" transform="translate(517.0797,263.5911)">
<path id="path372" class="st53" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g374" transform="translate(516.7314,262.8629)">
<path id="path376" class="st54" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g378" transform="translate(516.4149,262.1348)">
<path id="path380" class="st54" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g382" transform="translate(516.0666,261.4067)">
<path id="path384" class="st55" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g386" transform="translate(515.7501,260.6469)">
<path id="path388" class="st55" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g390" transform="translate(515.4334,259.9187)">
<path id="path392" class="st56" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g394" transform="translate(515.0852,259.1906)">
<path id="path396" class="st56" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g398" transform="translate(514.7686,258.4624)">
<path id="path400" class="st57" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g402" transform="translate(514.4204,257.7343)">
<path id="path404" class="st58" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g406" transform="translate(514.1038,257.0062)">
<path id="path408" class="st58" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g410" transform="translate(513.7872,256.2464)">
<path id="path412" class="st59" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g414" transform="translate(513.439,255.5182)">
<path id="path416" class="st59" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g418" transform="translate(513.1224,254.7901)">
<path id="path420" class="st60" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g422" transform="translate(512.7742,254.062)">
<path id="path424" class="st60" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g426" transform="translate(512.4576,253.3338)">
<path id="path428" class="st61" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g430" transform="translate(512.141,252.6057)">
<path id="path432" class="st61" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g434" transform="translate(511.7928,251.8459)">
<path id="path436" class="st62" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g438" transform="translate(511.4762,251.1177)">
<path id="path440" class="st62" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g442" transform="translate(511.1279,250.3896)">
<path id="path444" class="st63" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g446" transform="translate(510.8113,249.6615)">
<path id="path448" class="st64" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g450" transform="translate(510.4948,248.9333)">
<path id="path452" class="st65" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g454" transform="translate(510.1465,248.1735)">
<path id="path456" class="st66" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g458" transform="translate(509.83,247.4454)">
<path id="path460" class="st66" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g462" transform="translate(509.4817,246.7172)">
<path id="path464" class="st67" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g466" transform="translate(509.1651,245.9891)">
<path id="path468" class="st68" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g470" transform="translate(508.8485,245.261)">
<path id="path472" class="st69" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g474" transform="translate(508.5003,244.5328)">
<path id="path476" class="st69" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g478" transform="translate(508.1837,243.773)">
<path id="path480" class="st70" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g482" transform="translate(507.8355,243.0449)">
<path id="path484" class="st71" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g486" transform="translate(507.5189,242.3167)">
<path id="path488" class="st72" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g490" transform="translate(507.2023,241.5886)">
<path id="path492" class="st72" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g494" transform="translate(506.8541,240.8605)">
<path id="path496" class="st73" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g498" transform="translate(506.5375,240.1323)">
<path id="path500" class="st74" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g502" transform="translate(506.1892,239.3725)">
<path id="path504" class="st75" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g506" transform="translate(505.8727,238.6444)">
<path id="path508" class="st76" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g510" transform="translate(505.5561,237.9162)">
<path id="path512" class="st76" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g514" transform="translate(505.2079,237.1881)">
<path id="path516" class="st77" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g518" transform="translate(504.8913,236.46)">
<path id="path520" class="st77" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g522" transform="translate(504.543,235.7318)">
<path id="path524" class="st78" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g526" transform="translate(504.2264,234.972)">
<path id="path528" class="st78" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g530" transform="translate(503.9098,234.2439)">
<path id="path532" class="st79" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g534" transform="translate(503.5616,233.5157)">
<path id="path536" class="st79" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g538" transform="translate(503.245,232.7876)">
<path id="path540" class="st80" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g542" transform="translate(502.8968,232.0595)">
<path id="path544" class="st81" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g546" transform="translate(502.5802,231.3313)">
<path id="path548" class="st82" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g550" transform="translate(502.2636,230.5715)">
<path id="path552" class="st83" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g554" transform="translate(501.9154,229.8434)">
<path id="path556" class="st83" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g558" transform="translate(501.5988,229.1152)">
<path id="path560" class="st84" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g562" transform="translate(501.2506,228.3871)">
<path id="path564" class="st84" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g566" transform="translate(500.934,227.659)">
<path id="path568" class="st85" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g570" transform="translate(500.6174,226.9308)">
<path id="path572" class="st85" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g574" transform="translate(500.2691,226.171)">
<path id="path576" class="st86" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g578" transform="translate(499.9525,225.4429)">
<path id="path580" class="st87" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g582" transform="translate(499.6043,224.7148)">
<path id="path584" class="st88" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g586" transform="translate(499.2877,223.9866)">
<path id="path588" class="st88" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g590" transform="translate(498.9712,223.2585)">
<path id="path592" class="st89" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g594" transform="translate(498.6229,222.5303)">
<path id="path596" class="st90" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g598" transform="translate(498.3063,221.7705)">
<path id="path600" class="st91" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g602" transform="translate(497.9581,221.0424)">
<path id="path604" class="st92" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g606" transform="translate(497.6415,220.3142)">
<path id="path608" class="st92" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g610" transform="translate(497.3249,219.5861)">
<path id="path612" class="st93" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g614" transform="translate(496.9767,218.858)">
<path id="path616" class="st94" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g618" transform="translate(496.6601,218.1298)">
<path id="path620" class="st95" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g622" transform="translate(496.3119,217.37)">
<path id="path624" class="st95" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g626" transform="translate(495.9953,216.6419)">
<path id="path628" class="st96" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g630" transform="translate(495.6787,215.9137)">
<path id="path632" class="st96" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g634" transform="translate(495.3304,215.1856)">
<path id="path636" class="st97" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g638" transform="translate(495.0139,214.4575)">
<path id="path640" class="st97" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g642" transform="translate(494.6656,213.7293)">
<path id="path644" class="st98" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g646" transform="translate(494.3491,212.9695)">
<path id="path648" class="st99" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g650" transform="translate(494.0325,212.2414)">
<path id="path652" class="st99" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g654" transform="translate(493.6842,211.5132)">
<path id="path656" class="st100" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g658" transform="translate(493.3676,210.7851)">
<path id="path660" class="st100" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g662" transform="translate(493.0194,210.057)">
<path id="path664" class="st101" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g666" transform="translate(492.7028,209.3288)">
<path id="path668" class="st101" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g670" transform="translate(492.3863,208.569)">
<path id="path672" class="st102" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g674" transform="translate(492.038,207.8409)">
<path id="path676" class="st103" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g678" transform="translate(491.7214,207.1128)">
<path id="path680" class="st104" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g682" transform="translate(491.3732,206.3846)">
<path id="path684" class="st104" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g686" transform="translate(491.0566,205.6565)">
<path id="path688" class="st105" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g690" transform="translate(490.74,204.9283)">
<path id="path692" class="st106" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g694" transform="translate(490.3918,204.1685)">
<path id="path696" class="st107" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g698" transform="translate(490.0752,203.4404)">
<path id="path700" class="st108" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g702" transform="translate(489.727,202.7123)">
<path id="path704" class="st108" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g706" transform="translate(489.4104,201.9841)">
<path id="path708" class="st109" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g710" transform="translate(489.0938,201.256)">
<path id="path712" class="st110" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g714" transform="translate(488.7455,200.5278)">
<path id="path716" class="st111" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g718" transform="translate(488.429,199.768)">
<path id="path720" class="st111" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g722" transform="translate(488.0807,199.0399)">
<path id="path724" class="st112" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g726" transform="translate(487.7642,198.3118)">
<path id="path728" class="st112" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g730" transform="translate(487.4476,197.5836)">
<path id="path732" class="st113" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g734" transform="translate(487.0993,196.8555)">
<path id="path736" class="st113" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g738" transform="translate(486.7827,196.0957)">
<path id="path740" class="st114" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g742" transform="translate(486.4345,195.3675)">
<path id="path744" class="st115" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g746" transform="translate(486.1179,194.6394)">
<path id="path748" class="st116" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g750" transform="translate(485.8013,193.9113)">
<path id="path752" class="st117" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g754" transform="translate(485.4531,193.1831)">
<path id="path756" class="st117" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g758" transform="translate(485.1365,192.455)">
<path id="path760" class="st118" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g762" transform="translate(484.7883,191.6952)">
<path id="path764" class="st118" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g766" transform="translate(484.4717,190.967)">
<path id="path768" class="st119" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g770" transform="translate(484.1551,190.2389)">
<path id="path772" class="st119" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g774" transform="translate(483.8069,189.5108)">
<path id="path776" class="st120" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g778" transform="translate(483.4903,188.7826)">
<path id="path780" class="st120" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g782" transform="translate(483.1421,188.0545)">
<path id="path784" class="st121" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g786" transform="translate(482.8254,187.2947)">
<path id="path788" class="st121" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g790" transform="translate(482.5089,186.5666)">
<path id="path792" class="st122" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g794" transform="translate(482.1606,185.8384)">
<path id="path796" class="st122" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g798" transform="translate(481.844,185.1103)">
<path id="path800" class="st122" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g802" transform="translate(481.4958,184.3821)">
<path id="path804" class="st122" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g806" transform="translate(481.1792,183.654)">
<path id="path808" class="st122" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g810" transform="translate(480.8626,182.8942)">
<path id="path812" class="st123" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g814" transform="translate(480.5144,182.1661)">
<path id="path816" class="st123" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g818" transform="translate(480.1978,181.4379)">
<path id="path820" class="st123" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g822" transform="translate(479.8495,180.7098)">
<path id="path824" class="st123" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g826" transform="translate(479.533,179.9816)">
<path id="path828" class="st123" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g830" transform="translate(479.2164,179.2535)">
<path id="path832" class="st123" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g834" transform="translate(478.8682,178.4937)">
<path id="path836" class="st123" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g838" transform="translate(478.5516,177.7655)">
<path id="path840" class="st123" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g842" transform="translate(478.2033,177.0374)">
<path id="path844" class="st123" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g846" transform="translate(477.8867,176.3093)">
<path id="path848" class="st123" d="M-174,238.5l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g850" transform="translate(477.5702,175.5811)">
<path id="path852" class="st123" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g854" transform="translate(477.2219,174.853)">
<path id="path856" class="st123" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g858" transform="translate(476.9054,174.0932)">
<path id="path860" class="st123" d="M-174,238.5l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g862" transform="translate(476.5571,173.3651)">
<path id="path864" class="st124" d="M-174,238.5l-0.1-0.3l-229.6,103l0.1,0.3"/>
</g>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generator: Adobe Illustrator 22.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="svg2" inkscape:version="0.91 r13725" sodipodi:docname="evologica_logo.svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 332 200" style="enable-background:new 0 0 332 200;" xml:space="preserve">
<style type="text/css">
.st0{fill:#231F20;fill-opacity:0;}
.st1{clip-path:url(#SVGID_2_);}
.st2{fill:#153A61;}
.st3{fill:#133B61;}
.st4{fill:#113C61;}
.st5{fill:#0E3D62;}
.st6{fill:#0F3D63;}
.st7{fill:#0C3E63;}
.st8{fill:#063F64;}
.st9{fill:#083F64;}
.st10{fill:#044065;}
.st11{fill:#004165;}
.st12{fill:#004265;}
.st13{fill:#004266;}
.st14{fill:#004366;}
.st15{fill:#004467;}
.st16{fill:#004568;}
.st17{fill:#004668;}
.st18{fill:#004667;}
.st19{fill:#004768;}
.st20{fill:#004769;}
.st21{fill:#004869;}
.st22{fill:#004969;}
.st23{fill:#004A6A;}
.st24{fill:#004B6A;}
.st25{fill:#004D6B;}
.st26{fill:#004C6B;}
.st27{fill:#004E6B;}
.st28{fill:#00506C;}
.st29{fill:#004F6C;}
.st30{fill:#00516D;}
.st31{fill:#00526D;}
.st32{fill:#00526E;}
.st33{fill:#00536E;}
.st34{fill:#00546E;}
.st35{fill:#00556F;}
.st36{fill:#00566F;}
.st37{fill:#00576F;}
.st38{fill:#005870;}
.st39{fill:#005970;}
.st40{fill:#005A70;}
.st41{fill:#005A71;}
.st42{fill:#005B71;}
.st43{fill:#005C71;}
.st44{fill:#005C72;}
.st45{fill:#005D72;}
.st46{fill:#005E72;}
.st47{fill:#005F72;}
.st48{fill:#005F73;}
.st49{fill:#006073;}
.st50{fill:#006172;}
.st51{fill:#006273;}
.st52{fill:#006374;}
.st53{fill:#006474;}
.st54{fill:#006575;}
.st55{fill:#006675;}
.st56{fill:#006876;}
.st57{fill:#006976;}
.st58{fill:#006A76;}
.st59{fill:#006A77;}
.st60{fill:#006B77;}
.st61{fill:#006C77;}
.st62{fill:#006D77;}
.st63{fill:#006D78;}
.st64{fill:#006E78;}
.st65{fill:#006F78;}
.st66{fill:#006F79;}
.st67{fill:#007079;}
.st68{fill:#007179;}
.st69{fill:#007279;}
.st70{fill:#00727A;}
.st71{fill:#00737A;}
.st72{fill:#00747A;}
.st73{fill:#00757B;}
.st74{fill:#00767B;}
.st75{fill:#00777A;}
.st76{fill:#00777C;}
.st77{fill:#00787B;}
.st78{fill:#00797B;}
.st79{fill:#007A7C;}
.st80{fill:#007C7D;}
.st81{fill:#007D7C;}
.st82{fill:#007D7D;}
.st83{fill:#007E7E;}
.st84{fill:#007F7E;}
.st85{fill:#00807E;}
.st86{fill:#00807F;}
.st87{fill:#00817F;}
.st88{fill:#00827F;}
.st89{fill:#008280;}
.st90{fill:#008380;}
.st91{fill:#008480;}
.st92{fill:#008581;}
.st93{fill:#008681;}
.st94{fill:#008781;}
.st95{fill:#008882;}
.st96{fill:#008982;}
.st97{fill:#008A81;}
.st98{fill:#008983;}
.st99{fill:#008A82;}
.st100{fill:#008B82;}
.st101{fill:#008B84;}
.st102{fill:#008C83;}
.st103{fill:#008D83;}
.st104{fill:#008E83;}
.st105{fill:#008E84;}
.st106{fill:#008F84;}
.st107{fill:#009084;}
.st108{fill:#009185;}
.st109{fill:#009284;}
.st110{fill:#009385;}
.st111{fill:#009486;}
.st112{fill:#009586;}
.st113{fill:#009686;}
.st114{fill:#009687;}
.st115{fill:#009887;}
.st116{fill:#009988;}
.st117{fill:#009A88;}
.st118{fill:#009B88;}
.st119{fill:#009C88;}
</style>
<sodipodi:namedview bordercolor="#666666" borderopacity="1" gridtolerance="10" guidetolerance="10" id="namedview433" inkscape:current-layer="g10" inkscape:cx="375.27209" inkscape:cy="211.08096" inkscape:pageopacity="0" inkscape:pageshadow="2" inkscape:window-height="1017" inkscape:window-maximized="1" inkscape:window-width="1920" inkscape:window-x="-8" inkscape:window-y="-8" inkscape:zoom="0.9594985" objecttolerance="10" pagecolor="#ffffff" showgrid="false">
</sodipodi:namedview>
<g id="g10" transform="matrix(1.3333333,0,0,-1.3333333,0,519.99997)">
<path id="path12" inkscape:connector-curvature="0" class="st0" d="M319.5,119.6H-70.4v388.6h389.9V119.6z"/>
<g id="g98" transform="translate(-201.85709,-98.60097)">
<g id="g98-9" transform="translate(-0.30375054,0.41458444)">
<g>
<defs>
<path id="SVGID_1_" d="M317.8,482.8c-8.2-6.9-6.8-20.6-4.9-29.9l0,0c1.4-5.8,2.8-11.6,4.1-17.4l0,0v-0.1 c1-4.3,2.1-8.6,3.1-12.9l0,0c-3.7,2-7.5,4.1-11.2,6.1l0,0c-13.7,7.6-27.5,14.9-41.6,21.7l0,0c-6.6,3.1-13.2,6.1-19.9,8.8l0,0 c-5.5,2.2-11.3,4.3-17.1,5.7l0,0c-4,1-8.2,1.6-12.3,1.2l0,0c-3.2-0.3-6.5-1.1-9.1-3.1l0,0c-2.6-1.9-4.3-4.5-5.1-7.6l0,0 c-0.9-3.2-0.7-6.6-0.1-9.8l0,0c1.7-9.2,7-19.5,11.9-27.5l0,0c6.9-11.5,15.4-22.4,24.4-32.3l0,0c14.5-16,32.6-31.7,52.1-41.8 l0,0c9-4.7,12.1-5.4,23.5-5.1l0,0c5.8,0.2,11.6,0.7,17.3,1.5l0,0c13.8,1.8,27.8,4.8,41.3,8.5l0,0c10.6,2.9,21.3,6.3,31.6,10.3 l0,0c8.5,3.4,17.5,7.3,25.2,12.4l0,0c7.7,5.1,17.2,14.5,18.3,24.1l0,0c1,8.6-3,17.1-7.8,24.1l0,0 c-7.9,11.4-20.4,21.5-31.5,29.5l0,0c-9,6.4-18.4,12.3-28,17.8l0,0c-7.5,4.2-15.1,8.3-22.9,12l0,0c-0.1,0-0.1,0.1-0.2,0.1l0,0 c-7.5,3.4-16.2,6.6-24.5,7.4l0,0c-1.2,0.1-2.4,0.2-3.7,0.2l0,0C326.2,486.8,321.5,485.9,317.8,482.8 M377.5,395.2 c-15.9,5.7-31.3,13.4-46.2,21.3l0,0c-0.1,0.3-0.2,0.6-0.3,0.9l0,0c-0.4,2.5-1,5-1.6,7.5l0,0c-1,4-1.9,8-2.8,12l0,0v0 c-1.4,5.8-2.8,11.6-4.1,17.3l0,0c-1.3,6.2-3.4,19.3,4.4,22.4l0,0c7.6,3,21.2-2.4,28.1-5.3l0,0c7.5-3.5,14.9-7.5,22.1-11.6l0,0 c9.2-5.3,18.3-11,27-17.2l0,0c10.3-7.4,21.9-16.8,29.2-27.2l0,0c4-5.6,7.5-12.9,5.8-19.9l0,0c-0.4-1.7-1-4.1-2.4-5.3l0,0 c-1.7-1.5-6-2-8.2-2.4l0,0c-3.7-0.6-7.4-0.9-11.1-0.9l0,0C403.8,387.1,390,390.7,377.5,395.2 M294.9,352.5L294.9,352.5 c-17.7,9.6-34,23.8-47.4,38.6l0,0c-8.5,9.4-16.5,19.7-23.1,30.5l0,0c-4.4,7.2-9.5,16.7-11,25.1l0,0c-0.4,2.1-0.6,4.4,0,6.5l0,0 c0.3,1.2,0.9,2.3,2,3.1l0,0c1.2,0.9,2.8,1.2,4.2,1.3l0,0c2.8,0.2,6-0.3,8.7-1l0,0c5.4-1.3,10.8-3.3,15.9-5.4l0,0 c6.5-2.6,12.8-5.4,19.1-8.4l0,0c13.9-6.6,27.5-13.9,41-21.4l0,0c6.2-3.4,12.4-6.8,18.6-10.2l0,0c2.8-12.9,2.7-28-1.4-40.6l0,0 c-2.2-6.8-5.9-13.7-11.6-18.1l0,0c-2.6-2-4.8-2.9-7-2.9l0,0C300.4,349.5,298,350.6,294.9,352.5 M330.7,367.7 c3.8,11.8,4.4,25.4,2.8,37.8l0,0c13.2-6.8,26.8-13.3,40.7-18.3l0,0c15.9-5.7,33.7-10.1,50.7-8.6l0,0 c-6.3-4.2-13.9-7.6-20.6-10.3l0,0c-10.8-4.4-22.1-7.9-33.4-11l0,0c-10-2.7-20.2-5-30.4-6.9l0,0c-7.2-1.3-14.6-2.4-21.9-2.8l0,0 C324.5,353,328.3,360.2,330.7,367.7"/>
</defs>
<clipPath id="SVGID_2_">
<use xlink:href="#SVGID_1_" style="overflow:visible;"/>
</clipPath>
<g id="g100-7" class="st1">
<g id="g106-6" transform="translate(538.354,311.0468)">
<path id="path108-7" inkscape:connector-curvature="0" class="st2" d="M-70.5,119.3l-0.1-0.2l-229.6,103.1l0.1,0.1"/>
</g>
<g id="g110-2" transform="translate(538.4807,311.2684)">
<path id="path112-4" inkscape:connector-curvature="0" class="st3" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g114-6" transform="translate(538.1324,310.5403)">
<path id="path116-4" inkscape:connector-curvature="0" class="st4" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g118-1" transform="translate(537.8159,309.8121)">
<path id="path120-3" inkscape:connector-curvature="0" class="st4" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g122-5" transform="translate(537.4676,309.084)">
<path id="path124-0" inkscape:connector-curvature="0" class="st5" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g126-0" transform="translate(537.151,308.3242)">
<path id="path128-3" inkscape:connector-curvature="0" class="st6" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g130-7" transform="translate(536.8344,307.5961)">
<path id="path132-4" inkscape:connector-curvature="0" class="st7" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g134-9" transform="translate(536.4862,306.8679)">
<path id="path136-6" inkscape:connector-curvature="0" class="st7" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g138-9" transform="translate(536.1696,306.1398)">
<path id="path140-6" inkscape:connector-curvature="0" class="st8" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g142-0" transform="translate(535.8214,305.4117)">
<path id="path144-3" inkscape:connector-curvature="0" class="st9" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g146-1" transform="translate(535.5048,304.6835)">
<path id="path148-9" inkscape:connector-curvature="0" class="st10" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g150-9" transform="translate(535.1882,303.9237)">
<path id="path152-8" inkscape:connector-curvature="0" class="st10" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g154-0" transform="translate(534.84,303.1956)">
<path id="path156-3" inkscape:connector-curvature="0" class="st11" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g158-9" transform="translate(534.5234,302.4674)">
<path id="path160-7" inkscape:connector-curvature="0" class="st12" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g162-9" transform="translate(534.1751,301.7393)">
<path id="path164-6" inkscape:connector-curvature="0" class="st13" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g166-9" transform="translate(533.8586,301.0111)">
<path id="path168-2" inkscape:connector-curvature="0" class="st14" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g170-2" transform="translate(533.5419,300.2513)">
<path id="path172-5" inkscape:connector-curvature="0" class="st14" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g174-4" transform="translate(533.1937,299.5232)">
<path id="path176-3" inkscape:connector-curvature="0" class="st15" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g178-0" transform="translate(532.8771,298.7951)">
<path id="path180-3" inkscape:connector-curvature="0" class="st15" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g182-8" transform="translate(532.5289,298.0669)">
<path id="path184-9" inkscape:connector-curvature="0" class="st16" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g186-0" transform="translate(532.2123,297.3388)">
<path id="path188-4" inkscape:connector-curvature="0" class="st16" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g190-5" transform="translate(531.8958,296.6106)">
<path id="path192-4" inkscape:connector-curvature="0" class="st17" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g194-4" transform="translate(531.5475,295.8508)">
<path id="path196-4" inkscape:connector-curvature="0" class="st18" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g198-5" transform="translate(531.2309,295.1227)">
<path id="path200-2" inkscape:connector-curvature="0" class="st19" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g202-0" transform="translate(530.8827,294.3945)">
<path id="path204-2" inkscape:connector-curvature="0" class="st20" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g206-7" transform="translate(530.5661,293.6664)">
<path id="path208-1" inkscape:connector-curvature="0" class="st21" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g210-4" transform="translate(530.2495,292.9383)">
<path id="path212-1" inkscape:connector-curvature="0" class="st22" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g214-1" transform="translate(529.9013,292.2102)">
<path id="path216-5" inkscape:connector-curvature="0" class="st22" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g218-4" transform="translate(529.5847,291.4503)">
<path id="path220-6" inkscape:connector-curvature="0" class="st23" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g222-2" transform="translate(529.2365,290.7222)">
<path id="path224-9" inkscape:connector-curvature="0" class="st23" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g226-4" transform="translate(528.9199,289.9941)">
<path id="path228-5" inkscape:connector-curvature="0" class="st24" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g230-8" transform="translate(528.6033,289.2659)">
<path id="path232-4" inkscape:connector-curvature="0" class="st24" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g234-9" transform="translate(528.255,288.5378)">
<path id="path236-1" inkscape:connector-curvature="0" class="st25" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g238-1" transform="translate(527.9385,287.8096)">
<path id="path240-5" inkscape:connector-curvature="0" class="st26" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g242-9" transform="translate(527.5902,287.0499)">
<path id="path244-2" inkscape:connector-curvature="0" class="st25" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g246-1" transform="translate(527.2736,286.3217)">
<path id="path248-8" inkscape:connector-curvature="0" class="st27" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g250-0" transform="translate(526.957,285.5936)">
<path id="path252-9" inkscape:connector-curvature="0" class="st27" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g254-0" transform="translate(526.6088,284.8654)">
<path id="path256-4" inkscape:connector-curvature="0" class="st28" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g258-6" transform="translate(526.2922,284.1373)">
<path id="path260-4" inkscape:connector-curvature="0" class="st29" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g262-4" transform="translate(525.944,283.4091)">
<path id="path264-3" inkscape:connector-curvature="0" class="st30" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g266-2" transform="translate(525.6274,282.6494)">
<path id="path268-5" inkscape:connector-curvature="0" class="st30" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g270-4" transform="translate(525.3108,281.9212)">
<path id="path272-2" inkscape:connector-curvature="0" class="st31" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g274-6" transform="translate(524.9626,281.1931)">
<path id="path276-6" inkscape:connector-curvature="0" class="st32" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g278-4" transform="translate(524.646,280.4649)">
<path id="path280-5" inkscape:connector-curvature="0" class="st33" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g282-4" transform="translate(524.2977,279.7368)">
<path id="path284-0" inkscape:connector-curvature="0" class="st33" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g286-7" transform="translate(523.9812,279.0086)">
<path id="path288-5" inkscape:connector-curvature="0" class="st34" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g290-4" transform="translate(523.6646,278.2489)">
<path id="path292-6" inkscape:connector-curvature="0" class="st34" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g294-9" transform="translate(523.3163,277.5207)">
<path id="path296-2" inkscape:connector-curvature="0" class="st35" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g298-2" transform="translate(522.9998,276.7926)">
<path id="path300-8" inkscape:connector-curvature="0" class="st35" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g302-3" transform="translate(522.6516,276.0644)">
<path id="path304-5" inkscape:connector-curvature="0" class="st36" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g306-5" transform="translate(522.335,275.3363)">
<path id="path308-3" inkscape:connector-curvature="0" class="st37" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g310-8" transform="translate(522.0184,274.6082)">
<path id="path312-1" inkscape:connector-curvature="0" class="st37" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g314-5" transform="translate(521.6701,273.8483)">
<path id="path316-1" inkscape:connector-curvature="0" class="st38" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g318-1" transform="translate(521.3535,273.1202)">
<path id="path320-3" inkscape:connector-curvature="0" class="st38" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g322-9" transform="translate(521.0053,272.3921)">
<path id="path324-0" inkscape:connector-curvature="0" class="st39" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g326-6" transform="translate(520.6887,271.6639)">
<path id="path328-6" inkscape:connector-curvature="0" class="st39" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g330-6" transform="translate(520.3721,270.9358)">
<path id="path332-4" inkscape:connector-curvature="0" class="st40" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g334-8" transform="translate(520.0239,270.2076)">
<path id="path336-8" inkscape:connector-curvature="0" class="st41" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g338-8" transform="translate(519.7073,269.4478)">
<path id="path340-5" inkscape:connector-curvature="0" class="st42" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g342-2" transform="translate(519.3591,268.7197)">
<path id="path344-6" inkscape:connector-curvature="0" class="st42" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g346-8" transform="translate(519.0425,267.9916)">
<path id="path348-1" inkscape:connector-curvature="0" class="st43" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g350-1" transform="translate(518.7259,267.2634)">
<path id="path352-0" inkscape:connector-curvature="0" class="st44" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g354-4" transform="translate(518.3777,266.5353)">
<path id="path356-3" inkscape:connector-curvature="0" class="st45" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g358-9" transform="translate(518.0611,265.8072)">
<path id="path360-7" inkscape:connector-curvature="0" class="st46" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g362-0" transform="translate(517.7128,265.0474)">
<path id="path364-8" inkscape:connector-curvature="0" class="st46" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g366-8" transform="translate(517.3962,264.3192)">
<path id="path368-0" inkscape:connector-curvature="0" class="st47" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g370-8" transform="translate(517.0797,263.5911)">
<path id="path372-5" inkscape:connector-curvature="0" class="st48" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g374-3" transform="translate(516.7314,262.8629)">
<path id="path376-0" inkscape:connector-curvature="0" class="st49" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g378-6" transform="translate(516.4149,262.1348)">
<path id="path380-0" inkscape:connector-curvature="0" class="st49" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g382-5" transform="translate(516.0666,261.4067)">
<path id="path384-4" inkscape:connector-curvature="0" class="st50" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g386-6" transform="translate(515.7501,260.6469)">
<path id="path388-9" inkscape:connector-curvature="0" class="st50" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g390-7" transform="translate(515.4334,259.9187)">
<path id="path392-4" inkscape:connector-curvature="0" class="st51" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g394-0" transform="translate(515.0852,259.1906)">
<path id="path396-8" inkscape:connector-curvature="0" class="st51" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g398-8" transform="translate(514.7686,258.4624)">
<path id="path400-2" inkscape:connector-curvature="0" class="st52" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g402-1" transform="translate(514.4204,257.7343)">
<path id="path404-8" inkscape:connector-curvature="0" class="st53" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g406-9" transform="translate(514.1038,257.0062)">
<path id="path408-6" inkscape:connector-curvature="0" class="st53" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g410-3" transform="translate(513.7872,256.2464)">
<path id="path412-7" inkscape:connector-curvature="0" class="st54" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g414-6" transform="translate(513.439,255.5182)">
<path id="path416-5" inkscape:connector-curvature="0" class="st54" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g418-0" transform="translate(513.1224,254.7901)">
<path id="path420-7" inkscape:connector-curvature="0" class="st55" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g422-3" transform="translate(512.7742,254.062)">
<path id="path424-0" inkscape:connector-curvature="0" class="st55" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g426-1" transform="translate(512.4576,253.3338)">
<path id="path428-9" inkscape:connector-curvature="0" class="st56" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g430-7" transform="translate(512.141,252.6057)">
<path id="path432-1" inkscape:connector-curvature="0" class="st56" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g434-0" transform="translate(511.7928,251.8459)">
<path id="path436-1" inkscape:connector-curvature="0" class="st57" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g438-5" transform="translate(511.4762,251.1177)">
<path id="path440-2" inkscape:connector-curvature="0" class="st57" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g442-4" transform="translate(511.1279,250.3896)">
<path id="path444-5" inkscape:connector-curvature="0" class="st58" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g446-2" transform="translate(510.8113,249.6615)">
<path id="path448-8" inkscape:connector-curvature="0" class="st59" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g450-9" transform="translate(510.4948,248.9333)">
<path id="path452-5" inkscape:connector-curvature="0" class="st60" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g454-6" transform="translate(510.1465,248.1735)">
<path id="path456-4" inkscape:connector-curvature="0" class="st61" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g458-3" transform="translate(509.83,247.4454)">
<path id="path460-3" inkscape:connector-curvature="0" class="st61" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g462-6" transform="translate(509.4817,246.7172)">
<path id="path464-6" inkscape:connector-curvature="0" class="st62" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g466-9" transform="translate(509.1651,245.9891)">
<path id="path468-2" inkscape:connector-curvature="0" class="st63" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g470-4" transform="translate(508.8485,245.261)">
<path id="path472-2" inkscape:connector-curvature="0" class="st64" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g474-0" transform="translate(508.5003,244.5328)">
<path id="path476-6" inkscape:connector-curvature="0" class="st64" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g478-4" transform="translate(508.1837,243.773)">
<path id="path480-3" inkscape:connector-curvature="0" class="st65" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g482-3" transform="translate(507.8355,243.0449)">
<path id="path484-2" inkscape:connector-curvature="0" class="st66" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g486-7" transform="translate(507.5189,242.3167)">
<path id="path488-5" inkscape:connector-curvature="0" class="st67" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g490-4" transform="translate(507.2023,241.5886)">
<path id="path492-5" inkscape:connector-curvature="0" class="st67" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g494-8" transform="translate(506.8541,240.8605)">
<path id="path496-1" inkscape:connector-curvature="0" class="st68" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g498-7" transform="translate(506.5375,240.1323)">
<path id="path500-7" inkscape:connector-curvature="0" class="st69" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g502-4" transform="translate(506.1892,239.3725)">
<path id="path504-8" inkscape:connector-curvature="0" class="st70" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g506-9" transform="translate(505.8727,238.6444)">
<path id="path508-9" inkscape:connector-curvature="0" class="st71" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g510-2" transform="translate(505.5561,237.9162)">
<path id="path512-0" inkscape:connector-curvature="0" class="st71" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g514-3" transform="translate(505.2079,237.1881)">
<path id="path516-1" inkscape:connector-curvature="0" class="st72" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g518-9" transform="translate(504.8913,236.46)">
<path id="path520-9" inkscape:connector-curvature="0" class="st72" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g522-1" transform="translate(504.543,235.7318)">
<path id="path524-1" inkscape:connector-curvature="0" class="st73" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g526-2" transform="translate(504.2264,234.972)">
<path id="path528-6" inkscape:connector-curvature="0" class="st73" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g530-2" transform="translate(503.9098,234.2439)">
<path id="path532-8" inkscape:connector-curvature="0" class="st74" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g534-9" transform="translate(503.5616,233.5157)">
<path id="path536-7" inkscape:connector-curvature="0" class="st74" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g538-6" transform="translate(503.245,232.7876)">
<path id="path540-9" inkscape:connector-curvature="0" class="st75" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g542-2" transform="translate(502.8968,232.0595)">
<path id="path544-4" inkscape:connector-curvature="0" class="st76" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g546-1" transform="translate(502.5802,231.3313)">
<path id="path548-6" inkscape:connector-curvature="0" class="st77" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g550-5" transform="translate(502.2636,230.5715)">
<path id="path552-3" inkscape:connector-curvature="0" class="st78" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g554-0" transform="translate(501.9154,229.8434)">
<path id="path556-4" inkscape:connector-curvature="0" class="st78" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g558-5" transform="translate(501.5988,229.1152)">
<path id="path560-1" inkscape:connector-curvature="0" class="st79" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g562-0" transform="translate(501.2506,228.3871)">
<path id="path564-8" inkscape:connector-curvature="0" class="st79" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g566-6" transform="translate(500.934,227.659)">
<path id="path568-1" inkscape:connector-curvature="0" class="st80" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g570-2" transform="translate(500.6174,226.9308)">
<path id="path572-6" inkscape:connector-curvature="0" class="st80" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g574-2" transform="translate(500.2691,226.171)">
<path id="path576-3" inkscape:connector-curvature="0" class="st81" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g578-5" transform="translate(499.9525,225.4429)">
<path id="path580-7" inkscape:connector-curvature="0" class="st82" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g582-4" transform="translate(499.6043,224.7148)">
<path id="path584-8" inkscape:connector-curvature="0" class="st83" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g586-3" transform="translate(499.2877,223.9866)">
<path id="path588-1" inkscape:connector-curvature="0" class="st83" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g590-8" transform="translate(498.9712,223.2585)">
<path id="path592-7" inkscape:connector-curvature="0" class="st84" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g594-0" transform="translate(498.6229,222.5303)">
<path id="path596-6" inkscape:connector-curvature="0" class="st85" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g598-2" transform="translate(498.3063,221.7705)">
<path id="path600-1" inkscape:connector-curvature="0" class="st86" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g602-3" transform="translate(497.9581,221.0424)">
<path id="path604-8" inkscape:connector-curvature="0" class="st87" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g606-4" transform="translate(497.6415,220.3142)">
<path id="path608-3" inkscape:connector-curvature="0" class="st87" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g610-1" transform="translate(497.3249,219.5861)">
<path id="path612-5" inkscape:connector-curvature="0" class="st88" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g614-5" transform="translate(496.9767,218.858)">
<path id="path616-9" inkscape:connector-curvature="0" class="st89" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g618-1" transform="translate(496.6601,218.1298)">
<path id="path620-6" inkscape:connector-curvature="0" class="st90" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g622-7" transform="translate(496.3119,217.37)">
<path id="path624-0" inkscape:connector-curvature="0" class="st90" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g626-0" transform="translate(495.9953,216.6419)">
<path id="path628-8" inkscape:connector-curvature="0" class="st91" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g630-1" transform="translate(495.6787,215.9137)">
<path id="path632-4" inkscape:connector-curvature="0" class="st91" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g634-1" transform="translate(495.3304,215.1856)">
<path id="path636-1" inkscape:connector-curvature="0" class="st92" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g638-3" transform="translate(495.0139,214.4575)">
<path id="path640-0" inkscape:connector-curvature="0" class="st92" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g642-7" transform="translate(494.6656,213.7293)">
<path id="path644-9" inkscape:connector-curvature="0" class="st93" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g646-2" transform="translate(494.3491,212.9695)">
<path id="path648-7" inkscape:connector-curvature="0" class="st94" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g650-3" transform="translate(494.0325,212.2414)">
<path id="path652-4" inkscape:connector-curvature="0" class="st94" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g654-1" transform="translate(493.6842,211.5132)">
<path id="path656-4" inkscape:connector-curvature="0" class="st95" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g658-3" transform="translate(493.3676,210.7851)">
<path id="path660-0" inkscape:connector-curvature="0" class="st95" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g662-6" transform="translate(493.0194,210.057)">
<path id="path664-1" inkscape:connector-curvature="0" class="st96" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g666-4" transform="translate(492.7028,209.3288)">
<path id="path668-5" inkscape:connector-curvature="0" class="st96" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g670-3" transform="translate(492.3863,208.569)">
<path id="path672-4" inkscape:connector-curvature="0" class="st97" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g674-2" transform="translate(492.038,207.8409)">
<path id="path676-1" inkscape:connector-curvature="0" class="st98" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g678-1" transform="translate(491.7214,207.1128)">
<path id="path680-4" inkscape:connector-curvature="0" class="st99" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g682-0" transform="translate(491.3732,206.3846)">
<path id="path684-5" inkscape:connector-curvature="0" class="st99" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g686-4" transform="translate(491.0566,205.6565)">
<path id="path688-8" inkscape:connector-curvature="0" class="st100" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g690-0" transform="translate(490.74,204.9283)">
<path id="path692-9" inkscape:connector-curvature="0" class="st101" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g694-6" transform="translate(490.3918,204.1685)">
<path id="path696-9" inkscape:connector-curvature="0" class="st102" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g698-5" transform="translate(490.0752,203.4404)">
<path id="path700-0" inkscape:connector-curvature="0" class="st103" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g702-5" transform="translate(489.727,202.7123)">
<path id="path704-6" inkscape:connector-curvature="0" class="st103" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g706-6" transform="translate(489.4104,201.9841)">
<path id="path708-7" inkscape:connector-curvature="0" class="st104" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g710-3" transform="translate(489.0938,201.256)">
<path id="path712-3" inkscape:connector-curvature="0" class="st105" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g714-8" transform="translate(488.7455,200.5278)">
<path id="path716-2" inkscape:connector-curvature="0" class="st106" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g718-4" transform="translate(488.429,199.768)">
<path id="path720-0" inkscape:connector-curvature="0" class="st106" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g722-1" transform="translate(488.0807,199.0399)">
<path id="path724-2" inkscape:connector-curvature="0" class="st107" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g726-2" transform="translate(487.7642,198.3118)">
<path id="path728-3" inkscape:connector-curvature="0" class="st107" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g730-1" transform="translate(487.4476,197.5836)">
<path id="path732-6" inkscape:connector-curvature="0" class="st108" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g734-7" transform="translate(487.0993,196.8555)">
<path id="path736-1" inkscape:connector-curvature="0" class="st108" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g738-4" transform="translate(486.7827,196.0957)">
<path id="path740-4" inkscape:connector-curvature="0" class="st109" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g742-0" transform="translate(486.4345,195.3675)">
<path id="path744-5" inkscape:connector-curvature="0" class="st110" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g746-8" transform="translate(486.1179,194.6394)">
<path id="path748-0" inkscape:connector-curvature="0" class="st111" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g750-0" transform="translate(485.8013,193.9113)">
<path id="path752-4" inkscape:connector-curvature="0" class="st112" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g754-8" transform="translate(485.4531,193.1831)">
<path id="path756-9" inkscape:connector-curvature="0" class="st112" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g758-2" transform="translate(485.1365,192.455)">
<path id="path760-3" inkscape:connector-curvature="0" class="st113" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g762-9" transform="translate(484.7883,191.6952)">
<path id="path764-3" inkscape:connector-curvature="0" class="st113" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g766-8" transform="translate(484.4717,190.967)">
<path id="path768-3" inkscape:connector-curvature="0" class="st114" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g770-5" transform="translate(484.1551,190.2389)">
<path id="path772-7" inkscape:connector-curvature="0" class="st114" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g774-2" transform="translate(483.8069,189.5108)">
<path id="path776-0" inkscape:connector-curvature="0" class="st115" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g778-5" transform="translate(483.4903,188.7826)">
<path id="path780-4" inkscape:connector-curvature="0" class="st115" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g782-9" transform="translate(483.1421,188.0545)">
<path id="path784-8" inkscape:connector-curvature="0" class="st116" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g786-2" transform="translate(482.8254,187.2947)">
<path id="path788-0" inkscape:connector-curvature="0" class="st116" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g790-4" transform="translate(482.5089,186.5666)">
<path id="path792-1" inkscape:connector-curvature="0" class="st117" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g794-1" transform="translate(482.1606,185.8384)">
<path id="path796-9" inkscape:connector-curvature="0" class="st117" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g798-8" transform="translate(481.844,185.1103)">
<path id="path800-2" inkscape:connector-curvature="0" class="st117" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g802-8" transform="translate(481.4958,184.3821)">
<path id="path804-8" inkscape:connector-curvature="0" class="st117" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g806-1" transform="translate(481.1792,183.654)">
<path id="path808-2" inkscape:connector-curvature="0" class="st117" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g810-7" transform="translate(480.8626,182.8942)">
<path id="path812-9" inkscape:connector-curvature="0" class="st118" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g814-2" transform="translate(480.5144,182.1661)">
<path id="path816-5" inkscape:connector-curvature="0" class="st118" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g818-6" transform="translate(480.1978,181.4379)">
<path id="path820-3" inkscape:connector-curvature="0" class="st118" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g822-7" transform="translate(479.8495,180.7098)">
<path id="path824-4" inkscape:connector-curvature="0" class="st118" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g826-7" transform="translate(479.533,179.9816)">
<path id="path828-6" inkscape:connector-curvature="0" class="st118" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g830-1" transform="translate(479.2164,179.2535)">
<path id="path832-2" inkscape:connector-curvature="0" class="st118" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g834-4" transform="translate(478.8682,178.4937)">
<path id="path836-0" inkscape:connector-curvature="0" class="st118" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g838-3" transform="translate(478.5516,177.7655)">
<path id="path840-2" inkscape:connector-curvature="0" class="st118" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g842-8" transform="translate(478.2033,177.0374)">
<path id="path844-0" inkscape:connector-curvature="0" class="st118" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g846-8" transform="translate(477.8867,176.3093)">
<path id="path848-4" inkscape:connector-curvature="0" class="st118" d="M-70.5,119.3l-0.5-1.1l-229.6,103.1l0.5,1.1"/>
</g>
<g id="g850-4" transform="translate(477.5702,175.5811)">
<path id="path852-3" inkscape:connector-curvature="0" class="st118" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g854-2" transform="translate(477.2219,174.853)">
<path id="path856-5" inkscape:connector-curvature="0" class="st118" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g858-5" transform="translate(476.9054,174.0932)">
<path id="path860-8" inkscape:connector-curvature="0" class="st118" d="M-70.5,119.3l-0.5-1.1l-229.6,103l0.5,1.1"/>
</g>
<g id="g862-5" transform="translate(476.5571,173.3651)">
<path id="path864-1" inkscape:connector-curvature="0" class="st119" d="M-70.5,119.3l-0.1-0.3l-229.6,103l0.1,0.3"/>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>
\ No newline at end of file
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title><%= htmlWebpackPlugin.options.title %></title>
<%= htmlWebpackPlugin.tags.headTags %>
</head>
<body>
<div id="root"></div>
<script src="https://kit.fontawesome.com/a68ff73b1b.js" crossOrigin="anonymous"></script>
</body>
</html>
const express = require('express')
const path = require('path')
const server = express()
server.use(express.static(path.join(__dirname, 'dist')))
server.get('*', (req, res) => {
res.sendFile(path.join(__dirname, 'dist', 'index.html'))
})
server.listen(3010, () => {
console.log('Listening at http://localhost:3010/')
})
#!/bin/node
const fs = require('fs') //Obtain the environment string passed to the node script
const environment = process.argv[2]
const envFileContent = require(`./config/${environment}.json`) //read the content of the json file
console.log(__dirname)
//copy the json inside the env.json file
fs.writeFileSync(`${__dirname}/public/config.json`, JSON.stringify(envFileContent, undefined, 2))
export const creditLines = Array.from(Array(8).keys()).map((n, i) => ({
id: i.toString(),
name: `Line ${i + 1}`,
amount: {
min: 100,
max: 9999,
},
paymentMonths: {
min: 6,
max: 36,
},
graceMonths: {
min: 4,
max: 24,
},
informations:
'Donec sit amet ante rutrum, tincidunt ante quis, semper tortor. Quisque feugiat dictum dictum. Duis scelerisque erat sollicitudin egestas pretium. Vivamus eget magna eu dui vestibulum hendrerit nec vel mi. Mauris et urna blandit, porttitor dui at, semper justo. Vestibulum elit enim, finibus in porta vitae, faucibus non lacus. Ut feugiat magna ipsum, eu scelerisque risus dignissim semper. In condimentum tortor sit amet hendrerit tempus. Cras sed ex a libero euismod aliquet.',
}))
export interface CreditLineData {
id: string
amount: number
graceMonths: number
paymentMonths: number
interestRate: number
effectiveTotalCost: number
openingCreditRate: number
}
export const creditLinesData: Record<string, CreditLineData> = Array.from(Array(8).keys()).reduce(
(cLs, cL, i) => ({
...cLs,
[i]: {
id: i.toString(),
amount: Math.random() * 1000,
graceMonths: Math.ceil(Math.random() * 10),
paymentMonths: Math.ceil(Math.random() * 10),
interestRate: Math.ceil(Math.random() * 10),
effectiveTotalCost: Number((Math.random() * 100).toFixed(2)),
openingCreditRate: Math.ceil(Math.random() * 1000),
},
}),
{}
)
import { getSessionManager } from '@agiliza/curio'
import { System as ApiSystem } from '../interfaces/System'
import { DYNAMO_TRANSITIONS } from '../useCases/transitions'
export interface SearchParams {
values: Record<string, any>
}
export function createMenuAPI() {
return {
fetchMenu: async function () {
const sessionManger = await getSessionManager()
const response = await sessionManger.session!.sendRequest(DYNAMO_TRANSITIONS.menu, {
Level: {
_: sessionManger.session!.module,
},
Version: {
_: sessionManger.session!.version,
},
})
return response.System as ApiSystem
},
}
}
export interface SolicitarRedefinicao {
_cpf: string
_email: string
_login: string
}
export interface VerificarCodigo {
_codigoAcesso: string
_OID: string
}
export interface RedefinirSenha {
_OID: string
_senha: string
_codigoAcesso: string
}
export interface MU {
_Type: 'MU'
_Name: string
_VIEW?: 'menu' // ? ver com Sandro se isso faz algum sentido sem ser menu
_UC: string // Use case
_OP: string // Operation
}
export interface MS {
_Type: 'MS'
_Name: string
_EN: string //Entity
Actions: MU[]
}
export interface MI {
_Type: 'MI'
_Name: string
Submenus: Menu[]
}
export type Menu = MS | MI | MU
export interface System {
_Name: string
Menus: Menu[]
}
import { Action } from 'redux'
import { of } from 'rxjs'
import { actions as errorActions } from '@agiliza/redux/ui/error'
import { getError } from '@agiliza/utils/method'
export function mapErrorToActions(response: Error, ...actions: ((error: string) => Action)[]) {
const error = getError(response)
return of(...actions.map((a) => a(error)), errorActions.setErrorMessage(error))
}
import * as error from './error'
export { error }
import { normalize, schema } from 'normalizr'
import { Menu as ApiMenu, System as ApiSystem } from '@agiliza/api/interfaces/System'
import { Menu, MI, MS, MU, SystemData, SystemEntities } from '@agiliza/redux/entities/system'
import { Operations } from '@dynamo/utils'
let currentId = 0
function mapOpApiToStore(operation: string): Operations {
switch (operation) {
case '1':
return 'create'
case '2':
return 'read'
case '3':
return 'update'
case '4':
return 'delete'
default:
return 'unknown'
}
}
function mapMenuApiToStore(menus: ApiMenu[]): Menu[] {
if (!menus) return []
const menuTree = menus.map((m) => {
if (m._Type === 'MI') {
return {
id: (++currentId).toString(),
name: m._Name,
type: 'MI',
submenus: mapMenuApiToStore(m.Submenus),
} as MI
} else if (m._Type === 'MS') {
return {
id: (++currentId).toString(),
name: m._Name,
entity: m._EN,
type: 'MS',
actions: mapMenuApiToStore(m.Actions),
} as MS
} else {
return {
id: (++currentId).toString(),
name: m._Name,
operation: mapOpApiToStore(m._OP),
type: 'MU',
useCase: m._UC,
view: m._VIEW,
} as MU
}
})
return menuTree
}
const muSchema = new schema.Entity('MU')
const msSchema = new schema.Entity('MS', { actions: [muSchema] })
const mapMenusToEntities = (menus: Menu[]) => {
const entities: SystemEntities = menus.reduce(
(acc, menu) => {
if (menu.type === 'MI') {
const ents = mapMenusToEntities(menu.submenus)
acc.MS = { ...acc.MS, ...ents.MS }
acc.MU = { ...acc.MU, ...ents.MU }
return acc
} else if (menu.type === 'MS') {
const { entities: ents }: { entities: SystemEntities } = normalize(menu, msSchema)
acc.MS = { ...acc.MS, ...ents.MS }
acc.MU = { ...acc.MU, ...ents.MU }
return acc
} else {
acc.MU[menu.id] = menu
return acc
}
},
{ MS: {}, MU: {} } as SystemEntities
)
return entities
}
export function mapSystemApiToStore(system?: ApiSystem): SystemData {
if (!system) return {}
const menus = mapMenuApiToStore(system.Menus)
const entities = mapMenusToEntities(menus)
currentId = 0
return {
system: {
name: system._Name,
menus,
},
entities,
}
}
import pMinDelay from 'p-min-delay'
import * as apiSession from './session'
type ApiSessionManager<A> = (...args: any[]) => Promise<A | void>
interface ApiMapObject<A> {
[key: string]: ApiSessionManager<A>
}
export const applyDelayToApi = <
A,
M extends ApiMapObject<A> | ApiSessionManager<A>
>(
apiMapObject: M,
ms = 600
): M =>
Object.entries(apiMapObject).reduce(
(acc, [k, v]: [string, ApiSessionManager<any>]) => ({
...acc,
[k]: (...args: any[]) => pMinDelay(v(...args), ms)
}),
{} as M
)
export const session = applyDelayToApi(apiSession)
import { getSessionManager } from '@agiliza/curio'
import { createMenuAPI } from '../dynamo'
// import { createMenuAPI } from '../dynamo'
// import { SolicitarRedefinicao, VerificarCodigo, RedefinirSenha } from '../interfaces/Login'
// const ucRecuperarSenha = {
// id: '3522',
// SOLICITAR_REDEFINICAO: 'RM_SOLICITAR_REDEFINICAO',
// VERIFICAR_CODIGO: 'RM_VERIFICAR_CODIGO',
// DEFIINIR_SENHA: 'RM_DEFINIR_SENHA'
// }
interface LoginParams {
username: string
password: string
}
export const initialize = async () => {
await getSessionManager()
}
export const login = async ({ username, password }: LoginParams) => {
const sessionManager = await getSessionManager()
return sessionManager.openMainUseCase(username, password)
}
export const logout = async () => {
const sessionManager = await getSessionManager()
sessionManager?.session?.abort()
}
export const { fetchMenu } = createMenuAPI()
// export const solicitarRedefinicao = async (funcionario: SolicitarRedefinicao) => {
// const mainUseCase = await sessionManager.anonymousConnection()
// const uc = await mainUseCase.openUseCase(ucRecuperarSenha.id)
// const response = await uc.sendRequest(ucRecuperarSenha.SOLICITAR_REDEFINICAO, {
// Funcionario: funcionario
// })
// await uc.abort()
// return response.Funcionario as Funcionario
// }
// const enviarCodigoSenha = async (envCodigo: VerificarCodigo) => {
// const { _codigoAcesso, _OID } = envCodigo
// const mainUseCase = await sessionManager.anonymousConnection()
// const uc = await mainUseCase.openUseCase(ucRecuperarSenha.id)
// const response = await uc.sendRequest(ucRecuperarSenha.VERIFICAR_CODIGO, {
// Funcionario: { _codigoAcesso, _OID }
// })
// await uc.abort()
// return response.Funcionario as Funcionario
// }
// const redefinirSenha = async (redefSenha: RedefinirSenha) => {
// const { _OID, _senha, _codigoAcesso } = redefSenha
// const mainUseCase = await sessionManager.anonymousConnection()
// const uc = await mainUseCase.openUseCase(ucRecuperarSenha.id)
// const response = await uc.sendRequest(ucRecuperarSenha.DEFIINIR_SENHA, {
// Funcionario: { _senha, _OID, _codigoAcesso }
// })
// await uc.abort()
// return response.Funcionario as Funcionario
// }
// export const useCaseRecuperarSenha = {
// solicitarRedefinicao,
// enviarCodigoSenha,
// redefinirSenha
// }
import { Operations } from '@dynamo/utils'
export const DYNAMO_ENTITIES = {
TermsOfAcceptance: '1',
Profile: '5',
User: '6',
}
export const DYNAMO_TRANSITIONS = {
menu: '116',
presentation: '134',
search: '120',
} as const
export type DynamoMetadata = {
[key in Operations]?: string
} & { useCase: number; fetch: string }
export const USER_METADATA = {
useCase: 101,
save: 'RM_SALVA_OBJETO',
getContext: 'RM_OBTEM_CONTEXTO',
createObject: 'RM_INCLUI_OBJETO',
editObject: 'RM_EDITA_OBJETO',
disable: 'RM_EXCLUI_OBJETO',
} as const
export const PROFILE_METADATA = {
useCase: 1963,
save: 'RM_SALVA_OBJETO',
getContext: 'RM_OBTEM_CONTEXTO',
createObject: 'RM_INCLUI_OBJETO',
editObject: 'RM_EDITA_OBJETO',
deleteObject: 'RM_EXCLUI_OBJETO',
// getTransitions: 'RM_GET_TRIGGERS_FROM_CURRENT_STATE',
} as const
import React from 'react'
import { connect } from 'react-redux'
import { Redirect, Route, RouteProps } from 'react-router'
import { StoreState } from '@agiliza/redux'
import { isAuthenticated } from '@agiliza/redux/session/selectors'
interface Props extends RouteProps {
authenticated: boolean
}
function AuthRoute({ authenticated, ...props }: Props) {
return authenticated ? <Route {...props} /> : <Redirect to="/login" />
}
const mapStateToProps = (state: StoreState) => ({
authenticated: isAuthenticated(state.session),
})
export default connect(mapStateToProps)(AuthRoute)
import React from 'react'
import { Button, LinearProgress } from '@material-ui/core'
import { ButtonProps } from '@material-ui/core/Button'
import { withStyles, WithStyles } from '@material-ui/core/styles'
import { styles } from './styles'
type ExtendedTypes = WithStyles<typeof styles> &
Pick<ButtonProps, 'disabled' | 'onClick' | 'type' | 'children' | 'className' | 'color'>
interface Props extends ExtendedTypes {
fetching?: boolean
}
const ButtonWithProgress = (props: Props) => {
const { className, classes, fetching, disabled, onClick, type, children, color = 'primary' } = props
return (
<Button
className={className}
disabled={disabled || fetching}
onClick={onClick}
variant="contained"
color={color}
type={type}
>
{fetching && <LinearProgress className={classes.progress} />}
{children}
</Button>
)
}
export default withStyles(styles)(ButtonWithProgress)
export { default } from './ButtonWithProgress'
export * from './ButtonWithProgress'
import { Theme, createStyles } from '@material-ui/core/styles'
export const styles = (theme: Theme) => {
return createStyles({
progress: {
bottom: 0,
margin: 0,
width: '100%',
position: 'absolute'
}
})
}
import React from 'react'
import ListItem from '@material-ui/core/ListItem'
import ListItemIcon from '@material-ui/core/ListItemIcon'
import ListItemText from '@material-ui/core/ListItemText'
interface Props {
label: string
className?: string
children: React.ReactElement
onClick?: () => void
}
const ItemWithIcon = (props: Props) => {
const { className, label, children, onClick } = props
return (
<ListItem button className={className} onClick={onClick}>
<ListItemIcon>{children}</ListItemIcon>
<ListItemText primary={label} />
</ListItem>
)
}
export default ItemWithIcon
export { default } from './ItemWithIcon'
export * from './ItemWithIcon'
import React, { useState } from 'react'
import InputAdornment from '@material-ui/core/InputAdornment'
import TextField, { TextFieldProps } from '@material-ui/core/TextField'
import Visibility from '@material-ui/icons/Visibility'
import VisibilityOff from '@material-ui/icons/VisibilityOff'
import withStyles, { WithStyles } from '@material-ui/styles/withStyles'
import styles from './styles'
type BaseProps = WithStyles<typeof styles> &
Pick<TextFieldProps, 'value' | 'onChange' | 'required' | 'label' | 'type' | 'className' | 'InputProps' | 'autoFocus'>
interface Props extends BaseProps {}
const TextFieldWithIcon = (props: Props) => {
const [isPasswordVisible, setIsPasswordVisible] = useState(false)
const { onChange, required, value, label, type, className, InputProps, classes, autoFocus } = props
return (
<TextField
autoFocus={autoFocus}
required={required}
value={value}
onChange={onChange}
label={label}
className={className}
variant="outlined"
type={type === 'password' ? (isPasswordVisible ? undefined : type) : type}
InputProps={
InputProps || {
startAdornment:
type === 'password' ? (
<InputAdornment
position="start"
onClick={() => setIsPasswordVisible(!isPasswordVisible)}
className={classes.inputAdorment}
>
{isPasswordVisible ? <Visibility /> : <VisibilityOff />}
</InputAdornment>
) : null,
}
}
/>
)
}
export default withStyles(styles)(TextFieldWithIcon)
export { default } from './TextFieldWithIcon'
export * from './TextFieldWithIcon'
import { createStyles, Theme } from '@material-ui/core/styles'
export default (theme: Theme) =>
createStyles({
inputAdorment: {
cursor: 'pointer'
}
})
import React from 'react'
import MuiToolbar from '@material-ui/core/Toolbar'
import { useStyles } from './styles'
export interface ToolbarProps {
title?: React.ReactNode
actions?: React.ReactNode
nav?: React.ReactNode
}
export function Toolbar({ nav, title, actions }: ToolbarProps) {
const classes = useStyles()
return (
<MuiToolbar>
<div className={classes.nav}>{nav}</div>
{title ? <div className={classes.grow}>{title}</div> : <div className={classes.grow} />}
{actions}
</MuiToolbar>
)
}
import cn from 'classnames'
import React, { useState } from 'react'
import { Collapse, CollapseProps, Fade } from '@material-ui/core'
import MuiAppBar, { AppBarProps as MuiAppBarProps } from '@material-ui/core/AppBar'
import IconButton from '@material-ui/core/IconButton'
import { createStyles, makeStyles, Theme } from '@material-ui/core/styles'
import { Menu as DrawerIcon } from '@material-ui/icons'
import { Toolbar, ToolbarProps } from './Toolbar'
const useStyles = makeStyles((theme: Theme) =>
createStyles({
appBar: {
// position: 'fixed',
...theme.mixins.toolbar,
background: `linear-gradient(60deg, ${theme.palette.primary.main}, ${theme.palette.primary.light})`,
},
content: {
...theme.mixins.toolbar,
display: 'flex',
alignItems: 'center',
width: '100%',
},
})
)
type BaseType = Omit<ToolbarProps, 'classes' | 'nav'>
export interface AppBarProps extends BaseType {
className?: string
position?: MuiAppBarProps['position']
children?: React.ReactNode
onNavClick?(event: React.MouseEvent<HTMLButtonElement, MouseEvent>): void
style?: MuiAppBarProps['style']
}
const AppBar = ({ className, position = 'static', actions, title, children, onNavClick, style }: AppBarProps) => {
const classes = useStyles()
const [fadeIn, setFadeIn] = useState(false)
const onCollapse: CollapseProps['onEntered'] = (el, isAppearing) => {
setFadeIn(isAppearing)
}
const nav = onNavClick ? (
<IconButton color="inherit" onClick={onNavClick}>
<DrawerIcon />
</IconButton>
) : null
return (
<>
<MuiAppBar className={cn(classes.appBar, className)} position={position} style={style}>
<Toolbar title={title} actions={actions} nav={nav} />
{children && (
<Collapse appear enter in onEntered={onCollapse} timeout={400}>
<div>
<Fade in={fadeIn} enter timeout={600}>
<div className={classes.content}>{children}</div>
</Fade>
</div>
</Collapse>
)}
</MuiAppBar>
</>
)
}
export default AppBar
import { createStyles, makeStyles, Theme } from '@material-ui/core/styles'
export const useStyles = makeStyles((theme: Theme) =>
createStyles({
grow: {
flexGrow: 1,
},
nav: {
marginRight: theme.spacing(2),
},
})
)
import cn from 'classnames'
import React from 'react'
import CircularProgressMUI from '@material-ui/core/CircularProgress'
import Container from '@material-ui/core/Container'
import { useStyles } from './styles'
interface Props {
className?: string
root?: boolean
}
const CircularProgress = (props: Props) => {
const classes = useStyles()
return (
<Container
className={cn(classes.container, { [classes.allContainer]: props.root })}
>
<CircularProgressMUI className={props.className} color="secondary" />
</Container>
)
}
export default CircularProgress
export { default } from './CircularProgress'
export * from './CircularProgress'
import { createStyles, makeStyles, Theme } from '@material-ui/core/styles'
export const useStyles = makeStyles((theme: Theme) =>
createStyles({
container: {
display: 'flex',
flex: 1,
justifyContent: 'center',
alignItems: 'center'
},
allContainer: {
height: '100vh'
}
})
)
import React from 'react'
import IconButton from '@material-ui/core/IconButton'
import ListItemText from '@material-ui/core/ListItemText'
import Menu from '@material-ui/core/Menu'
import MenuItem from '@material-ui/core/MenuItem'
import { MoreVert as ContextIconVertical } from '@material-ui/icons'
export interface ContextItem {
icon?: React.ReactElement
label?: React.ReactNode
onClick?(event: React.MouseEvent<HTMLLIElement, MouseEvent>): void
}
export interface ContextButtonProps {
disabled?: boolean
menuId: string
className?: string
menuClassName?: string
icon?: React.ReactElement
menuItems: ContextItem[]
}
export default function ContextButton({ menuId, disabled, menuItems, className, menuClassName }: ContextButtonProps) {
const [anchorEl, setAnchorEl] = React.useState<HTMLButtonElement>(null!)
function handleClick(event: React.MouseEvent<HTMLButtonElement, MouseEvent>) {
setAnchorEl(event.currentTarget)
}
function handleClose() {
setAnchorEl(null!)
}
function handleItemClick(event: React.MouseEvent<HTMLLIElement, MouseEvent>, item: ContextItem) {
handleClose()
item.onClick && item.onClick(event)
}
return (
<>
<IconButton
disabled={disabled}
className={className}
aria-controls={menuId}
aria-haspopup="true"
onClick={handleClick}
>
<ContextIconVertical />
</IconButton>
<Menu
id={menuId}
anchorEl={anchorEl}
keepMounted
open={Boolean(anchorEl)}
onClose={handleClose}
className={menuClassName}
>
{menuItems.map((item, index) => (
<MenuItem key={index} onClick={(e) => handleItemClick(e, item)}>
{/* <ListItemIcon>{item.icon}</ListItemIcon> */}
<ListItemText primary={item.label} />
</MenuItem>
))}
</Menu>
</>
)
}
export { default } from './ContextButton'
export * from './ContextButton'
import React from 'react'
// import AppBar from '@material-ui/core/AppBar'
import AppBar from '@agiliza/components/molecules/AppBar'
import { IconButton } from '@material-ui/core'
import Dialog from '@material-ui/core/Dialog'
import DialogActions from '@material-ui/core/DialogActions'
// import Toolbar from '@material-ui/core/Toolbar'
// import IconButton from '@material-ui/core/IconButton'
import DialogContent from '@material-ui/core/DialogContent'
import DialogTitle from '@material-ui/core/DialogTitle'
import Slide from '@material-ui/core/Slide'
import { TransitionProps } from '@material-ui/core/transitions/transition'
import CloseIcon from '@material-ui/icons/Close'
import type { DialogProps } from '@material-ui/core/Dialog'
const Transition = React.forwardRef(function Transition(
props: TransitionProps & { children?: React.ReactElement<any, any> },
ref: React.Ref<unknown>
) {
return <Slide timeout={600} direction="left" ref={ref} {...props} />
})
type BaseProps = Pick<DialogProps, 'open' | 'fullScreen' | 'className' | 'maxWidth' | 'PaperProps'>
interface Props extends BaseProps {
onClose?(): void
children: React.ReactNode
actions?: React.ReactNode
title: React.ReactNode
contentClassName?: string
}
const DialogLayout = (props: Props) => {
const { open, onClose, fullScreen, children, actions, title, contentClassName, className, maxWidth, PaperProps } = props
return (
<Dialog
fullScreen={fullScreen}
open={open}
onClose={onClose}
className={className}
PaperProps={PaperProps}
TransitionComponent={Transition}
maxWidth={maxWidth}
>
{fullScreen ? (
<AppBar
title={title}
actions={
<IconButton edge="start" color="inherit" onClick={onClose} aria-label="close">
<CloseIcon />
</IconButton>
}
/>
) : null}
{!fullScreen ? <DialogTitle>{title}</DialogTitle> : null}
<DialogContent className={contentClassName}>{children}</DialogContent>
{!fullScreen ? <DialogActions>{actions}</DialogActions> : null}
</Dialog>
)
}
export default DialogLayout
export { default } from './DialogLayout'
export * from './DialogLayout'
import { Theme, createStyles } from '@material-ui/core/styles'
export const styles = (theme: Theme) =>
createStyles({
appBar: { position: 'relative' },
title: {
marginLeft: theme.spacing(2),
flex: 1
}
})
import cn from 'classnames'
import React from 'react'
import { RouteComponentProps } from 'react-router'
import logo from '@agiliza/public/images/logo.svg'
import { actions as sessionActions } from '@agiliza/redux/session'
import Divider from '@material-ui/core/Divider'
import MUIDrawer from '@material-ui/core/Drawer'
import { useStyles } from './styles'
type ExtendedTypes = RouteComponentProps
interface DrawerItemsProps extends ExtendedTypes {
listItemClassName?: string
toggleDrawer: () => void
logout: Props['logout']
}
type BaseProps = RouteComponentProps
export interface Props extends BaseProps {
drawerOpen: boolean
toggleDrawer: () => void
logout: typeof sessionActions.logout
Items?: React.ComponentType<DrawerItemsProps>
}
const Drawer = (props: Props) => {
const { drawerOpen, toggleDrawer, Items, logout, ...routeProps } = props
const classes = useStyles()
return (
<MUIDrawer
variant="temporary"
open={drawerOpen}
className={cn(classes.drawer, {
[classes.drawerOpen]: drawerOpen,
[classes.drawerClose]: !drawerOpen,
})}
classes={{
paper: cn(classes.drawer, {
[classes.drawerOpen]: drawerOpen,
[classes.drawerClose]: !drawerOpen,
}),
}}
onBackdropClick={() => toggleDrawer()}
>
<div className={classes.header}>
<img src={logo} className={classes.headerLogo} alt="Camedics Logo" />
</div>
<Divider />
{Items ? <Items logout={logout} listItemClassName={classes.listItem} toggleDrawer={toggleDrawer} {...routeProps} /> : null}
{/* <DrawerItems listItemClassName={classes.listItem} toggleDrawer={toggleDrawer} {...routerProps} /> */}
{/* <div className={classes.grow} /> */}
{/* <Divider /> */}
{/* <div className={cn(classes.collapseContainer)} onClick={() => toggleDrawer()}>
<Typography className={classes.iconLabel} variant="h5">
<DoubleArrowIcon fontSize="large" className={cn({ [style.arrowIconOpened]: drawerOpen })} />
{drawerOpen ? 'Colapsar' : null}
</Typography>
</div> */}
</MUIDrawer>
)
}
export default Drawer
export { default } from './Drawer'
export * from './Drawer'
import { drawerWidth, toolbarHeight } from '@agiliza/constants/styles'
import { createStyles, makeStyles, Theme } from '@material-ui/core/styles'
export const useStyles = makeStyles((theme: Theme) => {
const drawerClosedWidth = theme.spacing(0)
const hover = '&:hover'
return createStyles({
grow: {
flexGrow: 1,
},
collapseContainer: {
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
cursor: 'pointer',
[hover]: { backgroundColor: 'white' },
},
title: {
textDecoration: 'none',
color: 'inherit',
},
container: {
backgroundColor: 'white',
height: '100vh',
overflowY: 'hidden',
display: 'flex',
flexDirection: 'column',
},
contentContainer: {
marginLeft: drawerClosedWidth,
flexDirection: 'column',
paddingBottom: theme.spacing(3),
paddingLeft: 0,
width: `calc(100% - ${drawerClosedWidth}px)`,
maxHeight: `calc(100vh - ${toolbarHeight}px)`,
height: `calc(100vh - ${toolbarHeight}px)`,
},
drawer: {
position: 'fixed',
height: '100%',
// top: toolbarHeight,
// backgroundColor: '#fafafa',
zIndex: 5,
width: drawerClosedWidth,
transition: theme.transitions.create('width', {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.enteringScreen,
}),
},
drawerOpen: {
width: drawerWidth,
transition: theme.transitions.create('width', {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.enteringScreen,
}),
overflowX: 'hidden',
},
iconLabel: {
display: 'flex',
alignItems: 'center',
margin: '5px 0px',
},
drawerClose: {
transition: theme.transitions.create('width', {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen,
}),
overflowX: 'hidden',
width: drawerClosedWidth,
[theme.breakpoints.up('sm')]: {
width: drawerClosedWidth,
},
},
listItem: {
overflowX: 'hidden',
width: drawerWidth,
paddingLeft: theme.spacing(1.5),
},
header: {
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
paddingTop: theme.spacing(1),
paddingBottom: theme.spacing(2),
height: 102,
},
headerLogo: { width: 100, height: 'auto' },
})
})
import React, { useEffect, useState } from 'react'
import { connect } from 'react-redux'
import { bindActionCreators, Dispatch } from 'redux'
import { StoreState } from '@agiliza/redux'
import { actions as errorActions, selectors, State as ErrorState } from '@agiliza/redux/ui/error'
import Button from '@material-ui/core/Button'
import Dialog from '@material-ui/core/Dialog'
import DialogActions from '@material-ui/core/DialogActions'
import DialogContent from '@material-ui/core/DialogContent'
import DialogContentText from '@material-ui/core/DialogContentText'
import DialogTitle from '@material-ui/core/DialogTitle'
import { withStyles } from '@material-ui/styles'
import { styles } from './styles'
interface Props {
error: ErrorState['error']
setError: typeof errorActions.setErrorMessage
}
const ErrorDialog = (props: Props) => {
const { error, setError } = props
const [visible, setVisible] = useState(false)
useEffect(() => {
if (error) setVisible(true)
}, [props.error])
const handleClose = () => {
setVisible(false)
setTimeout(() => {
setError('')
}, 200)
}
return (
<Dialog open={visible} onClose={handleClose} aria-labelledby="error-dialog" aria-describedby="error-dialog-description">
<DialogTitle id="error-dialog-title">Erro</DialogTitle>
<DialogContent>
<DialogContentText>{error}</DialogContentText>
</DialogContent>
<DialogActions>
<Button onClick={handleClose} color="primary">
FECHAR
</Button>
</DialogActions>
</Dialog>
)
}
const mapStateToProps = (state: StoreState) => ({
error: selectors.getError(state.ui.error),
})
const mapDispatchToProps = (dispatch: Dispatch) =>
bindActionCreators(
{
setError: errorActions.setErrorMessage,
},
dispatch
)
export default connect(mapStateToProps, mapDispatchToProps)(withStyles(styles)(ErrorDialog))
export { default } from './ErrorDialog'
export * from './ErrorDialog'
import { Theme, createStyles } from '@material-ui/core/styles'
export const styles = (theme: Theme) => createStyles({})
import React, { useEffect, useState } from 'react'
import { ConfigService } from '@agiliza/curio/SessionManager'
import Popover from '@material-ui/core/Popover'
import Typography from '@material-ui/core/Typography'
import InfoIcon from '@material-ui/icons/InfoRounded'
import { WithStyles, withStyles } from '@material-ui/styles'
import { styles } from './styles'
interface Props extends WithStyles<typeof styles> {
service?: ConfigService
}
interface PopItem {
key: string
value?: string | number
underline?: boolean
}
const PopoverVersion = (props: Props) => {
const { classes, service } = props
const [popItems, setPopItems] = useState<PopItem[]>([])
const [anchor, setAnchor] = useState<HTMLDivElement | null>(null)
useEffect(() => {
let items: PopItem[] = [{ key: 'Versão', value: VERSION }]
if (service) {
items = items.concat(
{ key: 'ISAPI', value: service?.url, underline: true },
{ key: 'Serviço', value: service?.server },
{ key: 'Porta', value: service?.port },
{ key: 'Sistema', value: service?.system }
)
}
setPopItems(items)
}, [service])
const createPopItems = (items: PopItem[]) =>
items.map((item, i) => (
<Typography className={classes.msg} color="textPrimary" key={i}>
{`${item.key}: `}
{<span style={{ textDecoration: item.underline ? 'underline' : undefined }}>{item.value || ''}</span>}
</Typography>
))
return (
<div className={classes.root}>
<div onClick={(evt) => setAnchor(evt.currentTarget)}>
<InfoIcon className={classes.infoBtn} color="primary" />
</div>
<Popover
id="version-popover"
open={!!anchor}
anchorEl={anchor}
onClose={() => setAnchor(null)}
anchorOrigin={{
vertical: 'top',
horizontal: 'left',
}}
transformOrigin={{
vertical: 'bottom',
horizontal: 'right',
}}
>
<div className={classes.popoverContent}>{createPopItems(popItems)}</div>
</Popover>
</div>
)
}
export default withStyles(styles)(PopoverVersion)
export { default } from './PopoverVersion'
export * from './PopoverVersion'
import { createStyles, Theme } from '@material-ui/core/styles'
export const styles = (theme: Theme) =>
createStyles({
root: { position: 'fixed', bottom: theme.spacing(5), right: theme.spacing(5) },
popoverContent: { padding: theme.spacing(1.5) },
msg: {
fontWeight: 'bold',
fontSize: '100%',
overflowWrap: 'normal',
// fontFamily: '"Permanent Marker", cursive'
},
infoBtn: { fontSize: 50, cursor: 'pointer' },
})
import React from 'react'
import { SvgIcon } from '@material-ui/core'
interface Props {}
export function BellIcon(props: Props) {
return (
<SvgIcon
{...props}
style={{
width: 21,
height: 21,
}}
viewBox="0 0 21 21"
>
<svg
aria-hidden="true"
focusable="false"
data-prefix="fas"
data-icon="bell"
className="svg-inline--fa fa-bell fa-w-14"
role="img"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 448 512"
>
<path
fill="currentColor"
d="M224 512c35.32 0 63.97-28.65 63.97-64H160.03c0 35.35 28.65 64 63.97 64zm215.39-149.71c-19.32-20.76-55.47-51.99-55.47-154.29 0-77.7-54.48-139.9-127.94-155.16V32c0-17.67-14.32-32-31.98-32s-31.98 14.33-31.98 32v20.84C118.56 68.1 64.08 130.3 64.08 208c0 102.3-36.15 133.53-55.47 154.29-6 6.45-8.66 14.16-8.61 21.71.11 16.4 12.98 32 32.1 32h383.8c19.12 0 32-15.6 32.1-32 .05-7.55-2.61-15.27-8.61-21.71z"
></path>
</svg>
</SvgIcon>
)
}
import React from 'react'
import SvgIcon, { SvgIconProps } from '@material-ui/core/SvgIcon'
interface Props extends SvgIconProps {}
export default (props: Props) => {
return (
<SvgIcon
{...props}
style={{
width: 24,
height: 24,
}}
viewBox="0 0 24 24"
>
<path
fill="currentColor"
d="M12,1L3,5V11C3,16.55 6.84,21.74 12,23C17.16,21.74 21,16.55 21,11V5L12,1M12,5A3,3 0 0,1 15,8A3,3 0 0,1 12,11A3,3 0 0,1 9,8A3,3 0 0,1 12,5M17.13,17C15.92,18.85 14.11,20.24 12,20.92C9.89,20.24 8.08,18.85 6.87,17C6.53,16.5 6.24,16 6,15.47C6,13.82 8.71,12.47 12,12.47C15.29,12.47 18,13.79 18,15.47C17.76,16 17.47,16.5 17.13,17Z"
/>
</SvgIcon>
)
}
import React from 'react'
import SvgIcon, { SvgIconProps } from '@material-ui/core/SvgIcon'
interface Props extends SvgIconProps {}
export default (props: Props) => {
return (
<SvgIcon
{...props}
style={{
width: 21,
height: 21,
}}
viewBox="0 0 21 21"
>
<svg
aria-hidden="true"
focusable="false"
data-prefix="far"
data-icon="share-square"
className="svg-inline--fa fa-share-square fa-w-18"
role="img"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 576 512"
>
<path
fill="currentColor"
d="M561.938 158.06L417.94 14.092C387.926-15.922 336 5.097 336 48.032v57.198c-42.45 1.88-84.03 6.55-120.76 17.99-35.17 10.95-63.07 27.58-82.91 49.42C108.22 199.2 96 232.6 96 271.94c0 61.697 33.178 112.455 84.87 144.76 37.546 23.508 85.248-12.651 71.02-55.74-15.515-47.119-17.156-70.923 84.11-78.76V336c0 42.993 51.968 63.913 81.94 33.94l143.998-144c18.75-18.74 18.75-49.14 0-67.88zM384 336V232.16C255.309 234.082 166.492 255.35 206.31 376 176.79 357.55 144 324.08 144 271.94c0-109.334 129.14-118.947 240-119.85V48l144 144-144 144zm24.74 84.493a82.658 82.658 0 0 0 20.974-9.303c7.976-4.952 18.286.826 18.286 10.214V464c0 26.51-21.49 48-48 48H48c-26.51 0-48-21.49-48-48V112c0-26.51 21.49-48 48-48h132c6.627 0 12 5.373 12 12v4.486c0 4.917-2.987 9.369-7.569 11.152-13.702 5.331-26.396 11.537-38.05 18.585a12.138 12.138 0 0 1-6.28 1.777H54a6 6 0 0 0-6 6v340a6 6 0 0 0 6 6h340a6 6 0 0 0 6-6v-25.966c0-5.37 3.579-10.059 8.74-11.541z"
></path>
</svg>
</SvgIcon>
)
}
import React from 'react'
import SvgIcon, { SvgIconProps } from '@material-ui/core/SvgIcon'
interface Props extends SvgIconProps {}
export default (props: Props) => {
return (
<SvgIcon {...props} viewBox="0 0 24 24">
<path
fill="currentColor"
d="M6,2C4.89,2 4,2.89 4,4V20A2,2 0 0,0 6,22H10V20.09L12.09,18H6V16H14.09L16.09,14H6V12H18.09L20,10.09V8L14,2H6M13,3.5L18.5,9H13V3.5M20.15,13C20,13 19.86,13.05 19.75,13.16L18.73,14.18L20.82,16.26L21.84,15.25C22.05,15.03 22.05,14.67 21.84,14.46L20.54,13.16C20.43,13.05 20.29,13 20.15,13M18.14,14.77L12,20.92V23H14.08L20.23,16.85L18.14,14.77Z"
/>
</SvgIcon>
)
}
import React from 'react'
import SvgIcon, { SvgIconProps } from '@material-ui/core/SvgIcon'
interface Props extends SvgIconProps {}
export default (props: Props) => {
return (
<SvgIcon
{...props}
style={{
width: 21,
height: 21
}}
viewBox="0 0 21 21"
>
<svg
aria-hidden="true"
focusable="false"
data-prefix="fas"
data-icon="file-upload"
className="svg-inline--fa fa-file-upload fa-w-12"
role="img"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 384 512"
>
<path
fill="currentColor"
d="M224 136V0H24C10.7 0 0 10.7 0 24v464c0 13.3 10.7 24 24 24h336c13.3 0 24-10.7 24-24V160H248c-13.2 0-24-10.8-24-24zm65.18 216.01H224v80c0 8.84-7.16 16-16 16h-32c-8.84 0-16-7.16-16-16v-80H94.82c-14.28 0-21.41-17.29-11.27-27.36l96.42-95.7c6.65-6.61 17.39-6.61 24.04 0l96.42 95.7c10.15 10.07 3.03 27.36-11.25 27.36zM377 105L279.1 7c-4.5-4.5-10.6-7-17-7H256v128h128v-6.1c0-6.3-2.5-12.4-7-16.9z"
></path>
</svg>
</SvgIcon>
)
}
import React from 'react'
import SvgIcon, { SvgIconProps } from '@material-ui/core/SvgIcon'
interface Props extends SvgIconProps {}
export default (props: Props) => {
return (
<SvgIcon
{...props}
style={{
width: 21,
height: 21
}}
viewBox="0 0 21 21"
>
<svg
aria-hidden="true"
focusable="false"
data-prefix="fas"
data-icon="vial"
className="svg-inline--fa fa-vial fa-w-15"
role="img"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 480 512"
>
<path
fill="currentColor"
d="M477.7 186.1L309.5 18.3c-3.1-3.1-8.2-3.1-11.3 0l-34 33.9c-3.1 3.1-3.1 8.2 0 11.3l11.2 11.1L33 316.5c-38.8 38.7-45.1 102-9.4 143.5 20.6 24 49.5 36 78.4 35.9 26.4 0 52.8-10 72.9-30.1l246.3-245.7 11.2 11.1c3.1 3.1 8.2 3.1 11.3 0l34-33.9c3.1-3 3.1-8.1 0-11.2zM318 256H161l148-147.7 78.5 78.3L318 256z"
/>
</svg>
</SvgIcon>
)
}
export { BellIcon as NotificationIcon } from './BellIcon'
export * from './TermIcon'
import React from 'react'
import { RouteComponentProps } from 'react-router-dom'
import { Typography } from '@material-ui/core'
import { createStyles, Theme } from '@material-ui/core/styles'
import { withStyles, WithStyles } from '@material-ui/styles'
const styles = (theme: Theme) =>
createStyles({
container: {
paddingLeft: theme.spacing(2),
},
messageBox: {
paddingTop: theme.spacing(4),
},
})
type Props = WithStyles<typeof styles> & RouteComponentProps
interface NotFoundProps extends Props {}
function NotFound({ classes }: NotFoundProps) {
return (
<div className={classes.container}>
<Typography variant="h3">404: Página não encontrada</Typography>
<div className={classes.messageBox}>
<Typography variant="h5">A página pela qual você procurou não existe.</Typography>
</div>
</div>
)
}
export default /*#__PURE__*/ withStyles(styles)(NotFound)
export { default } from './NotFound'
export * from './NotFound'
import Bowser from 'bowser'
export const SUPPORTED_BROWSERS = {
// Material-ui compatibility https://material-ui.com/getting-started/supported-platforms/
windows: {
// 'internet explorer': '>=11',
edge: ">=14",
},
macos: {
safari: ">=10",
},
mobile: {
safari: ">=10",
},
chrome: ">=49",
firefox: ">=52",
};
export const browser = Bowser.getParser(window.navigator.userAgent);
import { PresenterModel } from '@dynamo/utils'
export const defaultPresenter: PresenterModel = {
definition: {},
data: [],
}
import { CSSProperties } from '@material-ui/styles/withStyles'
export const drawerWidth = 300
export const toolbarHeight = 124
export const flexColumn: CSSProperties = {
display: 'flex',
flexDirection: 'column',
}
import { Dispatch } from 'redux'
import session from '@agiliza/redux/session'
import { MainUseCase, RequestDriver, SecurityManager, UseCaseMessageType } from '@curio/client'
import { ConnectionError, DestinataryNotFoundError } from '@curio/client/errors'
import { ABORT } from '@curio/client/utils/constants'
const STORAGE_SESSION_KEY = '@app-exames-adm-session-token'
export interface ConfigService {
url: string
server: string
system: number
port: number
module: number
version: number
}
class Session extends MainUseCase {
module: number | undefined
version: number | undefined
constructor(token, service, driver) {
super(token, service, driver)
this.module = service.module
this.version = service.version
}
}
export class AnonymousSession extends MainUseCase {}
export class SessionManager extends SecurityManager {
public session: Session | undefined
private _dispatch: Dispatch
private _storage: Storage
private _service: ConfigService
constructor(storage: Storage, service: ConfigService, driver: RequestDriver, dispatch: Dispatch) {
super(service, driver)
this._dispatch = dispatch
this._storage = storage
this._service = service
const token = this._storage.getItem(STORAGE_SESSION_KEY)
const { actions } = session
if (process.env.NODE_ENV === 'development') {
dispatch(actions.setServiceInfo(service))
}
if (token) {
dispatch(actions.authRequest())
this.connectMainUseCase(new Session(token, this.service, driver))
this.session!.timeoutCheck()
.then(() => dispatch(actions.authSuccess()))
.catch((err) => {})
}
}
public anonymousConnection() {
return super.openMainUseCase('Administrador', '', AnonymousSession)
}
public async openMainUseCase<U extends typeof MainUseCase>(username: string, password: string) {
this.session = await super.openMainUseCase(username, password, Session)
this.session.module = this._service.module
this.session.version = this._service.version
this._storage.setItem(STORAGE_SESSION_KEY, this.session.token.toString())
this.session.addListener(ABORT, () => {
this._unauthenticate(false)
})
this.session.addListener(UseCaseMessageType.RESPONSE, (message: any) => {
if (message.error instanceof DestinataryNotFoundError || message.error instanceof ConnectionError) {
this._unauthenticate(true)
}
})
return this.session as InstanceType<U>
}
public connectMainUseCase(mainUseCase: Session) {
this.session = mainUseCase
if (!(mainUseCase instanceof AnonymousSession)) {
this._storage.setItem(STORAGE_SESSION_KEY, this.session.token.toString())
}
this.session.addListener(ABORT, () => {
this._unauthenticate(false)
})
this.session.addListener(UseCaseMessageType.RESPONSE, (message: any) => {
if (message.error instanceof DestinataryNotFoundError || message.error instanceof ConnectionError) {
this._unauthenticate(true)
}
})
return super.connectMainUseCase(mainUseCase)
}
private _unauthenticate(expired: boolean) {
this.session = undefined
this._storage.removeItem(STORAGE_SESSION_KEY)
if (expired) {
this._dispatch(session.actions.logout())
}
}
}
import { Dispatch } from 'redux'
import { store } from '@agiliza/redux'
import { FetchLink } from '@curio/client/links'
import { V3RequestParser } from '@curio/client/parsers'
import { createV3Validator } from '@curio/client/validators'
// import config from '../../config/config.json'
import { ConfigService, SessionManager } from './SessionManager'
interface Config {
service: ConfigService
accessToken: string
resources: {
get: string
put: string
}
logs: boolean
externalApiUrl: string
}
const createSessionManager = (config: Config, dispatch: Dispatch) => {
const link = new FetchLink(config.service)
const requestParser = new V3RequestParser(config.service)
const sessionManager = new SessionManager(
localStorage,
config.service,
(request) => {
return Promise.resolve(request)
.then(requestParser.parse)
.then(JSON.stringify)
.then(link.parse)
.then(link.post)
.then((response) => response.json())
.then(createV3Validator(request).validate)
},
dispatch
)
interface Attributes {
[index: string]: string
_Id: string
_Recipient: string
_Sender: string
_SerialNumber: string
_SignalName: string
}
if (config.logs) {
sessionManager[Symbol.observable]().subscribe({
next: (msg) => {
if (msg.signalName === '116' || msg.signalName === '120' || msg.signalName === '134' || !Number(msg.signalName)) {
const signalName = msg.signalName.substr(msg.signalName.indexOf('_') + 1).replace(/_/g, ' ')
const filteredBody = Object.keys(msg.body ? (msg.body as Attributes) : {}).reduce((acc, curr) => {
if (curr.indexOf('_') < 0) return { ...acc, [curr]: (msg.body as Attributes)[curr] }
else return acc
}, {})
const colorType = msg.type === 'response' ? 'green' : 'blue'
console.log(
`%c ${msg.type.toUpperCase()} %c ${signalName}`,
`color: white; font-weight: bolder; background: ${colorType}`,
'font-weight: bolder; font-style: italic;',
Object.keys(filteredBody).length !== 0 ? filteredBody : ''
)
}
},
error: console.error,
complete: () => console.log('complete'),
})
}
return sessionManager
}
const CONFIG_PATH = './config.json'
let sm: SessionManager
let config: Config
async function getSessionManager() {
if (sm) {
return sm
} else {
try {
const cnfg = await (await fetch(CONFIG_PATH)).json()
config = cnfg
sm = createSessionManager(config, store.dispatch)
return sm
} catch (e) {
if (e instanceof Response) {
//Not found, most likely
throw process.env.NODE_ENV === 'production'
? 'Não foi encontrado o arquivo config.json na raiz da aplicação.'
: 'Arquivo config.json faltando na pasta public.'
}
throw e
}
}
}
const wd: any = window
wd.__CURIO_GET_SESSION__ = () => getSessionManager().then((sm) => sm.session)
export { createSessionManager, getSessionManager, config }
import sessionEpic from './session'
import systemEpic from './system'
export { systemEpic, sessionEpic }
import { AnyAction } from 'redux'
import { ActionsObservable, combineEpics, ofType } from 'redux-observable'
import { from, of } from 'rxjs'
import { catchError, switchMap, tap } from 'rxjs/operators'
import { session } from '@agiliza/api/useCases'
import { actions as sessionActions, types as sessionTypes } from '@agiliza/redux/session'
import { actions as loginActions, types as loginTypes } from '@agiliza/redux/ui/login'
type LoginRequestAction = ReturnType<typeof loginActions.login>
const loginEpic = (action$: ActionsObservable<LoginRequestAction>) =>
action$.pipe(
ofType<AnyAction, LoginRequestAction>(loginTypes.login),
switchMap((action) =>
from(session.login(action.payload)).pipe(
switchMap(() => {
return of(loginActions.loginSuccess(), sessionActions.authSuccess())
}),
catchError((error) => of(loginActions.loginError(error)))
)
)
)
type LogoutRequestAction = ReturnType<typeof sessionActions.logout>
const logoutEpic = (action$: ActionsObservable<AnyAction>) =>
action$.pipe(
ofType<AnyAction, LogoutRequestAction>(sessionTypes.logout),
tap(() => void session.logout()),
switchMap(() => of(sessionActions.logoutSuccess(), { type: 'RESET_STORE' }))
)
type InitializeRequestAction = ReturnType<typeof sessionActions.initialize>
const initializeEpic = (action$: ActionsObservable<InitializeRequestAction>) =>
action$.pipe(
ofType<AnyAction, InitializeRequestAction>(sessionTypes.initialize),
switchMap(() =>
from(session.initialize()).pipe(
switchMap(() => {
return of(sessionActions.initializeSuccess())
}),
catchError((error) => of(sessionActions.initializeError(error)))
)
)
)
export default combineEpics(loginEpic, logoutEpic, initializeEpic)
import { AnyAction } from 'redux'
import { ActionsObservable, combineEpics, ofType } from 'redux-observable'
import { from, of } from 'rxjs'
import { catchError, switchMap } from 'rxjs/operators'
import { mapSystemApiToStore } from '@agiliza/api/mappers/system'
import { session } from '@agiliza/api/useCases'
import { actions, types } from '@agiliza/redux/ui/system'
import { getError } from '@agiliza/utils/method'
type FetchMenuAction = ReturnType<typeof actions.fetchMenu>
const fetchMenuEpic = (action$: ActionsObservable<AnyAction>) =>
action$.pipe(
ofType<AnyAction, FetchMenuAction>(types.fetchMenu),
switchMap(() =>
from(session.fetchMenu()).pipe(
switchMap((menu) => of(actions.fetchMenuSuccess(mapSystemApiToStore(menu)))),
catchError((error) => of(actions.fetchMenuError(getError(error))))
)
)
)
export default combineEpics(fetchMenuEpic)
import 'core-js/stable'
import 'regenerator-runtime/runtime'
import './theme/index.global.css'
import ptBR from 'date-fns/locale/pt-BR'
import React from 'react'
import { render } from 'react-dom'
import { Provider } from 'react-redux'
import { browser, SUPPORTED_BROWSERS } from '@agiliza/constants/browser'
import DateFnsUtils from '@date-io/date-fns'
import { MuiThemeProvider } from '@material-ui/core/styles'
import { MuiPickersUtilsProvider } from '@material-ui/pickers'
import ErrorDialog from './components/molecules/ErrorDialog'
import { store } from './redux'
import { theme } from './theme'
import Views from './views'
import BrowserIncompatible from './views/BrowserIncompatible'
const isValidBrowser = browser.satisfies(SUPPORTED_BROWSERS)
const root = document.getElementById('root')
interface Props {}
const Adm = (props: Props) => {
return (
<Provider store={store}>
<MuiThemeProvider theme={theme}>
<MuiPickersUtilsProvider utils={DateFnsUtils} locale={ptBR}>
<Views />
<ErrorDialog />
</MuiPickersUtilsProvider>
</MuiThemeProvider>
</Provider>
)
}
if (isValidBrowser) {
render(<Adm />, root)
} else {
render(<BrowserIncompatible />, root)
}
// import { initialState as profileInitState, reducer as profile, State as Profiles } from './profiles'
import { initialState as systemInitState, reducer as system, State as System } from './system'
// import { initialState as userInitState, reducer as user, State as Users } from './users'
export interface EntitiesState {
// user: Users
// profile: Profiles
system: System
}
const reducers = {
// user,
// profile,
system
}
export const initialState: EntitiesState = {
// user: userInitState,
// profile: profileInitState,
system: systemInitState
}
export default reducers
import slice from './reducer'
import * as selectors from './selectors'
export * from './reducer'
const actions = slice.actions
const reducer = slice.reducer
export { actions, reducer, selectors }
import { Operations } from '@dynamo/utils'
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
import { types as uiTypes } from '../../ui/system'
export interface MU {
id: string
type: 'MU'
name: string
useCase: string // Use case
operation: Operations // Operation
view?: 'menu'
}
export interface MS {
id: string
type: 'MS'
name: string
entity: string
actions: MU[]
}
export interface MI {
id: string
type: 'MI'
name: string
submenus: Menu[]
}
export type Menu = MS | MI | MU
export interface System {
name: string
menus: Menu[]
}
export interface State {
system?: System
MS: {
byId: Record<string, MS>
allIds: string[]
}
MU: {
byId: Record<string, MU>
allIds: string[]
}
}
export const initialState: State = {
MS: {
byId: {},
allIds: [],
},
MU: {
byId: {},
allIds: [],
},
}
export interface SystemEntities {
MS: Record<string, MS>
MU: Record<string, MU>
}
export interface SystemData {
system?: System
entities?: SystemEntities
}
export default createSlice({
name: 'entities/system',
initialState,
reducers: {},
extraReducers: {
[uiTypes.fetchMenuSuccess]: (state: State, action: PayloadAction<SystemData>) => {
const data = action.payload
state.system = data.system
if (data.entities) {
const entities = data.entities
state.MS.byId = entities.MS
state.MS.allIds = Object.keys(entities.MS)
state.MU.byId = entities.MU
state.MU.allIds = Object.keys(entities.MU)
}
},
},
})
import { State } from './reducer'
export const getSystem = (state: State) => state.system
export const getMSById = (state: State) => state.MS.byId
export const getMSUseCase = (state: State, id: string) => state.MS.byId[id]
export const getMUById = (state: State) => state.MU.byId
export const getMUUseCase = (state: State, id: string) => state.MU.byId[id]
import deepmerge from 'deepmerge'
import { AnyAction, combineReducers, Middleware, Reducer } from 'redux'
import { createLogger } from 'redux-logger'
import { combineEpics, createEpicMiddleware, Epic } from 'redux-observable'
import { sessionEpic } from '@agiliza/epics'
import { configureStore } from '@reduxjs/toolkit'
import entitiesReducer, { EntitiesState, initialState as entitiesInitState } from './entities'
import { errorMiddleware } from './middlewares'
import {
initialState as sessionInitState,
reducer as sessionReducer,
State as SessionState
} from './session'
import uiReducer, { initialState as uiInitState, UIState } from './ui'
type ReducerMap = Record<string, Reducer>
type Reducers = Record<string, Reducer | ReducerMap>
let registeredReducers: Reducers = {
entities: entitiesReducer,
session: sessionReducer,
ui: uiReducer,
}
function recombineReducers(reducers: Reducers) {
const result = Object.keys(reducers).reduce((acc, k) => {
const reducer = reducers[k]
acc[k] = typeof reducer === 'object' ? combineReducers(reducer) : reducer
return acc
}, {} as ReducerMap)
return combineReducers(result)
}
let combinedReducers = recombineReducers(registeredReducers)
const rootReducer = (state, action: AnyAction) => {
if (action.type === 'RESET_STORE') {
state = undefined
}
return combinedReducers(state, action)
}
const middlewares = !process.env.PRODUCTION ? [createLogger({ collapsed: true }), errorMiddleware] : [errorMiddleware]
const epicMiddleware = createEpicMiddleware()
const store = configureStore({
reducer: rootReducer,
middleware: [...middlewares, epicMiddleware] as Middleware[],
preloadedState: {
session: sessionInitState,
ui: uiInitState,
entities: entitiesInitState,
},
devTools: process.env.NODE_ENV === 'development',
})
type EpicMap = Record<string, Epic>
type Epics = Record<string, Epic | EpicMap>
let registeredEpics: Epics = {
session: sessionEpic,
}
function recombineEpics(epics: Epics) {
const result = Object.keys(epics).reduce((acc, k) => {
const epic = epics[k]
acc[k] = typeof epic === 'object' ? combineEpics(...Object.values(epic)) : epic
return acc
}, {} as EpicMap)
return combineEpics(...Object.values(result))
}
let combinedEpics = recombineEpics(registeredEpics)
epicMiddleware.run(combinedEpics)
function updateStore(newReducers: Reducers, newEpics: Epics) {
registeredReducers = deepmerge(registeredReducers, newReducers)
registeredEpics = deepmerge(registeredEpics, newEpics)
combinedReducers = recombineReducers(registeredReducers)
combinedEpics = recombineEpics(registeredEpics)
store.replaceReducer((state, action: AnyAction) => {
if (action.type === 'RESET_STORE') {
state = undefined
}
return combinedReducers(state, action)
})
epicMiddleware.run(combinedEpics)
}
export interface StoreState {
ui: UIState
session: SessionState
entities: EntitiesState
}
const wd: any = window
wd.__CURIO_REGISTER_VIEW__ = updateStore
export { store }
import { getError } from '@agiliza/utils/method'
import { Dispatch, Middleware, PayloadAction } from '@reduxjs/toolkit'
import { actions as errorActions } from './ui/error'
export const errorMiddleware: Middleware =
({ dispatch }) =>
(next: Dispatch<PayloadAction<any>>) =>
((action: PayloadAction<any>) => {
if (/Error$/.test(action.type) && action.payload) {
const error = getError(action.payload)
dispatch(errorActions.setErrorMessage(error))
}
return next(action)
}) as Dispatch<PayloadAction>
import { getTypesActions } from '@agiliza/utils/method'
import session from './reducer'
export * from './reducer'
export const actions = session.actions
export const reducer = session.reducer
export const types = getTypesActions(session.actions)
export default session
import { ConfigService } from '@agiliza/curio/SessionManager'
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
export interface State {
initializing: boolean
authenticating: boolean
authenticated: boolean
error?: string
serviceInfo?: ConfigService
}
export const initialState: State = {
authenticated: false,
authenticating: false,
initializing: false,
}
export type Actions = 'setServiceInfo' | 'authRequest' | 'authSuccess' | 'authError' | 'logout' | 'logoutSuccess'
const session = createSlice({
name: 'session',
initialState,
reducers: {
initialize: (state) => {
state.initializing = true
},
initializeSuccess: (state) => {
state.initializing = false
},
initializeError: (state, action: PayloadAction<string | undefined>) => {
state.initializing = false
state.error = action.payload
},
authRequest: (state) => {
state.authenticating = true
state.error = undefined
},
authSuccess: (state) => {
state.authenticating = false
state.authenticated = true
},
authError: (state, action: PayloadAction<string | undefined>) => {
state.authenticating = false
state.error = action.payload
},
logout: (state) => {
state.error = undefined
},
logoutSuccess: (state) => {
state.authenticated = false
},
setServiceInfo: (state, action: PayloadAction<ConfigService>) => {
state.serviceInfo = action.payload
},
},
})
export default session
import { State } from './reducer'
export const isAuthenticating = (state: State) => state.authenticating
export const isAuthenticated = (state: State) => state.authenticated
export const isInitializing = (state: State) => state.initializing
export const getError = (state: State) => state.error
export const getServiceInfo = (state: State) => state.serviceInfo
import { getTypesActions } from '@agiliza/utils/method'
import login from './reducer'
import * as selectors from './selectors'
export * from './reducer'
const actions = login.actions
const reducer = login.reducer
const types = getTypesActions(login.actions)
export { actions, reducer, types, selectors }
export default login
import { createSlice } from '@reduxjs/toolkit'
export interface State {
drawerOpen: boolean
}
export const initialState: State = {
drawerOpen: false
}
const employee = createSlice({
name: 'entities/drawer',
initialState,
reducers: {
toggleDrawer: state => {
state.drawerOpen = !state.drawerOpen
}
}
})
export default employee
import { State } from './reducer'
export const isDrawerOpen = (state: State) => state.drawerOpen
import { getTypesActions } from '@agiliza/utils/method'
import error from './reducer'
import * as selectors from './selectors'
export * from './reducer'
const actions = error.actions
const reducer = error.reducer
const types = getTypesActions(error.actions)
export { actions, reducer, types, selectors }
export default error
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
export interface State {
error: string
}
export const initialState: State = {
error: ''
}
const employee = createSlice({
name: 'ui/error',
initialState,
reducers: {
setErrorMessage: (state, action: PayloadAction<string>) => {
state.error = action.payload
}
}
})
export default employee
import { State } from '@agiliza/redux/ui/error'
export const getError = (state: State) => state.error
import {
initialState as drawerInitialState,
reducer as drawer,
State as DrawerState
} from './drawer'
import { initialState as errorInitialState, reducer as error, State as ErrorState } from './error'
import { initialState as loginInitialState, reducer as login, State as LoginState } from './login'
// import {
// initialState as profileInitialState,
// reducer as profile,
// State as ProfileState
// } from './profile'
import {
initialState as systemInitialState,
reducer as system,
State as SystemState
} from './system'
// import { initialState as userInitialState, reducer as user, State as UserState } from './user'
// export * from './login'
export interface UIState {
login: LoginState
error: ErrorState
drawer: DrawerState
// user: UserState
// profile: ProfileState
system: SystemState
}
const reducers = {
login,
error,
drawer,
// user,
// profile,
system
}
export const initialState: UIState = {
login: loginInitialState,
error: errorInitialState,
drawer: drawerInitialState,
// user: userInitialState,
// profile: profileInitialState,
system: systemInitialState
}
export default reducers
import { getTypesActions } from '@agiliza/utils/method'
import login from './reducer'
import * as selectors from './selectors'
export * from './reducer'
const actions = login.actions
const reducer = login.reducer
const types = getTypesActions(login.actions)
export { actions, reducer, types, selectors }
export default login
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
export interface State {
fetching: boolean
}
export const initialState: State = {
fetching: false,
}
interface Login {
username: string
password: string
}
const login = createSlice({
name: 'ui/login',
initialState,
reducers: {
login(state, action: PayloadAction<Login>) {
state.fetching = true
},
loginSuccess(state) {
state.fetching = false
},
loginError(state, action: PayloadAction<string>) {
state.fetching = false
},
},
})
export default login
import { State } from './reducer'
export const isFetching = (state: State) => state.fetching
import { getTypesActions } from '@agiliza/utils/method'
import login from './reducer'
import * as selectors from './selectors'
export * from './reducer'
const actions = login.actions
const reducer = login.reducer
const types = getTypesActions(login.actions)
export { actions, reducer, types, selectors }
export default login
import { SystemData } from '@agiliza/redux/entities/system'
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
export interface State {
fetching: boolean
}
export const initialState: State = {
fetching: false,
}
const slice = createSlice({
name: 'ui/system',
initialState,
reducers: {
fetchMenu(state) {
state.fetching = true
},
fetchMenuSuccess(state, action: PayloadAction<SystemData>) {
state.fetching = false
},
fetchMenuError(state, action: PayloadAction<string>) {
state.fetching = false
},
},
})
export default slice
import { State } from './reducer'
export const isFetching = (state: State) => state.fetching
@font-face {
font-family: 'Rubik';
src: url('../fonts/Rubik/Rubik-Regular.ttf') format('truetype');
font-weight: 400;
}
@font-face {
font-family: 'Rubik';
src: url('../fonts/Rubik/Rubik-SemiBold.ttf') format('truetype');
font-weight: 600 bold;
}
@font-face {
font-family: 'Heebo';
src: url('../fonts/Heebo/Heebo-Regular.ttf') format('truetype');
font-weight: 400;
}
@font-face {
font-family: 'Heebo';
src: url('../fonts/Heebo/Heebo-SemiBold.ttf') format('truetype');
font-weight: 600 bold;
}
@font-face {
font-family: 'Roboto';
src: url('../fonts/Roboto/Roboto-Regular.ttf') format('truetype');
font-weight: 400;
}
@font-face {
font-family: 'Roboto';
src: url('../fonts/Roboto/Roboto-Bold.ttf') format('truetype');
font-weight: 600 bold;
}
html,
body {
height: 100%;
margin: 0;
padding: 0;
font-family: 'Rubik', 'Roboto', 'Open Sans', sans-serif;
font-size: 16px;
}
* {
box-sizing: border-box;
}
#root {
height: 100%;
}
import red from '@material-ui/core/colors/red'
import { createMuiTheme } from '@material-ui/core/styles'
export const defaultToobarHeight = 64
export const theme = createMuiTheme({
palette: {
primary: {
light: '#034da6',
main: '#0d3366'
},
secondary: {
main: '#23a897',
contrastText: '#fafafa'
},
text: { primary: '#2e2e2e' },
error: {
main: red[500]
}
},
mixins: {
toolbar: {
minHeight: defaultToobarHeight
}
},
typography: {
fontSize: 13,
fontFamily: "'Rubik', 'Roboto', 'Open Sans', sans-serif"
},
overrides: {
MuiInputBase: {
input: {
'&:-webkit-autofill': {
WebkitBoxShadow: '0 0 0 1000px white inset'
}
}
},
MuiTableCell: {
root: {
fontFamily: 'Heebo'
}
},
MuiListItemText: {
primary: {
fontFamily: 'Heebo'
}
},
MuiDialogContentText: {
root: {
fontFamily: 'Heebo'
}
},
MuiListItemIcon: {
root: {
minWidth: 40
}
}
}
})
declare global {
interface Window {
__CURIO_GET_SESSION__(): Promise<MainUseCase>
__CURIO_REGISTER_VIEW__(reducers: any, epics: any): void
}
}
declare module 'curiojs' {
const n: any
export default n
}
declare module '*.scss' {
const obj: any
export default obj
}
declare module '*.sass' {
const obj: any
export default obj
}
declare module '*.json' {
const json: any
export const version: any
export default json
}
declare module '*.env' {
const json: any
export default json
}
declare module '*.png' {
const obj: any
export default json
}
declare module '*.svg' {
const obj: any
export default json
}
declare namespace NodeJS {
interface ProcessEnv {
NODE_ENV: 'development' | 'production'
PROFILE: any
APP_TITLE: string
}
}
declare global {
declare module '*.svg' {
const obj: any
export default json
}
interface Window {
__CURIO_GET_SESSION__(): Promise<MainUseCase>
__CURIO_REGISTER_VIEW__(reducers: any, epics: any): void
}
declare const VERSION
}
declare const VERSION
/**
* A supplementary function to deal with Safari's annoying lack
* of support for lookbehind in regular expressions.
* @param text The text to extract
* @returns A string containing a decimal with at most a single dot
* and at most a single negative symbol
*/
const NOT_DIGITS = /\D/g
const NOT_DIGITS_NOR_DOT = /[^\d.]/g
// const NOT_DIGITS_NOR_NEGATIVE = /[^\d\-]/g
// const NOT_DIGITS_NOR_NEGATIVE_NOR_DOT = /[^\d\.\-]/g
function extractProperDecimal(text?: string) {
if (!text) return ''
let filteredText = text
// Removes extra dots
const dotIndex = text.indexOf('.')
if (dotIndex > -1) {
filteredText = `${filteredText.slice(0, dotIndex)}.${filteredText.slice(dotIndex + 1).replace(NOT_DIGITS, '')}`
}
// Removes extra negative symbols
const negativeIndex = text.indexOf('-')
if (negativeIndex > 0) {
// negative symbol is not the first character, get rid of it
filteredText = `${filteredText.slice(0, dotIndex)}${filteredText.slice(dotIndex + 1).replace(NOT_DIGITS_NOR_DOT, '')}`
} else if (negativeIndex === 0) {
// negative symbol is the first character, get rid of the others
filteredText = `-${filteredText.slice(dotIndex + 1).replace(NOT_DIGITS_NOR_DOT, '')}`
}
return filteredText
}
export function extractNumbers(text?: string) {
return text ? text.replace(/\D/g, '') : ''
}
export function extractDecimal(text?: string) {
if (!text) return ''
const filteredText = extractProperDecimal(text.replace(/[^\d.]/g, ''))
// .replace(/(?=<\..*)\./g, '')
if (filteredText === '.') return '0.'
if (/[^0]/g.test(filteredText)) {
return filteredText.replace(/^0+(?!\.)/, '')
}
return '0'
}
export function extractLetters(text?: string) {
if (!text) return ''
return text.replace(/[^A-Za-z]/g, '')
}
export function extractLettersAndNumbers(text?: string) {
if (!text) return ''
return text.replace(/[^0-9A-Za-z]/g, '')
}
export function extractCurrency(text?: string) {
if (!text) return ''
if (text.startsWith('R$')) {
// Texto já está no formato BRL
const filteredText = extractProperDecimal(
text
.replace(/[^\d,]/g, '')
.replace(/[,]/g, '.')
// .replace(/(?<=\..*)\./g, '')
.replace(/^0+(?!\.)/, '')
)
if (filteredText === '.') return '0.'
if (/\.\d{3,}$/.test(filteredText)) return filteredText.slice(0, filteredText.length - 1)
return filteredText
} else {
// caso especial para toFixed
if (/\.\d{0,2}$/.test(text)) return text
else if (/\.\d{3,}$/.test(text)) return text.slice(0, text.indexOf('.') + 3)
else return text
}
}
export function extractCVC(text: string) {
const filteredText = extractNumbers(text)
return filteredText.slice(0, 3)
}
export function extractCEP(text: string) {
const filteredText = extractNumbers(text)
return filteredText.slice(0, 8)
}
export function extractCPF(text: string) {
const filteredText = extractNumbers(text)
return filteredText.slice(0, 11)
}
export function extractCNPJ(text: string) {
const filteredText = extractNumbers(text)
return filteredText.slice(0, 14)
}
export function extractCPFCNPJ(text: string) {
const filteredText = extractNumbers(text)
return filteredText.slice(0, 14)
}
export function extractPhone(text: string) {
const filteredText = extractNumbers(text)
return filteredText.slice(0, 11)
}
export function extractFIPE(text: string) {
const filteredText = extractNumbers(text)
return filteredText.slice(0, 7)
}
export function extractUF(text: string) {
const filteredText = extractLetters(text)
return filteredText.slice(0, 2).toUpperCase()
}
export function extractLicensePlate(text: string) {
const filteredText = extractLettersAndNumbers(text)
return filteredText.slice(0, 7).toUpperCase()
}
export function extractChassis(text: string) {
const filteredText = extractLettersAndNumbers(text)
return filteredText.slice(0, 17).toUpperCase()
}
export function extractDate(date: Date) {
if (date !== null) {
date.setHours(0, 0, 0, 0)
}
return date
}
import { extractCurrency, extractDecimal, extractNumbers } from './extractors'
// import { getUtcToZonedTime } from './methods'
export const formatPhone = (text: string) => {
if (!text) return ''
const filteredString = extractNumbers(text).slice(0, 11)
const length = filteredString.length
if (length < 3) return filteredString
if (length < 8) return filteredString.replace(/(\d\d)/, '($1) ')
return filteredString.replace(/(\d\d)(\d\d\d\d\d)/, '($1) $2-')
}
export const formatCPFCNPJ = (text: string) => {
if (!text) return ''
const filteredText = extractNumbers(text).slice(0, 14)
const length = filteredText.length
if (length < 4) return filteredText
if (length < 7) return filteredText.replace(/(\d{3})/, '$1.')
if (length < 10) return filteredText.replace(/(\d{3})(\d{3})/, '$1.$2.')
if (length < 12) return filteredText.replace(/(\d{3})(\d{3})(\d{3})/, '$1.$2.$3-')
if (length < 13) return filteredText.replace(/(\d{2})(\d{3})(\d{3})(\d{4})/, '$1.$2.$3/$4')
else return filteredText.replace(/(\d{2})(\d{3})(\d{3})(\d{4})/, '$1.$2.$3/$4-')
}
export const formatCPF = (text: string) => {
if (!text) return ''
const filteredText = extractNumbers(text).slice(0, 11)
const length = filteredText.length
if (length < 4) return filteredText
if (length < 7) return filteredText.replace(/(\d{3})/, '$1.')
if (length < 10) return filteredText.replace(/(\d{3})(\d{3})/, '$1.$2.')
return filteredText.replace(/(\d{3})(\d{3})(\d{3})/, '$1.$2.$3-')
}
export const formatFIPE = (text: string) => {
if (!text) return ''
const filteredText = extractNumbers(text).slice(0, 7)
const length = filteredText.length
if (length < 7) return filteredText
return filteredText.replace(/(\d{6})/, '$1-')
}
export const formatCNPJ = (text: string) => {
const filteredText = extractNumbers(text).slice(0, 14)
const length = filteredText.length
if (length < 2) return filteredText
if (length < 6) return filteredText.replace(/(\d\d)/, '$1.')
if (length < 9) return filteredText.replace(/(\d\d)(\d\d\d)/, '$1.$2.')
if (length < 13) return filteredText.replace(/(\d\d)(\d\d\d)(\d\d\d)/, '$1.$2.$3/')
if (length < 15) return filteredText.replace(/(\d\d)(\d\d\d)(\d\d\d)(\d\d\d\d)/, '$1.$2.$3/$4-')
return text
}
export const formatCEP = (text: string) => {
if (!text) return ''
const filteredText = extractNumbers(text).slice(0, 8)
const length = filteredText.length
if (length < 6) return filteredText
return filteredText.replace(/(\d{5})/, '$1-')
}
export const formatDateValue = (value: string | Date) => {
if (!value) return null
return typeof value === 'string' ? new Date(value) : value
}
export const formatDateText = (text?: string) => {
if (!text) return ''
const filteredString = extractNumbers(text).slice(0, 8)
const length = filteredString.length
if (length < 3) return filteredString
if (length < 5) return filteredString.replace(/^(\d\d)/g, '$1/')
if (length < 9) return filteredString.replace(/^(\d\d)(\d\d)/g, '$1/$2/')
return text
}
const formatLeftSide = (text?: string) => {
if (!text) return ''
return text.replace(/\B(?=(\d{3})+(?!\d))/g, '.')
}
const formatRightSide = (text?: string) => {
if (!text) return ''
return text.padEnd(2, '0').slice(0, 2)
}
export const formatCurrency = (text?: string, partial = false, prefix = 'R$') => {
if (!text) return ''
const value = text.startsWith(prefix) ? extractCurrency(text) : text
if (!value) return ''
let [leftSide, rightSide] = value.split('.')
if (!leftSide) {
// usuário apertou '.' primeiro
return `${prefix} 0,`
}
leftSide = formatLeftSide(leftSide)
if (rightSide !== undefined) {
rightSide = partial ? rightSide.slice(0, 2) : formatRightSide(rightSide)
return `${prefix} ${leftSide},${rightSide}`
} else {
return `${prefix} ${leftSide}`
}
}
export const formatNumber = (text?: string, partial = false) => {
if (!text) return ''
const value = extractDecimal(text)
if (!value) return ''
let [leftSide, rightSide] = value.split('.')
if (!leftSide) {
// usuário apertou '.' primeiro
return `0,`
}
leftSide = formatLeftSide(leftSide)
if (rightSide !== undefined) {
rightSide = partial ? rightSide.slice(0, 2) : formatRightSide(rightSide)
return `${leftSide},${rightSide}`
} else {
return `${leftSide}`
}
}
import { Dispatch } from 'react'
/**
* An *action* is a plain object that represents an intention to change the
* state. Actions are the only way to get data into the store. Any data,
* whether from UI events, network callbacks, or other sources such as
* WebSockets needs to eventually be dispatched as actions.
*
* Actions must have a `type` field that indicates the type of action being
* performed. Types can be defined as constants and imported from another
* module. It's better to use strings for `type` than Symbols because strings
* are serializable.
*
* Other than `type`, the structure of an action object is really up to you.
* If you're interested, check out Flux Standard Action for recommendations on
* how actions should be constructed.
*
* @template T the type of the action's `type` tag.
*/
interface Action<T = any> {
type: T
}
/**
* An Action type which accepts any other properties.
* This is mainly for the use of the `Reducer` type.
* This is not part of `Action` itself to prevent types that extend `Action` from
* having an index signature.
*/
interface AnyAction extends Action {
// Allows any extra properties to be defined in an action.
[extraProps: string]: any
}
/**
* An *action creator* is, quite simply, a function that creates an action. Do
* not confuse the two terms—again, an action is a payload of information, and
* an action creator is a factory that creates an action.
*
* Calling an action creator only produces an action, but does not dispatch
* it. You need to call the store's `dispatch` function to actually cause the
* mutation. Sometimes we say *bound action creators* to mean functions that
* call an action creator and immediately dispatch its result to a specific
* store instance.
*
* If an action creator needs to read the current state, perform an API call,
* or cause a side effect, like a routing transition, it should return an
* async action instead of an action.
*
* @template A Returned action type.
*/
type ActionCreator<A> = (...args: any[]) => A
/**
* Object whose values are action creator functions.
*/
interface ActionCreatorsMapObject<A = any> {
[key: string]: ActionCreator<A>
}
function bindActionCreator<A extends AnyAction = AnyAction>(
actionCreator: ActionCreator<A>,
dispatch: Dispatch<any>
) {
return function (this: any, ...args: any[]) {
return dispatch(actionCreator.apply(this, args))
}
}
/**
* Turns an object whose values are action creators, into an object with the
* same keys, but with every function wrapped into a `dispatch` call so they
* may be invoked directly. This is just a convenience method, as you can call
* `store.dispatch(MyActionCreators.doSomething())` yourself just fine.
*
* For convenience, you can also pass an action creator as the first argument,
* and get a dispatch wrapped function in return.
*
* @param actionCreators An object whose values are action
* creator functions. One handy way to obtain it is to use ES6 `import * as`
* syntax. You may also pass a single function.
*
* @param dispatch The `dispatch` function available on React.
*
* @returns The object mimicking the original object, but with
* every action creator wrapped into the `dispatch` call. If you passed a
* function as `actionCreators`, the return value will also be a single
* function.
*/
export default function bindActionCreators(
actionCreators: ActionCreator<any> | ActionCreatorsMapObject,
dispatch: Dispatch<any>
) {
if (typeof actionCreators === 'function') {
return bindActionCreator(actionCreators, dispatch)
}
if (typeof actionCreators !== 'object' || actionCreators === null) {
throw new Error(
`bindActionCreators expected an object or a function, instead received ${
actionCreators === null ? 'null' : typeof actionCreators
}.`
)
}
const boundActionCreators: ActionCreatorsMapObject = {}
for (const key in actionCreators) {
if (key) {
const actionCreator = actionCreators[key]
if (typeof actionCreator === 'function') {
boundActionCreators[key] = bindActionCreator(actionCreator, dispatch)
}
}
}
return boundActionCreators
}
import { useCallback, useMemo, useReducer } from 'react'
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
import { Field, FieldValidation, validateRequiredField } from '../validators'
import bindActionCreators from './bindActionCreators'
export type Validator<V> = (field: Field<V>) => FieldValidation
type Adapter<A, B> = (value: A, field: Field<B>) => B
type Accessor<V> = string | ((state: any) => V)
export interface BaseDescription {
/**
* If set to false, ignores the current state of this field
* for state validation. Useful for fields which might be in
* the form state but aren't modified (e.g. id).
*/
// ignoreValidation?: boolean
/**
* Whether the field needs to be filled (i.e. different from null,
* undefined and empty string). If set to true, the default Required
* validator is attributed to this field.
*/
required: boolean
/**
* Transforms the incoming value for the field into a new value to be
* stored.
*/
adapter?: Adapter<any, any>
/**
* A property name or a function to extract a value from the initial state.
*/
accessor?: Accessor<any>
/**
* Validators are tested in order.
*/
validators?: Validator<any>[]
/**
* Value to be used when no initial state is provided, no accessor is provided,
* or if the accessed value is undefined, null or an empty string.
*/
defaultValue?: any
}
type DescriptionValidator<V> = Omit<BaseDescription, 'validators'> & {
validators: Validator<V>[]
}
type DescriptionAdapter<A, B> = Omit<BaseDescription, 'adapter'> & {
adapter: Adapter<A, B>
}
type DescriptionAccessor<V> = Omit<BaseDescription, 'accessor'> & {
accessor: Accessor<V>
}
type DescriptionDefaultValue<V> = Omit<BaseDescription, 'defaultValue'> & {
defaultValue: V
}
type FieldValue<X> = X extends DescriptionAdapter<infer A, infer B>
? B
: X extends DescriptionValidator<infer V1>
? V1
: X extends DescriptionDefaultValue<infer V2>
? V2
: X extends DescriptionAccessor<infer V3>
? V3
: unknown
type UpdateValue<X> = X extends DescriptionAdapter<infer A, infer B>
? A
: X extends DescriptionValidator<infer V1>
? V1
: X extends DescriptionDefaultValue<infer V2>
? V2
: X extends DescriptionAccessor<infer V3>
? V3
: unknown
type GetTypedDescription<X> = X extends DescriptionAdapter<infer A, infer B>
? {
defaultValue?: B
validators?: Validator<B>[]
accessor?: Accessor<B>
}
: X extends DescriptionValidator<infer V1>
? {
defaultValue?: V1
adapter?: Adapter<any, V1>
accessor?: Accessor<V1>
}
: X extends DescriptionAccessor<infer V2>
? {
defaultValue?: V2
validators?: Validator<V2>[]
adapter?: Adapter<any, V2>
}
: X extends DescriptionDefaultValue<infer V3>
? {
validators?: Validator<V3>[]
adapter?: Adapter<any, V3>
accessor?: Accessor<V3>
}
: Record<string, any>
type Description<X> = X & GetTypedDescription<X>
type Descriptor<T> = Record<string, Description<T>>
type FormState<D> = {
[K in keyof D]: Field<FieldValue<D[K]>>
}
type FormValidator<D> = (
state: FormState<D>
) => Partial<Record<keyof D, FieldValidation>>
export function createFormReducer<
T extends BaseDescription,
U extends Descriptor<T>
>(descriptor: U, stateValidators?: FormValidator<U>[]) {
type State = FormState<U>
return function<S>(initialState?: S) {
const initializeState = useCallback(function(initialValues?: S) {
const val = Object.entries(descriptor).reduce((acc, [k, description]) => {
const key = k as keyof U
const { accessor, defaultValue } = description
let value: any
if (!initialValues) {
value = defaultValue
} else if (accessor) {
value =
typeof accessor === 'function'
? accessor(initialValues)
: initialValues[accessor as keyof S]
value = value !== undefined ? value : defaultValue
}
acc[key] = {
value,
error: false,
invalid: false,
success: false,
errorText: undefined
}
return acc
}, {} as State)
return val
}, [])
type UpdatePayload = {
[k in keyof State]?: UpdateValue<U[k]> | undefined
}
const slice = useMemo(
() =>
createSlice({
name: 'formReducer',
initialState: initializeState(),
reducers: {
update(state, action: PayloadAction<UpdatePayload>) {
Object.entries(action.payload).forEach(([k, v]) => {
const key = k as keyof UpdatePayload
const value = v as UpdatePayload[typeof key]
const description = descriptor[key]
const field = (state as any)[key] as State[typeof key]
if (description.adapter) {
const adaptedValue = description.adapter(value, field)
field.value = adaptedValue as typeof field.value
} else {
field.value = (value as any) as typeof field.value
}
if (description.required) {
const { error } = validateRequiredField(field)
field.invalid = error
}
if (description.validators) {
field.invalid = description.validators.some(
(validator) => validator(field).error
)
}
field.success = !!field.value && !field.invalid
field.error = false
field.errorText = undefined
})
if (stateValidators) {
stateValidators.forEach((validator) => {
const validatedFields = validator((state as any) as State)
Object.keys(validatedFields).forEach((k) => {
const field = state[k]
const validation = validatedFields[k]
field.invalid = field.invalid || !!validation?.error
field.error = field.error || false
field.errorText = field.errorText || undefined
field.success = !!field.value && !field.invalid
})
})
}
},
validate(state, action: PayloadAction<keyof State>) {
const key = action.payload
const description = descriptor[key]
const field = (state as any)[key] as State[typeof key]
if (field) {
field.invalid = false
if (description.required) {
const { error, errorText } = validateRequiredField(field)
field.error = error
field.errorText = errorText
}
if (description.validators && !field.error) {
description.validators.some((validator) => {
const { error: vError, errorText: vErrorText } = validator(
field
)
field.error = vError
field.errorText = vErrorText
return vError
})
}
field.success = !field.error && !!field.value
}
if (stateValidators) {
const fieldKeysToValidate = Object.keys(state).filter(
(k) => !state[k].error
)
stateValidators.forEach((validator) => {
const validatedFields = validator((state as any) as State)
fieldKeysToValidate.forEach((k) => {
const field = state[k]
const validation = validatedFields[k]
if (!field.error && validation?.error) {
field.error = validation.error
field.errorText = validation.errorText
}
field.success = !field.error && !!field.value
})
})
}
},
reset(state, action: PayloadAction<S | undefined>) {
return initializeState(action.payload)
}
}
}),
[initializeState, stateValidators]
)
type Actions = Omit<typeof slice.actions, 'update'> & {
update(
payload: UpdatePayload
): {
payload: UpdatePayload
type: string
}
}
const [currentState, dispatch] = useReducer(
slice.reducer,
initialState,
initializeState
)
const actions = useMemo(
() => bindActionCreators(slice.actions, dispatch) as Actions,
[slice.actions, dispatch]
)
type FormValues = {
[k in keyof U]: FieldValue<U[k]>
}
const getValues = useCallback(() => {
return Object.entries(currentState).reduce((acc, [k, f]) => {
const key = k as keyof State
const field = f as State[typeof key]
acc[k as keyof FormValues] = field.value
return acc
}, {} as FormValues)
}, [currentState])
const invalidState = useMemo(() => {
return Object.entries(currentState).some(([k, f]) => {
const key = k as keyof State
const field = f as State[typeof key]
const description = descriptor[key]
if (!description.required) {
return field.error || field.invalid
} else {
return (
validateRequiredField(field).error || field.error || field.invalid
)
}
})
}, [currentState])
const getInvalidExcept = useCallback(
(keys: Array<keyof State>) => {
return Object.entries(currentState).some(([k, f]) => {
const key = k as keyof State
if (keys.includes(key)) return false
const field = f as State[typeof key]
const description = descriptor[key]
if (!description.required) {
return field.error || field.invalid
} else {
return (
validateRequiredField(field).error || field.error || field.invalid
)
}
})
},
[currentState]
)
return {
state: currentState,
actions,
invalidState,
getValues,
getInvalidExcept
}
}
}
import { useMemo, useReducer } from 'react'
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
import { entries, keys } from '../method'
import bindActionCreators from './bindActionCreators'
export type Error = { error: boolean; errorMessage: string; value: string }
export type Validator = (value: string) => Error
export type ErrorState<S> = {
[k in keyof S]: S[k] extends string | Date ? Error : S[k] extends Record<string, unknown> ? ErrorState<S> : unknown
}
export type Validators<S> = {
[k in keyof S]: Validator | Validator[]
}
const createErrorInitState = <ObjectType>(obj: Record<string, unknown>) =>
entries(obj).reduce((kys, [k, v]) => {
if (v instanceof Object) return { ...kys, [k]: createErrorInitState(v as Record<string, unknown>) }
return { ...kys, [k]: { error: false, errorMessage: undefined, value: v } }
}, {} as ObjectType)
export type ErrorValidatePayload<S> = {
[key in keyof S]: string
}
export const validState = (value: string): Error => ({ error: false, errorMessage: '', value })
export const invalidState = (value: string, errorMessage: string): Error => ({ errorMessage, error: true, value })
const requiredValidator = (value: string): Error => (value ? validState(value) : { error: true, errorMessage: 'Campo obrigatório.', value })
export const getErrorProps = (error: Error) => ({ error: error.error, helperText: error.errorMessage })
export const useErrorValidator = <S>(initialState: S, validators?: Validators<Partial<S>>, notRequiredKeys?: (keyof S)[]) => {
const errorsInitState = createErrorInitState<ErrorState<S>>(initialState as Record<string, unknown>)
const errorSlice = useMemo(
() =>
createSlice({
name: 'errorValidator',
initialState: errorsInitState,
reducers: {
validate: (state: ErrorState<S>, action: PayloadAction<Partial<ErrorValidatePayload<S>>>) => {
const { payload } = action
entries(payload).forEach(([k, v]) => {
const value = v as string
if (!state[k]) state[k] = validState(value)
const sError = state[k] as Error
sError.value = value
const validator: Validator | Validator[] = validators && validators[k]
const isRequired = notRequiredKeys ? !notRequiredKeys.find((nrk) => nrk === k) : true
if (isRequired) {
const validationError = requiredValidator(value)
const { error, errorMessage } = validationError || validState(value)
sError.error = error
sError.errorMessage = errorMessage
}
if (validator) {
if (validator instanceof Array) {
let validationError
validator.forEach((vld) => !validationError && (validationError = vld(value)))
const { error, errorMessage } = validationError || validState(value)
sError.error = error
sError.errorMessage = errorMessage
}
if (validator instanceof Function) {
const validationError: Error = validator(value)
const { error, errorMessage } = validationError || validState(value)
sError.error = error
sError.errorMessage = errorMessage
}
}
})
},
},
}),
[]
)
const [state, dispatch] = useReducer(errorSlice.reducer, errorsInitState)
const actions = bindActionCreators(errorSlice.actions, dispatch) as typeof errorSlice.actions
// useEffect(() => {
// entries(state).forEach(([k, v]) => actions.validate({ [k]: v }))
// }, [])
const errorState = state as ErrorState<S>
const getValidState = useMemo(() => {
const requiredKeys = notRequiredKeys ? keys(state).filter((k) => !notRequiredKeys.find((nRK) => nRK === k)) : keys(state)
return requiredKeys.every((k) => !state[k].error && !!state[k].value)
}, [state, notRequiredKeys])
return { errorState, actions, validState: getValidState }
}
import { extractNumbers } from './method'
export const maskCPFCNPJ = (str?: string) => {
if (!str) return ''
const filteredString = extractNumbers(str)
// if (filteredString.length !== str.length) return str
const length = filteredString.length
if (length < 4) return filteredString
if (length < 7) return filteredString.replace(/(\d\d\d)/, '$1.')
if (length < 10) return filteredString.replace(/(\d\d\d)(\d\d\d)/, '$1.$2.')
if (length < 12) {
return filteredString.replace(/(\d\d\d)(\d\d\d)(\d\d\d)/, '$1.$2.$3-')
}
if (length < 13) {
return filteredString.replace(/(\d\d)(\d\d\d)(\d\d\d)(\d\d\d\d)/, '$1.$2.$3/$4')
}
if (length < 15) {
return filteredString.replace(/(\d\d)(\d\d\d)(\d\d\d)(\d\d\d\d)/, '$1.$2.$3/$4-')
}
return filteredString
}
export const maskCEP = (str?: string) => {
if (!str) return ''
const filteredString = extractNumbers(str)
// if (filteredString.length !== str.length) return str
const length = filteredString.length
if (length < 6) return filteredString
if (length < 9) return filteredString.replace(/(\d\d\d\d\d)/, '$1-')
return filteredString
}
export const maskTel = (str?: string) => {
if (!str) return ''
let filteredString = extractNumbers(str)
// if (filteredString.length !== str.length) return str
if (filteredString[0] === '0') filteredString = filteredString.substring(1)
const length = filteredString.length
if (length < 3) return filteredString
if (length < 7) return filteredString.replace(/(\d\d)/, '($1) ')
if (length < 11) return filteredString.replace(/(\d\d)(\d\d\d\d)/, '($1) $2-')
if (length < 12) {
return filteredString.replace(/(\d\d)(\d\d\d\d\d)/, '($1) $2-')
}
return filteredString
}
import deepmerge from 'deepmerge'
import { PayloadAction } from '@reduxjs/toolkit'
export const values = (obj: Record<string, unknown>) => {
return Object.values(obj || {})
}
export const entries = (obj: Record<string, unknown>) => {
return Object.entries(obj || {})
}
export const keys = (obj: Record<string, unknown>) => {
return Object.keys(obj || {})
}
export const extractNumbers = (str?: string): string => (str ? str.replace(/\D/g, '') : '')
export const extractLetters = (str?: string): string =>
str
? str
.replace(/[^A-Za-z ]/g, '')
.toUpperCase()
.trim()
: ''
export const getTypesActions = <Actions>(actions: Actions) => {
type Types = {
[key in keyof Actions]: string
}
return Object.keys(actions).reduce((acc, curr) => {
return { ...acc, [curr]: `${actions[curr as keyof Actions]}` }
}, {} as Types)
}
export const getError = (error: Error | { error: string } | string) => {
if (error instanceof Error) {
if (process.env.NODE_ENV === 'development') return `${error.message} - ${error.stack}`
return error.message || 'Ocorreu um erro na requisição ao servidor.'
} else if (typeof error === 'object') return error.error
else return error
}
export const getTablePaperHeight = (heightReso: number) => {
if (650 <= heightReso && heightReso <= 800) return heightReso / 1.65
if (980 <= heightReso && heightReso <= 1100) return heightReso / 1.35
return heightReso / 1.2
// switch (heightReso) {
// // case 720:
// // return 445
// // case 1080:
// // return 800
// default:
// return heightReso / 1.65
// }
}
export const mergeState = <State extends { byId: Record<string, DataType>; allIds: string[] }, DataType extends { id: string }>(
state: State,
payload: DataType[]
) => {
const { allIds, byId } = state
payload.forEach((p) => {
if (!byId[p.id]) allIds.push(p.id)
byId[p.id] = p
})
}
type ActionType<Type, Payload> = {
type: Type
payload: Payload
}
export const reducerActions = <StateType extends { fetching: { [x: string]: any } | boolean }, Action extends { type: string; payload: any }>(
name: string
): {
[k in Action['type']]: (state: StateType, action: PayloadAction<Action['payload'] | undefined>) => void
} => {
const request = `${name}Request`
const success = `${name}Success`
const error = `${name}Error`
return {
[request]: (state: StateType, action: PayloadAction<Action['payload']>) => {
// eslint-disable-line
if (typeof state.fetching === 'object') state.fetching[name] = true
else state.fetching = true
},
[success]: (state: StateType) => {
if (typeof state.fetching === 'object') state.fetching[name] = false
else state.fetching = false
},
[error]: (state: StateType) => {
if (typeof state.fetching === 'object') state.fetching[name] = false
else state.fetching = false
},
} as {
[k in Action['type']]: (state: StateType, action: PayloadAction<Action['payload'] | undefined>) => void
}
}
export interface Entity {
id: string
}
export interface NormalizedEntity<T> {
[id: string]: T
}
export interface EntityStore<T> {
byId: NormalizedEntity<T>
allIds: string[]
}
export function syncById<T extends Entity, State extends EntityStore<T>>(state: State, entities: NormalizedEntity<T> = {}): NormalizedEntity<T> {
return deepmerge<NormalizedEntity<T>>(state.byId, entities, {
arrayMerge: <Type>(dest: Type[], src: Type[]) => src,
})
}
export function deepmergeArray<T = any>(array1: T[], array2: T[]) {
return array2.reduce<T[]>((prev, curr) => (prev.includes(curr) ? prev : [...prev, curr]), array1)
}
export function syncAllIds<T extends Entity, State extends EntityStore<T>>(state: State, entities: NormalizedEntity<T> = {}): string[] {
return deepmergeArray(state.allIds, Object.keys(entities))
}
type FirstParameter<T extends (...args: any) => any> = Parameters<T>[0]
type RequiredBy<T, K extends keyof T> = Pick<T, K> & Partial<Omit<T, K>>
export type { ActionType, FirstParameter, RequiredBy }
import { isAfter, isValid } from 'date-fns'
import { extractNumbers } from './extractors'
export interface Field<T> {
value: T
invalid: boolean
success: boolean
error: boolean
errorText?: string
}
export function isFilled(value: any) {
return !(value === '' || value === undefined || value === null || (Array.isArray(value) && value.length === 0))
}
export interface FieldValidation {
error: boolean
errorText?: string
}
export type FormValidation<S> = Partial<Record<keyof S, FieldValidation>>
export function validateRequiredField(field: Field<any>): FieldValidation {
const error = !isFilled(field.value)
return {
error,
errorText: error ? 'O campo é obrigatório.' : undefined,
}
}
export const validateCPF = (field: Field<string>): FieldValidation => {
const cpf = field.value
if (cpf.length < 11) {
return {
error: true,
errorText: 'O CPF informado é inválido.',
}
}
switch (cpf) {
case '11111111111':
case '22222222222':
case '33333333333':
case '44444444444':
case '55555555555':
case '66666666666':
case '77777777777':
case '88888888888':
case '99999999999':
case '00000000000':
return {
error: true,
errorText: 'O CPF informado é inválido.',
}
}
let firstDigitSum = 0
let cpfIndex = 0
for (let i = 10; i > 1; i--) {
firstDigitSum += i * Number(cpf[cpfIndex])
cpfIndex++
}
if ((firstDigitSum % 11 < 2 ? 0 : 11 - (firstDigitSum % 11)).toString() === cpf[9]) {
let secondDigitSum = 0
cpfIndex = 0
for (let i = 11; i > 1; i--) {
secondDigitSum += i * Number(cpf[cpfIndex])
cpfIndex++
}
const valid = (secondDigitSum % 11 < 2 ? 0 : 11 - (secondDigitSum % 11)).toString() === cpf[10]
return {
error: !valid,
errorText: !valid ? 'O CPF informado é inválido.' : undefined,
}
} else {
return {
error: true,
errorText: 'O CPF informado é inválido.',
}
}
}
export const validateCNPJ = (cnpj: string) => {
const seq = [5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2]
let firstDigitSum = 0
let cnpjIndex = 0
for (let i = 0; i < 12; i++) {
firstDigitSum += seq[i] * Number(cnpj[cnpjIndex])
cnpjIndex++
}
if ((firstDigitSum % 11 < 2 ? 0 : 11 - (firstDigitSum % 11)).toString() === cnpj[12]) {
let secondDigitSum = 0
cnpjIndex = 0
const seq2 = [6, ...seq]
for (let i = 0; i < 13; i++) {
secondDigitSum += seq2[i] * Number(cnpj[cnpjIndex])
cnpjIndex++
}
const valid = (secondDigitSum % 11 < 2 ? 0 : 11 - (secondDigitSum % 11)).toString() === cnpj[13]
return {
error: !valid,
errorText: !valid ? 'O CNPJ informado é inválido.' : undefined,
}
} else {
return {
error: true,
errorText: 'O CNPJ informado é inválido.',
}
}
}
// export const isValidCPFCNPJ = (cpfOrCnpj: string) => {
// switch (cpfOrCnpj.length) {
// case 0:
// return false
// case 11:
// return validateCPF(cpfOrCnpj)
// case 14:
// return validateCNPJ(cpfOrCnpj)
// default:
// return false
// }
// }
export const isValidEmail = (email: string) => !!email && email.indexOf('@') !== -1
export function validateEmail(field: Field<string>): FieldValidation {
const error = !isValidEmail(field.value)
return {
error,
errorText: error ? 'O email é inválido.' : undefined,
}
}
export function validateDate(field: Field<Date>): FieldValidation {
try {
if (field.value !== null) field.value.toISOString()
return {
error: false,
}
} catch {
return {
error: true,
errorText: 'A data é inválida.',
}
}
}
interface DateIntervalState {
startDate: Field<Date>
endDate: Field<Date>
}
export function validateDateInterval(state: DateIntervalState): FormValidation<DateIntervalState> {
if (isValid(state.startDate.value) && isValid(state.endDate.value) && isAfter(state.startDate.value, state.endDate.value)) {
return {
endDate: {
error: true,
errorText: 'Data de fim é inferior à data de início.',
},
}
}
return {}
}
/**
* Tests whether a given numeric value is beween a range.
* If no value is provided to `min` or `max`,
* they are respectivelly assumed to be `NEGATIVE_INFINITY` and `POSITIVE_INFINITY`.
* @param value The number to check
* @param min The lower bound of the range
* @param max The upper bound of the range
* @returns *true* if `value` is in range, *false* otherwise
*/
export function isBetween(value: number, min = Number.NEGATIVE_INFINITY, max = Number.POSITIVE_INFINITY) {
return value >= min && value <= max
}
/**
* Tests whether a given numeric value is less than the specified upper bound.
* @param value The number to check
* @param max The upper bound to be checked
* @returns *true* if `value` is less than `max`, *false* otherwise
*/
export function isLessThan(value: number, max: number) {
return value <= max
}
/**
* Tests whether a given numeric value is greater than the specified lower bound.
* @param value The number to check
* @param min The lower bound to be checked
* @returns *true* if `value` is greater than `min`, *false* otherwise
*/
export function isGreaterThan(value: number, min: number) {
return min <= value
}
export const createLengthValidator =
(minLength?: number, maxLength?: number) =>
(field: Field<string>): FieldValidation => {
const length = field.value.length
if (maxLength && !isLessThan(length, maxLength)) {
return {
error: true,
errorText: `O campo deve ter no máximo ${maxLength} caracteres.`,
}
} else if (minLength && !isGreaterThan(length, minLength)) {
return {
error: true,
errorText: `O campo deve ter no mínimo ${minLength} caracteres.`,
}
}
return {
error: false,
errorText: undefined,
}
}
const phoneRegexp = /[1-9]{2}9[1-9][0-9]{7}/
export const isValidPhone = (text: string) => {
const phone = extractNumbers(text)
return phone.length === 11 && phoneRegexp.test(phone)
}
import cn from 'classnames'
import React from 'react'
import { browser, SUPPORTED_BROWSERS } from '@agiliza/constants/browser'
import { withStyles, WithStyles } from '@material-ui/core/styles'
import styles from './styles'
type ExtendedProps = WithStyles<typeof styles>
interface Props extends ExtendedProps {}
const chrome = SUPPORTED_BROWSERS['chrome'].replace(/(>=)/g, '') + '+'
const firefox = SUPPORTED_BROWSERS['firefox'].replace(/(>=)/g, '') + '+'
const edge = SUPPORTED_BROWSERS['windows']['edge'].replace(/(>=)/g, '') + '+'
const safari = SUPPORTED_BROWSERS['macos']['safari'].replace(/(>=)/g, '') + '+'
const BrowserIncompatible = (props: Props) => {
const { classes } = props
return (
<div className={classes.page}>
<i className={cn('fas fa-exclamation-circle', classes.titleIcon)} />
<h1 className={classes.title}>Navegador não suportado</h1>
<p className={classes.subTitle}>{`Você está usando o ${browser.getBrowserName()} na versão ${browser.getBrowserVersion()}`}</p>
<p className={classes.subTitle}>É recomendado utilizar o {process.env.APP_TITLE} em um dos seguintes navegadores:</p>
<div className={classes.browserList}>
<a target="#" className={classes.anchorBrowser} href="https://www.google.com/chrome/">
<i className={cn('fab fa-chrome', classes.icon)} />
Chrome {chrome}
</a>
<a target="#" className={classes.anchorBrowser} href="https://www.mozilla.org/en-US/firefox/new/">
<i className={cn('fab fa-firefox-browser', classes.icon)} />
Firefox {firefox}
</a>
<a target="#" className={classes.anchorBrowser} href="https://www.microsoft.com/en-us/edge">
<i className={cn('fab fa-edge', classes.icon)}></i>
Edge {edge}
</a>
<a target="#" className={classes.anchorBrowser} href="https://support.apple.com/downloads/safari">
<i className={cn('fab fa-safari', classes.icon)}></i>
Safari {safari}
</a>
</div>
</div>
)
}
export default withStyles(styles)(BrowserIncompatible)
export { default } from './BrowserIncompatible'
export * from './BrowserIncompatible'
import { Theme } from '@material-ui/core'
import { createStyles } from '@material-ui/core/styles'
export default (theme: Theme) => {
return createStyles({
page: {
display: 'flex',
flexDirection: 'column',
height: '97vh',
justifyContent: 'center',
alignItems: 'center',
},
titleIcon: {
fontSize: '150px',
},
title: {
textAlign: 'center',
marginBottom: '1rem',
fontSize: 'xx-large',
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif',
},
subTitle: {
textAlign: 'center',
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans","Helvetica Neue", sans-serif',
},
browserList: {
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
width: '75%',
marginTop: '2rem',
},
anchorBrowser: {
color: 'black',
marginRight: '2.5rem',
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
fontSize: '25px',
textDecoration: 'none',
fontWeight: 'bold',
marginBottom: '0.5rem',
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans","Helvetica Neue", sans-serif',
},
icon: {
fontSize: '55px',
marginBottom: '1rem',
color: 'black',
},
})
}
import React, { useState } from 'react'
import { connect } from 'react-redux'
import { Redirect } from 'react-router'
import { bindActionCreators, Dispatch } from 'redux'
import ButtonWithProgress from '@agiliza/components/atoms/ButtonWithProgress'
import TextFieldWithIcon from '@agiliza/components/atoms/TextFieldWithIcon'
import PopoverVersion from '@agiliza/components/molecules/PopoverVersion'
import { ConfigService } from '@agiliza/curio/SessionManager'
import { StoreState } from '@agiliza/redux'
import { isAuthenticated } from '@agiliza/redux/session/selectors'
import { actions } from '@agiliza/redux/ui/login'
import { isFetching } from '@agiliza/redux/ui/login/selectors'
import InputAdornment from '@material-ui/core/InputAdornment'
import Typography from '@material-ui/core/Typography'
import AccountCircle from '@material-ui/icons/AccountCircle'
import { useStyles } from './styles'
import type { RouteComponentProps } from 'react-router'
type BaseProps = RouteComponentProps
interface Props extends BaseProps {
authenticated: boolean
fetching: boolean
loginRequest: typeof actions.login
service?: ConfigService
}
const Login = (props: Props) => {
const { loginRequest, authenticated, service, fetching } = props
const classes = useStyles()
const [username, setUsername] = useState('')
const [password, setPassword] = useState('')
const handleLogin = () => {
loginRequest({ username, password })
}
if (authenticated) {
return <Redirect to="/" />
}
return (
<div className={classes.container}>
{/* <div className={classes.logo} /> */}
<div className={classes.formContainer}>
<Typography align="center" className={classes.title} color="primary">
{process.env.APP_TITLE}
</Typography>
<form className={classes.form} onKeyDown={(evt) => evt.keyCode === 13 && handleLogin()}>
<TextFieldWithIcon
autoFocus
required
value={username}
onChange={(evt) => setUsername(evt.target.value)}
label="Usuário"
className={classes.usernameTxtField}
InputProps={{
startAdornment: (
<InputAdornment position="start">
<AccountCircle />
</InputAdornment>
),
}}
/>
<TextFieldWithIcon required value={password} onChange={(evt) => setPassword(evt.target.value)} label="Senha" type="password" />
</form>
<ButtonWithProgress disabled={!username} color="secondary" fetching={fetching} onClick={handleLogin}>
Entrar
</ButtonWithProgress>
</div>
<PopoverVersion service={service} />
</div>
)
}
const mapStateToProps = (state: StoreState) => ({
authenticated: isAuthenticated(state.session),
fetching: isFetching(state.ui.login),
})
const mapDispatchToProps = (dispatch: Dispatch) =>
bindActionCreators(
{
loginRequest: actions.login,
},
dispatch
)
export default connect(mapStateToProps, mapDispatchToProps)(Login)
export { default } from './Login'
export * from './Login'
import { flexColumn } from '@agiliza/constants/styles'
import { makeStyles, Theme } from '@material-ui/core/styles'
import { createStyles } from '@material-ui/styles'
// eslint-disable-next-line
export const useStyles = makeStyles((theme: Theme) =>
createStyles({
title: {
fontSize: '150%',
fontWeight: 'bold',
overflowWrap: 'normal',
},
formContainer: {
height: '40%',
textAlign: 'center',
justifyContent: 'space-between',
...flexColumn,
},
container: {
display: 'flex',
height: '100vh',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
textAlign: 'center',
},
logo: {
position: 'absolute',
opacity: 0.1,
top: 0,
left: 0,
width: '100%',
height: '100%',
backgroundImage: `url(${'/images/logo.png'})`,
backgroundSize: 'contain',
backgroundRepeat: 'no-repeat',
backgroundPosition: 'center',
},
form: {
padding: 10,
display: 'flex',
flexDirection: 'column',
},
usernameTxtField: { marginBottom: 10 },
})
)
import cn from 'classnames'
import React from 'react'
import ItemWithIcon from '@agiliza/components/atoms/ItemWithIcon'
import List from '@material-ui/core/List'
import { AttachMoney as AttachMoneyIcon, ExitToApp } from '@material-ui/icons'
import withStyles from '@material-ui/styles/withStyles'
import { styles } from './styles'
import type { WithStyles } from '@material-ui/styles/withStyles'
import type { RouteComponentProps } from 'react-router-dom'
import type { Props as DrawerProps } from '@agiliza/components/molecules/Drawer'
interface ListItem {
label: string
path: string
Icon: React.ComponentType
}
export const PATHS = {
creditLines: '/linhasCredito',
}
export const drawerListItems: ListItem[] = [{ label: 'Linhas de Crédito', path: PATHS.creditLines, Icon: AttachMoneyIcon }]
export const mapPathToTitle = (path: string) => {
return drawerListItems.find((dL) => dL.path === path)?.label || ''
}
type ExtendedTypes = RouteComponentProps & WithStyles<typeof styles>
interface Props extends ExtendedTypes {
listItemClassName?: string
toggleDrawer: () => void
logout: DrawerProps['logout']
}
const isCurrentPath = (history: RouteComponentProps['history'], path: string) => {
const result = history.location.pathname.replace(/(\/.*?)\/(.*?)$/g, '$1') === path
return result
}
const DrawerItems = (props: Props) => {
const { listItemClassName, history, classes, toggleDrawer, logout } = props
const handleClick = (path: string) => () => {
history.push(path)
toggleDrawer()
}
const listItemComponent = (label: string, path: string, Icon: React.ComponentType) => (
<ItemWithIcon
key={path}
label={label}
className={cn(listItemClassName, { [classes.selected]: isCurrentPath(history, path) })}
onClick={handleClick(path)}
>
<Icon />
</ItemWithIcon>
)
return (
<List className={classes.list}>
{drawerListItems.map((item) => listItemComponent(item.label, item.path, item.Icon))}
<ItemWithIcon label="Sair" className={listItemClassName} onClick={() => logout()}>
<ExitToApp />
</ItemWithIcon>
</List>
)
}
export default withStyles(styles)(DrawerItems)
export { default } from './DrawerItems'
export * from './DrawerItems'
import { drawerWidth } from '@agiliza/constants/styles'
import { createStyles, Theme } from '@material-ui/core/styles'
export const styles = (theme: Theme) => {
return createStyles({
selected: {
backgroundColor: theme.palette.primary.light,
color: theme.palette.primary.contrastText,
borderRadius: 40,
'& .MuiTypography-root': {
fontWeight: 'bold',
},
'& .MuiListItemIcon-root': {
color: theme.palette.primary.contrastText,
},
'&:hover': {
backgroundColor: theme.palette.primary.main,
},
},
list: {
flex: 1,
flexDirection: 'column',
display: 'flex',
paddingLeft: theme.spacing(1),
paddingRight: theme.spacing(1),
'& .MuiListItem-button:not(:last-of-type)': {
marginBottom: theme.spacing(1),
},
'& .MuiListItem-button': {
borderRadius: 40,
},
},
listItem: {
overflowX: 'hidden',
width: drawerWidth,
paddingLeft: theme.spacing(1.5),
},
grow: { flex: 1 },
})
}
import React, { lazy, Suspense, useEffect } from 'react'
import { Redirect, Route, RouteComponentProps, Switch, useLocation } from 'react-router'
import AppBar from '@agiliza/components/molecules/AppBar'
import CircularProgress from '@agiliza/components/molecules/CircularProgress'
import Drawer from '@agiliza/components/molecules/Drawer'
import { actions as sessionActions } from '@agiliza/redux/session'
import { actions as drawerActions } from '@agiliza/redux/ui/drawer'
import { withStyles, WithStyles } from '@material-ui/core/styles'
import connect, { ConnectedProps } from './connect'
import DrawerItems, { mapPathToTitle, PATHS } from './DrawerItems'
import styles from './styles'
const SimulationCreditLines = lazy(() => import('@agiliza/views/SimulationCreditLines/pages/router'))
// const SecurityProfile = lazy(() => import('@curio/ui/dist/views/SecurityProfile'))
type BaseProps = RouteComponentProps & ConnectedProps & WithStyles<typeof styles>
interface Props extends BaseProps {
toggleDrawer: typeof drawerActions.toggleDrawer
logout: typeof sessionActions.logout
}
const Main = (props: Props) => {
const { classes, drawerOpen, toggleDrawer, logout, fetchMenu, ...routeProps } = props
const { pathname } = useLocation()
useEffect(() => {
fetchMenu()
}, [])
return (
<div className={classes.pageContainer}>
<AppBar
onNavClick={toggleDrawer}
title={<div className={classes.title}>{mapPathToTitle(pathname.substring(0, pathname.lastIndexOf('/')))}</div>}
></AppBar>
<Drawer drawerOpen={drawerOpen} toggleDrawer={toggleDrawer} logout={logout} Items={DrawerItems} {...routeProps} />
<Suspense fallback={<CircularProgress />}>
<Switch>
<Route path={PATHS.creditLines} render={(rProps) => <SimulationCreditLines {...rProps} />} />
<Redirect from="/" to={PATHS.creditLines} />
</Switch>
</Suspense>
</div>
)
}
export default connect(withStyles(styles)(Main))
import { connect } from 'react-redux'
import { bindActionCreators, Dispatch } from 'redux'
import { StoreState } from '@agiliza/redux'
import { actions as sessionActions } from '@agiliza/redux/session'
import { actions as drawerActions } from '@agiliza/redux/ui/drawer'
import { isDrawerOpen } from '@agiliza/redux/ui/drawer/selectors'
import { actions as systemActions, selectors as systemSelectors } from '@agiliza/redux/ui/system'
export interface ConnectedProps {
drawerOpen: boolean
fetchingMenu: boolean
fetchMenu: typeof systemActions.fetchMenu
toggleDrawer: typeof drawerActions.toggleDrawer
logout: typeof sessionActions.logout
}
const mapStateToProps = (state: StoreState) => ({
drawerOpen: isDrawerOpen(state.ui.drawer),
fetchMenu: systemActions.fetchMenu,
fetchingMenu: systemSelectors.isFetching(state.ui.system),
})
const mapDispatchToProps = (dispatch: Dispatch) =>
bindActionCreators(
{
toggleDrawer: drawerActions.toggleDrawer,
logout: sessionActions.logout,
fetchMenu: systemActions.fetchMenu,
},
dispatch
)
export default connect(mapStateToProps, mapDispatchToProps)
export { default } from './Main'
export * from './Main'
import { createStyles, Theme } from '@material-ui/core/styles'
import sharedStyles from '../shared-styles'
export default (theme: Theme) => {
return createStyles({
...sharedStyles(theme),
})
}
import React, { useState } from 'react'
import { RouteComponentProps } from 'react-router'
import { extractCurrency, extractNumbers } from '@agiliza/utils/extractors'
import { formatCurrency } from '@agiliza/utils/formatters'
import {
Button,
CircularProgress,
InputAdornment,
TextareaAutosize,
TextField,
Typography
} from '@material-ui/core'
import { withStyles, WithStyles } from '@material-ui/core/styles'
import { Autocomplete } from '@material-ui/lab'
import { creditLines } from '../../../../__mocks__/creditLines'
import { CREDIT_LINES_PATHS } from '../router'
import SliderField from './SliderField'
import styles from './styles'
type CreditLine = typeof creditLines[0]
type ExtendedProps = WithStyles<typeof styles> & RouteComponentProps
interface Props extends ExtendedProps {
fetching: boolean
}
const CreditLinesList: React.FC<Props> = (props) => {
const { classes, fetching, history, match } = props
const [selectedCreditLine, setSelectedCreditLine] = useState<CreditLine | null>(null)
const [amount, setAmount] = useState('0')
const [paymentMonths, setPaymentMonths] = useState(0)
const [graceMonths, setGraceMonths] = useState(0)
const parentPath = match.path.substring(0, match.path.lastIndexOf('/'))
const handleSimulate = () => {
if (selectedCreditLine) history.push({ pathname: parentPath + CREDIT_LINES_PATHS.simulation, state: { id: selectedCreditLine.id } })
}
return (
<div className={classes.pageContent}>
<div className={classes.contentContainer}>
<div className={classes.content}>
<Typography variant="h5" className={classes.title}>
Escolha a melhor linha de crédito para você e clique em simular!
</Typography>
<Autocomplete<CreditLine>
id="credit-lines"
className={classes.creditLinesAutocomplete}
options={creditLines}
getOptionLabel={(option) => option.name}
getOptionSelected={(opt, val) => opt.id === selectedCreditLine?.id}
noOptionsText="Nenhuma linha encontrado"
value={selectedCreditLine}
onChange={(_, opt) => {
setSelectedCreditLine(opt || null)
setAmount(opt?.amount.min.toString() || '0')
setPaymentMonths(opt?.paymentMonths.min || 0)
setGraceMonths(opt?.graceMonths.min || 0)
}}
renderInput={(params) => {
const isValid = React.isValidElement(params.InputProps.endAdornment)
return (
<TextField
{...params}
id="select-patient-id"
label="Selecione ou Digite Id Paciente"
variant="outlined"
InputProps={{
ref: params.InputProps.ref,
endAdornment: fetching ? (
<InputAdornment position="end" style={{ flex: '1', display: 'flex', justifyContent: 'flex-end' }}>
<CircularProgress size={20} />
</InputAdornment>
) : isValid ? (
React.cloneElement(params.InputProps.endAdornment as React.ReactElement, {
style: { marginRight: '1rem' },
})
) : (
params.InputProps.endAdornment
),
}}
/>
)
}}
/>
<TextField
className={classes.description}
label="Descrição da linha de crédito"
value={selectedCreditLine?.informations || ''}
rows={5}
multiline
contentEditable={false}
InputLabelProps={{
shrink: true,
}}
InputProps={{ readOnly: true, inputProps: { component: TextareaAutosize } }}
variant="outlined"
unselectable="on"
/>
<SliderField
className={classes.sliderField}
title="De quanto você precisa?"
min={selectedCreditLine?.amount.min || 0}
max={selectedCreditLine?.amount.max || 5000}
marks={
selectedCreditLine
? [
{ value: selectedCreditLine.amount.min, label: formatCurrency(selectedCreditLine.amount.min.toString()) },
{ value: selectedCreditLine.amount.max, label: formatCurrency(selectedCreditLine.amount.max.toString()) },
]
: [
{ value: 0, label: formatCurrency('0') },
{ value: 5000, label: '' },
]
}
valueSlider={Number(amount)}
valueField={formatCurrency(amount.toString(), true)}
step={0.01}
disabled={!selectedCreditLine}
onChangeSlider={(_, value) => setAmount((value as number).toString())}
onChangeField={(evt) => setAmount(extractCurrency(evt.target.value))}
onBlurField={(evt) => {
const amountValue = extractCurrency(evt.target.value)
if (selectedCreditLine)
setAmount(Number(amountValue) <= selectedCreditLine.amount.max ? amountValue : selectedCreditLine.amount.max.toString())
}}
/>
<SliderField
className={classes.sliderField}
title="Quantos meses para pagar?"
min={selectedCreditLine?.paymentMonths.min || 0}
max={selectedCreditLine?.paymentMonths.max || 12}
marks={
selectedCreditLine
? [
{ value: selectedCreditLine.paymentMonths.min, label: `${selectedCreditLine.paymentMonths.min} meses` },
{ value: selectedCreditLine.paymentMonths.max, label: `${selectedCreditLine.paymentMonths.max} meses` },
]
: [
{ value: 0, label: '0 meses' },
{ value: 12, label: '' },
]
}
valueSlider={Number(paymentMonths)}
valueField={paymentMonths.toString() + ' meses'}
disabled={!selectedCreditLine}
onChangeSlider={(_, value) => setPaymentMonths(value as number)}
onChangeField={(evt) => setPaymentMonths(Number(evt.target.value))}
onBlurField={(evt) => {
const paymentMonthsValue = Number(extractNumbers(evt.target.value))
if (selectedCreditLine)
setPaymentMonths(
paymentMonthsValue <= selectedCreditLine.paymentMonths.max ? paymentMonthsValue : selectedCreditLine.paymentMonths.max
)
}}
/>
<SliderField
className={classes.sliderField}
title="Quantos meses de carência?"
min={selectedCreditLine?.graceMonths.min || 0}
max={selectedCreditLine?.graceMonths.max || 12}
marks={
selectedCreditLine
? [
{ value: selectedCreditLine.graceMonths.min, label: `${selectedCreditLine.graceMonths.min} meses` },
{ value: selectedCreditLine.graceMonths.max, label: `${selectedCreditLine.graceMonths.max} meses` },
]
: [
{ value: 0, label: '0 meses' },
{ value: 12, label: '' },
]
}
valueSlider={Number(graceMonths)}
valueField={graceMonths.toString() + ' meses'}
disabled={!selectedCreditLine}
onChangeSlider={(_, value) => setGraceMonths(value as number)}
onChangeField={(evt) => setGraceMonths(Number(evt.target.value))}
onBlurField={(evt) => {
const graceMonthsValue = Number(extractNumbers(evt.target.value))
if (selectedCreditLine)
setGraceMonths(graceMonthsValue <= selectedCreditLine.graceMonths.max ? graceMonthsValue : selectedCreditLine.graceMonths.max)
}}
/>
<div className={classes.btnContainer}>
<Button disabled={!selectedCreditLine} variant="contained" color="secondary" onClick={handleSimulate}>
Simular
</Button>
</div>
</div>
</div>
</div>
)
}
export default withStyles(styles)(CreditLinesList)
import React from 'react'
import { Slider, SliderProps, TextField, TextFieldProps, Typography } from '@material-ui/core'
type ExtendedProps = Record<string, unknown>
interface Props extends ExtendedProps {
title: string
min: SliderProps['min']
max: SliderProps['max']
marks?: SliderProps['marks']
valueSlider: number
valueField: string
step?: SliderProps['step']
onChangeSlider: (event: React.ChangeEvent<Record<string, unknown>>, value: number | number[]) => void
onChangeField: TextFieldProps['onChange']
onBlurField: TextFieldProps['onBlur']
disabled: boolean
className?: string
}
const SliderField = (props: Props) => {
const { className, title, min, max, marks, valueSlider, valueField, step = 1, disabled, onChangeSlider, onChangeField, onBlurField } = props
return (
<div className={className}>
<Typography gutterBottom>{title}</Typography>
<Slider
disabled={disabled}
min={min}
max={max}
value={valueSlider}
onChange={onChangeSlider}
// valueLabelDisplay="auto"
step={step}
marks={marks}
/>
<TextField style={{ width: '12%' }} disabled={disabled} value={valueField} onChange={onChangeField} onBlur={onBlurField} />
</div>
)
}
export default SliderField
export { default } from './CreditLinesList'
export * from './CreditLinesList'
import { Theme } from '@material-ui/core/styles'
import { createStyles } from '@material-ui/styles'
import sharedStyles from '../shared-styles'
// eslint-disable-next-line
export default (theme: Theme) =>
createStyles({
...sharedStyles(theme),
contentContainer: { display: 'flex', justifyContent: 'center', width: '100%' },
content: { display: 'flex', flexDirection: 'column', alignItems: 'center', width: '50%' },
creditLinesAutocomplete: { width: '100%' },
description: { margin: theme.spacing(2), width: '100%' },
sliderField: { textAlign: 'center', width: '100%', marginBottom: theme.spacing(3) },
btnContainer: { width: '100%', textAlign: 'right', marginBottom: theme.spacing(2) },
})
import React, { useEffect, useMemo } from 'react'
import { formatCurrency } from '@agiliza/utils/formatters'
import { Grid } from '@material-ui/core'
import { withStyles, WithStyles } from '@material-ui/core/styles'
import { creditLinesData } from '../../../../../__mocks__/creditLines'
import GridLine from './GridLine'
import styles from './styles'
type ExtendedProps = WithStyles<typeof styles>
interface Props extends ExtendedProps {
id: string
onChangeCanGoForward: (vl: boolean) => void
}
const CreditLinesInfo = (props: Props) => {
const { classes, id, onChangeCanGoForward } = props
const creditLine = useMemo(() => creditLinesData[id], [id])
useEffect(() => {
onChangeCanGoForward(true)
}, [])
return (
<div className={classes.contentContainer}>
<div className={classes.content}>
<Grid container className={classes.gridContainer}>
<GridLine label="Número de parcelas" value={creditLine?.paymentMonths} />
<GridLine label="Valor das parcelas" value={formatCurrency(creditLine?.amount.toFixed(2))} />
<GridLine label="Taxa de juros" value={`${creditLine?.interestRate} %`} />
<GridLine label="Custo efetivo total (CET)" value={`${creditLine?.effectiveTotalCost} %`} />
<GridLine label="Taxa abertura crédito (TAC)" value={formatCurrency(creditLine?.openingCreditRate.toFixed(2))} />
</Grid>
</div>
</div>
)
}
export default withStyles(styles)(CreditLinesInfo)
import React from 'react'
import { Grid, Typography } from '@material-ui/core'
type ExtendedProps = Record<string, unknown>
interface Props extends ExtendedProps {
label: string
value: string | number
}
const GridLine = (props: Props) => {
const { label, value } = props
return (
<>
<Grid item xs={10}>
<Typography variant="h5">{label}</Typography>
</Grid>
<Grid item xs={2} style={{ whiteSpace: 'nowrap' }}>
<Typography variant="h5">{value}</Typography>
</Grid>
</>
)
}
export default GridLine
export { default } from './CreditLinesInfo'
export * from './CreditLinesInfo'
import { Theme } from '@material-ui/core/styles'
import { createStyles } from '@material-ui/styles'
import sharedStyles from '../styles'
// eslint-disable-next-line
export default (theme: Theme) =>
createStyles({
...sharedStyles(theme),
gridContainer: {},
gridItem: { whiteSpace: 'nowrap' },
})
import React, { useMemo, useState } from 'react'
import { RouteComponentProps, useLocation } from 'react-router'
import { PATHS } from '@agiliza/views/Main/DrawerItems'
import { Button, Step, StepLabel, Stepper } from '@material-ui/core'
import { withStyles, WithStyles } from '@material-ui/core/styles'
import {
KeyboardArrowLeft as KeyboardArrowLeftIcon,
KeyboardArrowRight as KeyboardArrowRightIcon
} from '@material-ui/icons'
import CreditLinesInfo from './CreditLinesInfo'
import styles from './styles'
import UserForm from './UserForm'
import VerificationCode from './VerificationCode'
type ExtendedProps = WithStyles<typeof styles> & RouteComponentProps
interface Props extends ExtendedProps {}
const Simulation = (props: Props) => {
const { classes, history } = props
// const theme = useTheme()
const { state: lState } = useLocation<{ id: string }>()
const [activeStep, setActiveStep] = useState(0)
const [canGoForward, setCanGoForward] = useState(true)
const handleChangeCanGoForward = (value: boolean) => {
setCanGoForward(value)
}
const renderStep = (step: number) => {
switch (step) {
case 0:
return <CreditLinesInfo id={lState.id} onChangeCanGoForward={handleChangeCanGoForward} />
case 1:
return <UserForm onChangeCanGoForward={handleChangeCanGoForward} />
case 2:
return <VerificationCode onChangeCanGoForward={handleChangeCanGoForward} />
}
}
const handleNext = () => {
if (activeStep === steps - 1) history.push({ pathname: PATHS.creditLines })
else setActiveStep((prevActiveStep) => prevActiveStep + 1)
}
const handleBack = () => {
setActiveStep((prevActiveStep) => prevActiveStep - 1)
}
const steps = useMemo(() => 3, [])
return (
<div className={classes.pageContent}>
<div className={classes.stepContentContainer}>{renderStep(activeStep)}</div>
<div className={classes.stepperContainer}>
<Button size="large" onClick={handleBack} disabled={activeStep === 0} className={classes.stepperBtn}>
<KeyboardArrowLeftIcon />
Anterior
</Button>
<Stepper activeStep={activeStep} alternativeLabel className={classes.stepper}>
<Step>
<StepLabel>Informações linha de crédito</StepLabel>
</Step>
<Step>
<StepLabel>Dados pessoais</StepLabel>
</Step>
<Step>
<StepLabel>Código de verificação</StepLabel>
</Step>
</Stepper>
<Button size="large" onClick={handleNext} disabled={!canGoForward} className={classes.stepperBtn}>
{activeStep === steps - 1 ? (
'Finalizar'
) : (
<>
Próximo
<KeyboardArrowRightIcon />
</>
)}
</Button>
{/* <MobileStepper
variant="dots"
steps={steps}
position="static"
activeStep={activeStep}
className={classes.stepper}
nextButton={
<Button size="small" onClick={handleNext} disabled={!canGoForward || activeStep === steps}>
Próximo
<KeyboardArrowRightIcon />
</Button>
}
backButton={
<Button size="small" onClick={handleBack} disabled={!canGoBackward || activeStep === 0}>
<KeyboardArrowLeftIcon />
Anterior
</Button>
}
/> */}
</div>
</div>
)
}
export default withStyles(styles)(Simulation)
import React, { useEffect, useState } from 'react'
import { formatPhone } from '@agiliza/utils/formatters'
import {
getErrorProps,
invalidState,
useErrorValidator,
Validators,
validState
} from '@agiliza/utils/hooks/errorValidation'
import { isValidEmail, isValidPhone } from '@agiliza/utils/validators'
import { TextField, TextFieldProps } from '@material-ui/core'
import { withStyles, WithStyles } from '@material-ui/core/styles'
import styles from './styles'
interface UserFormFieldProps extends Pick<TextFieldProps, 'label' | 'value' | 'onChange' | 'error' | 'helperText' | 'inputProps'> {}
const UserFormField = ({ helperText, ...props }: UserFormFieldProps) => <TextField fullWidth margin="normal" variant="outlined" {...props} />
interface State {
name: string
phoneNumber: string
email: string
}
const validators: Validators<Partial<State>> = {
phoneNumber: (vl) => (isValidPhone(vl) ? validState(vl) : invalidState(vl, '')),
email: (vl) => (isValidEmail(vl) ? validState(vl) : invalidState(vl, '')),
}
type ExtendedProps = WithStyles<typeof styles>
interface Props extends ExtendedProps {
onChangeCanGoForward: (vl: boolean) => void
}
const UserForm = (props: Props) => {
const { classes, onChangeCanGoForward } = props
const [state, setState] = useState<State>({ email: '', phoneNumber: '', name: '' })
const { name, phoneNumber, email } = state
const { errorState, validState: isValidState, actions } = useErrorValidator({ email: '', phoneNumber: '', name: '' }, validators)
useEffect(() => {
onChangeCanGoForward(isValidState)
}, [])
useEffect(() => {
onChangeCanGoForward(isValidState)
}, [isValidState])
const handleChange =
(key: keyof State): TextFieldProps['onChange'] =>
(evt) => {
setState({ ...state, [key]: evt.target.value })
actions.validate({ [key]: evt.target.value })
}
return (
<div className={classes.contentContainer}>
<div className={classes.content}>
<UserFormField label="Nome" value={name} onChange={handleChange('name')} {...getErrorProps(errorState.name)} />
<UserFormField
label="Número de celular"
value={formatPhone(phoneNumber)}
onChange={handleChange('phoneNumber')}
inputProps={{ maxLength: 15 }}
{...getErrorProps(errorState.phoneNumber)}
/>
<UserFormField label="Email" value={email} onChange={handleChange('email')} {...getErrorProps(errorState.email)} />
</div>
</div>
)
}
export default withStyles(styles)(UserForm)
export { default } from './UserForm'
export * from './UserForm'
import { Theme } from '@material-ui/core/styles'
import { createStyles } from '@material-ui/styles'
import sharedStyles from '../styles'
// eslint-disable-next-line
export default (theme: Theme) =>
createStyles({
...sharedStyles(theme),
gridContainer: {},
gridItem: { whiteSpace: 'nowrap' },
})
import React, { useEffect, useState } from 'react'
import { extractNumbers } from '@agiliza/utils/extractors'
import { TextField, TextFieldProps, Typography } from '@material-ui/core'
import { withStyles, WithStyles } from '@material-ui/core/styles'
import styles from './styles'
type ExtendedProps = WithStyles<typeof styles>
interface Props extends ExtendedProps {
onChangeCanGoForward: (vl: boolean) => void
}
const VerificationCode = (props: Props) => {
const { classes, onChangeCanGoForward } = props
const [code, setCode] = useState('')
useEffect(() => {
onChangeCanGoForward(code.length === 6)
}, [code])
const handleChange: TextFieldProps['onChange'] = (evt) => {
setCode(extractNumbers(evt.target.value))
}
return (
<div className={classes.contentContainer}>
<div className={classes.content}>
<Typography variant="h5">Foi enviado um código de verificação por email.</Typography>
<TextField
label="Código de verificação"
value={code}
onChange={handleChange}
variant="outlined"
className={classes.codeField}
inputProps={{ maxLength: 6 }}
/>
</div>
</div>
)
}
export default withStyles(styles)(VerificationCode)
export { default } from './VerificationCode'
export * from './VerificationCode'
import { Theme } from '@material-ui/core/styles'
import { createStyles } from '@material-ui/styles'
import sharedStyles from '../styles'
// eslint-disable-next-line
export default (theme: Theme) =>
createStyles({
...sharedStyles(theme),
codeField: { marginTop: theme.spacing(5) },
})
export { default } from './Simulation'
export * from './Simulation'
import { Theme } from '@material-ui/core/styles'
import { createStyles } from '@material-ui/styles'
import sharedStyles from '../shared-styles'
// eslint-disable-next-line
export default (theme: Theme) =>
createStyles({
...sharedStyles(theme),
contentContainer: { display: 'flex', justifyContent: 'center', width: '100%' },
content: { display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', width: '35%' },
stepContentContainer: { display: 'flex', flexDirection: 'column', justifyContent: 'center', flexGrow: 1 },
stepperContainer: { display: 'flex', alignItems: 'center', justifyContent: 'center' },
stepper: { flexGrow: 1 },
stepperBtn: { height: '100%' },
})
import React, { lazy, Suspense } from 'react'
import { Redirect, Route, RouteComponentProps, Switch } from 'react-router'
import NotFound from '@agiliza/components/templates/NotFound'
import { CircularProgress } from '@material-ui/core'
import { withStyles, WithStyles } from '@material-ui/core/styles'
import styles from './shared-styles'
const CreditLinesList = lazy(() => import('./CreditLinesList'))
const Simulation = lazy(() => import('./Simulation'))
export const CREDIT_LINES_PATHS = {
creditLinesList: '/selecionarLinhaCredito',
simulation: '/simulador',
}
type ExtendedProps = WithStyles<typeof styles> & RouteComponentProps
interface Props extends ExtendedProps {}
const CreditLinesRouter = (props: Props) => {
const { classes, match } = props
return (
<div className={classes.pageContainer}>
<Suspense fallback={<CircularProgress className={classes.circularProgress} />}>
<Switch>
<Route exact path={match.path + CREDIT_LINES_PATHS.creditLinesList} render={(rProps) => <CreditLinesList fetching={false} {...rProps} />} />
<Route
exact
path={match.path + CREDIT_LINES_PATHS.simulation}
render={(rProps) => {
const { location } = rProps as RouteComponentProps<any, any, { id: string }>
if (location.state?.id) return <Simulation {...rProps} />
else return <NotFound {...rProps} />
}}
/>
<Redirect from={match.path} to={match.path + CREDIT_LINES_PATHS.creditLinesList} />
</Switch>
</Suspense>
</div>
)
}
export default withStyles(styles)(CreditLinesRouter)
import sharedStyles from '@agiliza/views/shared-styles'
import { Theme } from '@material-ui/core/styles'
import { createStyles } from '@material-ui/styles'
// eslint-disable-next-line
export default (theme: Theme) =>
createStyles({
...sharedStyles(theme),
circularProgressContainer: {
display: 'flex',
width: '100%',
height: '100%',
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
circularProgress: { position: 'absolute', top: '50%', left: '50%' },
title: { marginBottom: theme.spacing(2) },
})
import { createHashHistory } from 'history'
import React, { lazy, Suspense, useEffect } from 'react'
import { connect } from 'react-redux'
import { Route, Router, Switch } from 'react-router'
import { bindActionCreators, Dispatch } from 'redux'
import AuthRoute from '@agiliza/components/atoms/AuthRoute'
import CircularProgress from '@agiliza/components/molecules/CircularProgress'
import { ConfigService } from '@agiliza/curio/SessionManager'
import { StoreState } from '@agiliza/redux'
import { actions as sessionActions } from '@agiliza/redux/session'
import {
getServiceInfo,
isAuthenticated,
isAuthenticating,
isInitializing
} from '@agiliza/redux/session/selectors'
import { actions as drawerActions } from '@agiliza/redux/ui/drawer'
import { isDrawerOpen } from '@agiliza/redux/ui/drawer/selectors'
import { getError } from '@agiliza/redux/ui/error/selectors'
const Login = lazy(() => import('./Login'))
const Main = lazy(() => import('./Main'))
const history = createHashHistory()
interface Props {
error: string
authenticated: boolean
authenticating: boolean
initialize: typeof sessionActions.initialize
serviceInfo?: ConfigService
}
const Views = (props: Props) => {
const { authenticating, serviceInfo, initialize } = props
useEffect(() => {
initialize()
}, [])
if (authenticating) return <CircularProgress root />
return (
<Router history={history}>
<Suspense fallback={<CircularProgress />}>
<Switch>
<Route path="/login" render={(renderProps) => <Login {...renderProps} service={serviceInfo} />} />
<AuthRoute path="/" component={Main} />
</Switch>
</Suspense>
</Router>
)
}
const mapStateToProps = (state: StoreState) => ({
error: getError(state.ui.error),
authenticated: isAuthenticated(state.session),
authenticating: isAuthenticating(state.session) || isInitializing(state.session),
serviceInfo: getServiceInfo(state.session),
drawerOpen: isDrawerOpen(state.ui.drawer),
})
const mapDispatchToProps = (dispatch: Dispatch) =>
bindActionCreators(
{
toggleDrawer: drawerActions.toggleDrawer,
initialize: sessionActions.initialize,
},
dispatch
)
export default connect(mapStateToProps, mapDispatchToProps)(Views)
import { Theme } from '@material-ui/core'
import { createStyles } from '@material-ui/core/styles'
// import sharedStyles from '../../shared-styles'
export default (theme: Theme) => {
const display = 'flex'
return createStyles({
pageContainer: {
height: '100vh',
display: 'flex',
flexDirection: 'column',
// padding: theme.spacing(2),
paddingTop: 0,
paddingBottom: 0,
justifyContent: 'flex-start',
},
pageContent: {
height: `calc(100vh - ${theme.mixins.toolbar.minHeight}px)`,
padding: theme.spacing(2),
display: 'flex',
flexDirection: 'column',
},
title: {
flexGrow: 1,
fontSize: '100%',
},
circularProgress: { position: 'absolute', top: '50%', left: '50%' },
container: { display: 'flex', flexDirection: 'column', flex: 1, height: '100%' },
inputContainer: { display, flexWrap: 'wrap' },
form: { display, flexWrap: 'wrap', alignItems: 'center' },
formContent: {
marginRight: theme.spacing(3),
flexWrap: 'wrap',
display,
flexDirection: 'column',
width: '85%',
},
})
}
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
/*Modified paths, e.g. @projectName/.../, required modify webpack: resolve->alias*/
"@agiliza/api": ["src/api"],
"@agiliza/api/*": ["src/api/*"],
"@agiliza/constants": ["src/constants"],
"@agiliza/constants/*": ["src/constants/*"],
"@agiliza/config": ["src/config"],
"@agiliza/config/*": ["src/config/*"],
"@agiliza/theme": ["src/theme"],
"@agiliza/theme/*": ["src/theme/*"],
"@agiliza/curio": ["src/curio"],
"@agiliza/curio/*": ["src/curio/*"],
"@agiliza/utils": ["src/utils"],
"@agiliza/utils/*": ["src/utils/*"],
"@agiliza/redux": ["src/redux"],
"@agiliza/redux/*": ["src/redux/*"],
"@agiliza/epics": ["src/epics"],
"@agiliza/epics/*": ["src/epics/*"],
"@agiliza/components": ["src/components"],
"@agiliza/components/*": ["src/components/*"],
"@agiliza/views": ["src/views"],
"@agiliza/views/*": ["src/views/*"],
"@agiliza/public": ["public"],
"@agiliza/public/*": ["public/*"]
},
"removeComments": true,
"preserveConstEnums": true,
"sourceMap": true,
"declaration": false,
"noImplicitAny": false,
"noImplicitThis": true,
"target": "ESNext",
"lib": ["dom", "esnext"],
"outDir": "./tsDist",
"allowJs": true,
"checkJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": false,
"noEmit": true,
"jsx": "preserve",
"noUnusedLocals": true,
"pretty": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"typeRoots": ["node_modules/@types", "src/typings"]
},
"include": ["src"],
"exclude": ["node_modules", "dist", "public"]
}
// eslint-disable
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const webpack = require('webpack')
const CleanWebpackPlugin = require('clean-webpack-plugin').CleanWebpackPlugin
const CopyWebpackPlugin = require('copy-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const ForkTSCheckerPlugin = require('fork-ts-checker-webpack-plugin')
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin')
const pathResolve = (pth) => path.resolve(__dirname, pth)
const SRC = path.join(__dirname, 'src')
const PUBLIC = path.join(__dirname, 'public')
const DIST = path.join(__dirname, 'dist')
const defaultEnv = {
production: false,
port: 3000,
analyze: false,
}
const babelLoader = {
loader: require.resolve('babel-loader'),
options: {
cacheDirectory: true,
babelrc: true,
configFile: pathResolve('babel.config.json'),
},
}
const tsRule = (env) => ({
test: /\.ts(x?)$/,
use: [
babelLoader,
{
loader: require.resolve('ts-loader'),
options: {
transpileOnly: true,
configFile: path.join(__dirname, 'tsconfig.json'),
},
},
],
})
const cssLoader = (env) => ({
test: /\.css$/,
use: [
env.production
? MiniCssExtractPlugin.loader // injeta tags de link para os arquivos css no html
: 'style-loader', // injeta o css processados diretamente no arquivo html
{
loader: 'css-loader',
options: {
modules: { localIdentName: '[name]_[local]_[hash:base64:5]' },
sourceMap: !env.production,
url: false,
},
},
'postcss-loader', // cria uma AST dos arquivos .css para serem processados por plugins
],
})
const fileLoader = {
include: /public/,
exclude: /\.ejs$/,
type: 'asset/resource',
generator: {
filename: (pathdata) =>
pathdata.filename.endsWith('.ttf') || pathdata.filename.endsWith('.txt')
? 'fonts/[hash][ext]'
: pathdata.filename.endsWith('.json')
? 'config.json'
: 'images/[hash][ext]',
},
}
const resolve = {
alias: {
'@agiliza/api': pathResolve('src/api'),
'@agiliza/theme': pathResolve('src/theme'),
'@agiliza/constants': pathResolve('src/constants'),
'@agiliza/components': pathResolve('src/components'),
'@agiliza/curio': pathResolve('src/curio'),
'@agiliza/redux': pathResolve('src/redux'),
'@agiliza/epics': pathResolve('src/epics'),
'@agiliza/views': pathResolve('src/views'),
'@agiliza/utils': pathResolve('src/utils'),
'@agiliza/public': pathResolve('public'),
'@material-ui/styles': path.resolve('.', 'node_modules', '@material-ui/styles'),
}, // Modified paths, modify tsconfig.json "paths"
extensions: ['.ts', '.tsx', '.js'],
}
const makeCommonPlugins = (env) => [
new MiniCssExtractPlugin({
chunkFilename: env.production ? 'styles/[id].[contenthash].css' : 'styles/[id].css',
filename: env.production ? 'styles/[name].[contenthash].css' : 'styles/[name].css',
}),
new CleanWebpackPlugin(),
new ForkTSCheckerPlugin({
typescript: {
configFile: path.join(__dirname, 'tsconfig.json'),
},
eslint: {
files: './**/*.{ts,tsx}', // required - same as command `eslint ./src/**/*.{ts,tsx,js,jsx} --ext .ts,.tsx,.js,.jsx`
},
}),
new webpack.ProvidePlugin({
process: 'process/browser',
}),
new webpack.EnvironmentPlugin({
PUBLIC_PATH: '/',
NODE_ENV: env.production ? 'production' : 'development',
APP_TITLE: 'Agiliza',
}),
new HtmlWebpackPlugin({
template: path.join(__dirname, 'public', 'index.ejs'),
favicon: path.join(PUBLIC, 'images', 'favicon.png'),
title: 'Agiliza',
inject: false,
}),
new webpack.DefinePlugin({
VERSION: JSON.stringify(require('./package.json').version),
}),
]
const makeDevPlugins = (env) => [...makeCommonPlugins(env)]
const makeProdPlugins = (env) => [
...makeCommonPlugins(env),
new CopyWebpackPlugin({
patterns: [
{
from: PUBLIC,
to: DIST,
globOptions: { ignore: ['**/*.ejs', '**/*.png'] },
},
],
}),
]
const output = (env) => ({
chunkFilename: env.production ? 'js/chunks/[name].[chunkhash].js' : 'js/chunks/[name].js',
filename: env.production ? 'js/[name].[contenthash].js' : 'js/[name].js',
path: DIST,
publicPath: '/',
})
const devServer = (env) => ({
contentBase: PUBLIC,
disableHostCheck: true,
port: env.port,
stats: {
all: false,
modules: true,
maxModules: 0,
errors: true,
warnings: false,
version: true,
colors: true,
},
inline: true,
host: '0.0.0.0',
historyApiFallback: true,
})
module.exports = (env) => {
env = { ...defaultEnv, ...env }
return {
context: SRC,
mode: env.production ? 'production' : 'development',
entry: ['./index.tsx'],
devtool: env.production ? undefined : 'eval-cheap-module-source-map',
devServer: devServer(env),
module: {
rules: [cssLoader(env), fileLoader, tsRule(env)],
},
plugins: env.production ? makeProdPlugins(env) : makeDevPlugins(env),
resolve,
output: output(env),
optimization: {
minimize: true,
minimizer: [
// For webpack@5 you can use the `...` syntax to extend existing minimizers (i.e. `terser-webpack-plugin`), uncomment the next line
`...`,
new CssMinimizerPlugin(),
],
},
}
}
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment