mirror of
https://github.com/ragestudio/comty.git
synced 2025-06-09 02:24:16 +00:00
core release
This commit is contained in:
commit
c5e5ecf576
16
.editorconfig
Normal file
16
.editorconfig
Normal file
@ -0,0 +1,16 @@
|
||||
# http://editorconfig.org
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[Makefile]
|
||||
indent_style = tab
|
7
.eslintignore
Normal file
7
.eslintignore
Normal file
@ -0,0 +1,7 @@
|
||||
src/**/*-test.js
|
||||
src/public
|
||||
src/routes/chart/ECharts/theme
|
||||
src/routes/chart/highCharts/mapdata
|
||||
src/locales/_build/
|
||||
src/locales/**/*.js
|
||||
docs/**/*.js
|
8
.eslintrc
Normal file
8
.eslintrc
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "react-app",
|
||||
"rules": {
|
||||
"jsx-a11y/href-no-hash": "off",
|
||||
"no-console": "warn",
|
||||
"valid-jsdoc": "warn"
|
||||
}
|
||||
}
|
29
.gitignore
vendored
Normal file
29
.gitignore
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
coverage
|
||||
dist
|
||||
node_modules
|
||||
npm-debug.log
|
||||
yarn-error.log
|
||||
yarn.lock
|
||||
package-lock.json
|
||||
|
||||
# ide
|
||||
.idea
|
||||
|
||||
# Mac General
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
|
||||
# umi
|
||||
.umi
|
||||
.umi-production
|
||||
|
||||
# jslingui
|
||||
src/locales/_build
|
||||
src/locales/**/*.js
|
||||
recover/
|
||||
|
||||
.env
|
||||
.env
|
||||
.env
|
||||
sockets/rs_develop
|
6
.prettierignore
Normal file
6
.prettierignore
Normal file
@ -0,0 +1,6 @@
|
||||
*.svg
|
||||
*.ejs
|
||||
.DS_Store
|
||||
.umi
|
||||
.umi-production
|
||||
src/locales/**/*.json
|
5
.prettierrc
Normal file
5
.prettierrc
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"semi": false,
|
||||
"singleQuote": true,
|
||||
"trailingComma": "es5"
|
||||
}
|
9
.stylelintrc.json
Normal file
9
.stylelintrc.json
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"extends": ["stylelint-config-standard", "stylelint-config-prettier"],
|
||||
"rules": {
|
||||
"declaration-empty-line-before": null,
|
||||
"no-descending-specificity": null,
|
||||
"selector-pseudo-class-no-unknown": null,
|
||||
"selector-pseudo-element-colon-notation": null
|
||||
}
|
||||
}
|
27
.travis.yml
Normal file
27
.travis.yml
Normal file
@ -0,0 +1,27 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- node
|
||||
script:
|
||||
- npm run build
|
||||
before_install:
|
||||
- |
|
||||
if [ "$TRAVIS_BRANCH" = "develop" ]; then
|
||||
for prefixed_envvar in ${!DEV_*}; do
|
||||
eval export ${prefixed_envvar#DEV_}="${!prefixed_envvar}"
|
||||
done
|
||||
elif [ "$TRAVIS_BRANCH" = "master" ]; then
|
||||
for prefixed_envvar in ${!PROD_*}; do
|
||||
eval export ${prefixed_envvar#PROD_}="${!prefixed_envvar}"
|
||||
done
|
||||
else
|
||||
for prefixed_envvar in ${!TEST_*}; do
|
||||
eval export ${prefixed_envvar#TEST_}="${!prefixed_envvar}"
|
||||
done
|
||||
fi
|
||||
- openssl aes-256-cbc -K $encrypted_18b2305b78c9_key -iv $encrypted_18b2305b78c9_iv -in config/id_rsa.enc -out ~/.ssh/id_rsa -d
|
||||
- chmod 600 ~/.ssh/id_rsa
|
||||
- echo -e "Host $HOST\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config
|
||||
- yarn global add now
|
||||
after_script:
|
||||
- scp -o stricthostkeychecking=no -r ./dist root@$HOST:$BUILD_DIR
|
||||
- cd ./docs && now -A $DOC_NOW_CONFIG -t $NOW_TOKEN && now alias -A $DOC_NOW_CONFIG -t $NOW_TOKEN
|
92
.umirc.js
Normal file
92
.umirc.js
Normal file
@ -0,0 +1,92 @@
|
||||
// https://umijs.org/config/
|
||||
import { resolve } from 'path';
|
||||
import { i18n } from './config/ycore.config.js';
|
||||
export default {
|
||||
ignoreMomentLocale: true,
|
||||
targets: {
|
||||
ie: 9,
|
||||
},
|
||||
treeShaking: true,
|
||||
plugins: [
|
||||
[
|
||||
'umi-plugin-react',
|
||||
{
|
||||
dva: {
|
||||
immer: true,
|
||||
hmr: true,
|
||||
},
|
||||
antd: true,
|
||||
dynamicImport: {
|
||||
webpackChunkName: true,
|
||||
loadingComponent: './components/Loader/Loader',
|
||||
},
|
||||
routes: {
|
||||
exclude: [
|
||||
/model\.(j|t)sx?$/,
|
||||
/service\.(j|t)sx?$/,
|
||||
/models\//,
|
||||
/components\//,
|
||||
/services\//,
|
||||
],
|
||||
update: routes => {
|
||||
if (!i18n) return routes;
|
||||
const newRoutes = [];
|
||||
|
||||
for (const item of routes[0].routes) {
|
||||
newRoutes.push(item);
|
||||
|
||||
if (item.path) {
|
||||
newRoutes.push(
|
||||
Object.assign({}, item, {
|
||||
path: `/:lang(${i18n.languages.map(item => item.key).join('|')})` + item.path,
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
routes[0].routes = newRoutes;
|
||||
return routes;
|
||||
},
|
||||
},
|
||||
dll: false,
|
||||
pwa: {
|
||||
manifestOptions: {
|
||||
srcPath: 'manifest.json',
|
||||
},
|
||||
},
|
||||
hd: false,
|
||||
},
|
||||
],
|
||||
],
|
||||
// Theme for antd
|
||||
// https://ant.design/docs/react/customize-theme
|
||||
theme: './config/theme.config.js',
|
||||
// Webpack Configuration
|
||||
alias: {
|
||||
sockets: resolve(__dirname, './sockets'),
|
||||
ycore: resolve(__dirname, './src/ycore_worker.tsx'),
|
||||
ycstyle: resolve(__dirname, './src/ycore_style.scss'),
|
||||
api: resolve(__dirname, './src/services/'),
|
||||
components: resolve(__dirname, './src/components'),
|
||||
widgets: resolve(__dirname, './src/widgets'),
|
||||
config: resolve(__dirname, './config/ycore.config.js'),
|
||||
models: resolve(__dirname, './src/models'),
|
||||
routes: resolve(__dirname, './src/routes'),
|
||||
services: resolve(__dirname, './src/services'),
|
||||
themes: resolve(__dirname, './src/themes'),
|
||||
utils: resolve(__dirname, './src/utils'),
|
||||
},
|
||||
extraBabelPresets: ['@lingui/babel-preset-react'],
|
||||
extraBabelPlugins: [
|
||||
[
|
||||
'import',
|
||||
{
|
||||
libraryName: 'lodash',
|
||||
libraryDirectory: '',
|
||||
camel2DashComponentName: false,
|
||||
},
|
||||
'lodash',
|
||||
],
|
||||
],
|
||||
};
|
||||
|
201
LICENSE
Normal file
201
LICENSE
Normal file
@ -0,0 +1,201 @@
|
||||
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.
|
BIN
config/id_rsa.enc
Normal file
BIN
config/id_rsa.enc
Normal file
Binary file not shown.
3
config/keys.js
Normal file
3
config/keys.js
Normal file
@ -0,0 +1,3 @@
|
||||
module.exports = {
|
||||
secretOrKey: "secret"
|
||||
};
|
8
config/theme.config.js
Normal file
8
config/theme.config.js
Normal file
@ -0,0 +1,8 @@
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const lessToJs = require('less-vars-to-js')
|
||||
|
||||
module.exports = () => {
|
||||
const themePath = path.join(__dirname, '../src/themes/default.less')
|
||||
return lessToJs(fs.readFileSync(themePath, 'utf8'))
|
||||
}
|
69
config/ycore.config.js
Normal file
69
config/ycore.config.js
Normal file
@ -0,0 +1,69 @@
|
||||
module.exports = {
|
||||
siteName: 'Comty',
|
||||
copyright: 'RageStudio©',
|
||||
logoPath: '/logo.svg',
|
||||
FullLogoPath: '/full_logo.svg',
|
||||
apiPrefix: '/api/v1',
|
||||
fixedHeader: true, // sticky primary layout header
|
||||
|
||||
App_Config: {
|
||||
InitRes: { width: 1000, height: 900},
|
||||
InitOpenConsole: true,
|
||||
},
|
||||
|
||||
/* Layout configuration, specify which layout to use for route. */
|
||||
layouts: [
|
||||
{
|
||||
name: 'primary',
|
||||
include: [/.*/],
|
||||
exclude: [/\/login/, /\/socket\/(.*)/, /\/publics/, /\/authorize/],
|
||||
},
|
||||
],
|
||||
yConfig: {
|
||||
// Disused Variables, exported from yCoreWorker
|
||||
// Global Server Key (Requiered for RS-YIBTP), Not autogenerated, must be included on. (Recommended not modify this constants)
|
||||
server_key: "f706b0a535b6c2d36545c4137a0a3a26853ea8b5-1223c9ba7923152cae28e5a2e7501b2b-50600768",
|
||||
openwheater_apiKey:'2acf34be0b8f033b89ba4de1e674d42a',
|
||||
},
|
||||
Endpoints: {
|
||||
auth_endpoint: "https://api.ragestudio.net/RS-YIBTP/yid/auth",
|
||||
get_servicesHandler: 'https://api.ragestudio.net/RS-YIBTP/rs/servicesHandler',
|
||||
get_modhandler: "https://api.ragestudio.net/RS-YIBTP/rs/modHandler",
|
||||
get_subscriptionHandler: "https://api.ragestudio.net/RS-YIBTP/rs/subscriptionHandler",
|
||||
get_marketplace_global: "https://api.ragestudio.net/RS-YIBTP/rs/marketplaceHandler?access_token=",
|
||||
get_config_endpoint: "https://api.ragestudio.net/RS-YIBTP/yid/get-site-settings?access_token=",
|
||||
get_userData_endpoint: "https://api.ragestudio.net/RS-YIBTP/yid/get-user-data?access_token=",
|
||||
update_userData_endpoint: "https://api.ragestudio.net/RS-YIBTP/yid/update-user-data?access_token=",
|
||||
removeToken: "https://api.ragestudio.net/RS-YIBTP/yid/delete-access-token?access_token=",
|
||||
register_endpoint: "https://api.ragestudio.net/RS-YIBTP/yid/create-account",
|
||||
resetPassword_endpoint: "https://api.ragestudio.net/RS-YIBTP/yid/send-reset-password-email?access_token=",
|
||||
logotype_uri: 'https://api.ragestudio.net/branding/svg/STUDIO-JETBLACK-Generic_template.png',
|
||||
},
|
||||
DevOptions: {
|
||||
defaultSettings: [{id: 'strict_lightMode', value: false}, {id: 'force_collapse', value: false}, {id: 'force_showDevLogs', value: true}],
|
||||
|
||||
// Global Behaviors
|
||||
InfiniteLoading: false,
|
||||
InfiniteLogin: false,
|
||||
InfiniteRegister: false,
|
||||
DisableLogin: false,
|
||||
DisableRegister: true,
|
||||
DisablePasswordRecover: true,
|
||||
// Activating this, the logs must be trowed
|
||||
ShowFunctionsLogs: true,
|
||||
StrictLightMode: false
|
||||
},
|
||||
/* I18n configuration, `languages` and `defaultLanguage` are required currently. */
|
||||
i18n: {
|
||||
/* Countrys flags: https://www.flaticon.com/packs/countrys-flags */
|
||||
languages: [
|
||||
{
|
||||
key: 'en',
|
||||
title: 'English',
|
||||
},
|
||||
],
|
||||
defaultLanguage: 'en',
|
||||
},
|
||||
}
|
||||
|
||||
|
3
jest.config.js
Normal file
3
jest.config.js
Normal file
@ -0,0 +1,3 @@
|
||||
module.exports = {
|
||||
testURL: 'http://localhost:8000',
|
||||
}
|
12
manifest.json
Normal file
12
manifest.json
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"name": "Comty",
|
||||
"start_url": ".",
|
||||
"display": "standalone",
|
||||
"background_color": "white",
|
||||
"description": "RageStudio users dashboard",
|
||||
"icons": [
|
||||
{
|
||||
"src": "logo.svg"
|
||||
}
|
||||
]
|
||||
}
|
40
mock/_utils.js
Normal file
40
mock/_utils.js
Normal file
@ -0,0 +1,40 @@
|
||||
/**
|
||||
* Query objects that specify keys and values in an array where all values are objects.
|
||||
* @param {array} array An array where all values are objects, like [{key:1},{key:2}].
|
||||
* @param {string} key The key of the object that needs to be queried.
|
||||
* @param {string} value The value of the object that needs to be queried.
|
||||
* @return {object|undefined} Return frist object when query success.
|
||||
*/
|
||||
export function queryArray(array, key, value) {
|
||||
if (!Array.isArray(array)) {
|
||||
return
|
||||
}
|
||||
return array.filter(_ => _[key] === value)
|
||||
}
|
||||
|
||||
export function randomNumber(min, max) {
|
||||
return Math.floor(Math.random() * (max - min) + min)
|
||||
}
|
||||
|
||||
export const Constant = {
|
||||
ApiPrefix: '/api/v1',
|
||||
NotFound: {
|
||||
message: 'Not Found',
|
||||
documentation_url: '',
|
||||
},
|
||||
Color: {
|
||||
green: '#64ea91',
|
||||
blue: '#8fc9fb',
|
||||
purple: '#d897eb',
|
||||
red: '#f69899',
|
||||
yellow: '#f8c82e',
|
||||
peach: '#f797d6',
|
||||
borderBase: '#e5e5e5',
|
||||
borderSplit: '#f4f4f4',
|
||||
grass: '#d6fbb5',
|
||||
sky: '#c1e0fc',
|
||||
},
|
||||
}
|
||||
|
||||
export Mock from 'mockjs'
|
||||
export qs from 'qs'
|
152
mock/route.js
Normal file
152
mock/route.js
Normal file
@ -0,0 +1,152 @@
|
||||
import {
|
||||
Constant
|
||||
} from './_utils'
|
||||
const {
|
||||
ApiPrefix
|
||||
} = Constant
|
||||
|
||||
const database = [
|
||||
|
||||
// DASHBOARD SECTION
|
||||
{
|
||||
id: '1',
|
||||
icon: 'home',
|
||||
name: 'Main',
|
||||
route: '/main',
|
||||
},
|
||||
|
||||
// ACCOUNT SECTION
|
||||
{
|
||||
id: '2',
|
||||
breadcrumbParentId: '1',
|
||||
name: 'Account',
|
||||
icon: 'user',
|
||||
},
|
||||
{
|
||||
id: '21',
|
||||
breadcrumbParentId: '2',
|
||||
menuParentId: '2',
|
||||
name: 'YulioID™',
|
||||
icon: 'user',
|
||||
route: '/account',
|
||||
},
|
||||
{
|
||||
id: '22',
|
||||
breadcrumbParentId: '2',
|
||||
menuParentId: '2',
|
||||
name: 'YulioPay™',
|
||||
icon: 'wallet',
|
||||
route: '/wallet',
|
||||
},
|
||||
{
|
||||
id: '23',
|
||||
breadcrumbParentId: '2',
|
||||
menuParentId: '2',
|
||||
name: 'Vault',
|
||||
icon: 'save',
|
||||
route: '/account',
|
||||
},
|
||||
|
||||
|
||||
// RESOURCES SECTION
|
||||
{
|
||||
id: '3',
|
||||
breadcrumbParentId: '1',
|
||||
name: 'Resources',
|
||||
icon: 'compass',
|
||||
},
|
||||
{
|
||||
id: '31',
|
||||
breadcrumbParentId: '3',
|
||||
menuParentId: '3',
|
||||
name: 'Marketplace',
|
||||
icon: 'shopping-cart',
|
||||
route: '/resources/marketplace',
|
||||
},
|
||||
{
|
||||
id: '32',
|
||||
breadcrumbParentId: '3',
|
||||
menuParentId: '3',
|
||||
name: 'Apps',
|
||||
icon: 'desktop',
|
||||
route: '/resources/apps',
|
||||
},
|
||||
{
|
||||
id: '33',
|
||||
breadcrumbParentId: '3',
|
||||
menuParentId: '3',
|
||||
name: 'Download Manager',
|
||||
icon: 'build',
|
||||
route: '/resources/dl',
|
||||
},
|
||||
{
|
||||
id: '34',
|
||||
breadcrumbParentId: '3',
|
||||
menuParentId: '3',
|
||||
name: 'Other Services',
|
||||
icon: 'compass',
|
||||
route: '/resources/otherservices',
|
||||
},
|
||||
|
||||
// CloudStudio
|
||||
{
|
||||
id: '4',
|
||||
breadcrumbParentId: '1',
|
||||
name: 'Cloud Studio',
|
||||
icon: 'cloud',
|
||||
},
|
||||
{
|
||||
id: '42',
|
||||
breadcrumbParentId: '4',
|
||||
menuParentId: '4',
|
||||
name: 'Workspaces',
|
||||
icon: 'deployment-unit',
|
||||
route: '/changelogs',
|
||||
},
|
||||
{
|
||||
id: '43',
|
||||
breadcrumbParentId: '4',
|
||||
menuParentId: '4',
|
||||
name: 'Cloud Computing',
|
||||
icon: 'cloud-server',
|
||||
route: '/help',
|
||||
},
|
||||
{
|
||||
id: '44',
|
||||
breadcrumbParentId: '4',
|
||||
menuParentId: '4',
|
||||
name: 'GIT',
|
||||
icon: 'branches',
|
||||
route: '/about',
|
||||
},
|
||||
// Project Manager
|
||||
{
|
||||
id: '5',
|
||||
breadcrumbParentId: '1',
|
||||
name: 'Project Manager',
|
||||
icon: 'team',
|
||||
},
|
||||
{
|
||||
id: '51',
|
||||
breadcrumbParentId: '5',
|
||||
menuParentId: '5',
|
||||
name: 'Project Manager',
|
||||
icon: 'reconciliation',
|
||||
route: '/help',
|
||||
},
|
||||
{
|
||||
id: '52',
|
||||
breadcrumbParentId: '5',
|
||||
menuParentId: '5',
|
||||
name: 'Teams',
|
||||
icon: 'team',
|
||||
route: '/changelogs',
|
||||
},
|
||||
|
||||
]
|
||||
|
||||
module.exports = {
|
||||
[`GET ${ApiPrefix}/routes`](req, res) {
|
||||
res.status(200).json(database)
|
||||
},
|
||||
}
|
52
mock/user.js
Normal file
52
mock/user.js
Normal file
@ -0,0 +1,52 @@
|
||||
import { Mock, Constant, qs, randomAvatar } from './_utils'
|
||||
import bcrypt from 'bcryptjs';
|
||||
import jwt from 'jsonwebtoken';
|
||||
import keys from '../config/keys.js';
|
||||
|
||||
const { ApiPrefix } = Constant
|
||||
const queryArray = (array, key, keyAlias = 'key') => {
|
||||
if (!(array instanceof Array)) {
|
||||
return null
|
||||
}
|
||||
let data
|
||||
|
||||
for (let item of array) {
|
||||
if (item[keyAlias] === key) {
|
||||
data = item
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (data) {
|
||||
return data
|
||||
}
|
||||
return null
|
||||
}
|
||||
const NOTFOUND = {
|
||||
message: 'API Route Not Found',
|
||||
documentation_url: 'http://localhost:8000/request',
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
[`POST ${ApiPrefix}/user/login`](req, res) {
|
||||
var ExpireTime = '1556952'
|
||||
const now = new Date()
|
||||
now.setDate(now.getDate() + 1)
|
||||
const { UserID, UserToken } = req.body
|
||||
const frame = { UserID, UserToken, deadline: now.getTime()}
|
||||
jwt.sign(
|
||||
frame,
|
||||
keys.secretOrKey,
|
||||
{ expiresIn: ExpireTime },
|
||||
(err, token) => {
|
||||
res.cookie('token', token, { maxAge: ExpireTime, httpOnly: false }),
|
||||
res.json({ success: true, token: token })
|
||||
}
|
||||
)
|
||||
},
|
||||
|
||||
[`GET ${ApiPrefix}/user/logout`](req, res) {
|
||||
res.clearCookie('token')
|
||||
res.status(200).end()
|
||||
},
|
||||
}
|
151
package.json
Normal file
151
package.json
Normal file
@ -0,0 +1,151 @@
|
||||
{
|
||||
"name": "comty-development",
|
||||
"version": "0.1.1",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@ant-design/pro-layout": "^4.9.11",
|
||||
"@lingui/react": "^2.9.0",
|
||||
"ant-design-pro": "^2.3.2",
|
||||
"antd": "^3.26.3",
|
||||
"autoprefixer": "7.1.6",
|
||||
"axios": "^0.18.0",
|
||||
"babel-core": "7.0.0-bridge.0",
|
||||
"bcryptjs": "^2.4.3",
|
||||
"body-parser": "^1.19.0",
|
||||
"chart.js": "^2.9.3",
|
||||
"classnames": "^2.2.6",
|
||||
"concurrently": "^5.0.2",
|
||||
"cryptr": "^4.0.2",
|
||||
"dns": "^0.2.2",
|
||||
"dotenv": "^8.2.0",
|
||||
"draftjs-to-html": "^0.8.4",
|
||||
"draftjs-to-markdown": "^0.5.1",
|
||||
"dva-model-extend": "^0.1.2",
|
||||
"enquire-js": "^0.2.1",
|
||||
"highcharts-exporting": "^0.1.7",
|
||||
"highcharts-more": "^0.1.7",
|
||||
"immutability-helper": "^3.0.1",
|
||||
"is-empty": "^1.2.0",
|
||||
"jquery": "^3.4.1",
|
||||
"js-cookie": "^2.2.1",
|
||||
"json-format": "^1.0.1",
|
||||
"jsonwebtoken": "^8.5.1",
|
||||
"lodash": "^4.17.15",
|
||||
"md5": "^2.2.1",
|
||||
"moment": "^2.24.0",
|
||||
"node-sass": "^4.13.1",
|
||||
"nprogress": "^0.2.0",
|
||||
"os-utils": "0.0.14",
|
||||
"passport": "^0.4.1",
|
||||
"passport-auth0": "^1.3.1",
|
||||
"passport-jwt": "^4.0.0",
|
||||
"path-to-regexp": "^2.4.0",
|
||||
"prop-types": "^15.7.0",
|
||||
"qs": "^6.9.0",
|
||||
"radium": "^0.26.0",
|
||||
"rc-tween-one": "^2.6.8",
|
||||
"react-animations": "^1.0.0",
|
||||
"react-bootstrap": "^0.32.4",
|
||||
"react-chartjs": "^1.2.0",
|
||||
"react-chat-elements": "^10.1.1",
|
||||
"react-countup": "^4.3.0",
|
||||
"react-dazzle": "^1.4.0",
|
||||
"react-detect-offline": "^2.4.0",
|
||||
"react-draft-wysiwyg": "^1.14.1",
|
||||
"react-fullscreen-crossbrowser": "^1.0.9",
|
||||
"react-helmet": "^5.2.0",
|
||||
"react-highcharts": "^16.1.0",
|
||||
"react-iframe": "^1.8.0",
|
||||
"react-modal": "^3.11.1",
|
||||
"react-new-window": "^0.1.2",
|
||||
"react-notifications": "^1.4.3",
|
||||
"react-perfect-scrollbar": "^1.4.2",
|
||||
"react-responsive": "^8.0.1",
|
||||
"react-router": "^5.1.2",
|
||||
"react-scripts": "2.1.1",
|
||||
"react-select-country-list": "^2.0.1",
|
||||
"react-server-status": "^1.1.1",
|
||||
"react-sound": "^1.2.0",
|
||||
"recompose": "^0.30.0",
|
||||
"simple-oauth2": "^3.1.0",
|
||||
"socket.io-client": "^2.1.1",
|
||||
"store": "^2.0.12",
|
||||
"stripe": "^7.14.0",
|
||||
"ts-cookies": "^1.0.0",
|
||||
"uifx": "^1.0.8",
|
||||
"umi-plugin-datahub": "^3.2.1",
|
||||
"universal-cookie": "^4.0.2",
|
||||
"validator": "^12.1.0",
|
||||
"websocket": "^1.0.31"
|
||||
},
|
||||
"devDependencies": {
|
||||
"electron-builder": "^20.43.0",
|
||||
"electron-devtools-installer": "^2.2.4",
|
||||
"electron-reload": "^1.4.0",
|
||||
"rimraf": "^2.6.3",
|
||||
"wait-on": "^3.2.0",
|
||||
"@lingui/babel-preset-react": "^2.9.0",
|
||||
"@lingui/cli": "^2.9.0",
|
||||
"@lingui/loader": "^2.9.0",
|
||||
"@types/react": "^16.9.16",
|
||||
"babel-eslint": "^10.0.3",
|
||||
"babel-plugin-dev-expression": "^0.2.2",
|
||||
"babel-plugin-import": "^1.13.0",
|
||||
"babel-plugin-macros": "^2.8.0",
|
||||
"babel-plugin-module-resolver": "^3.2.0",
|
||||
"cross-env": "^5.2.1",
|
||||
"electron": "^7.1.8",
|
||||
"eslint": "^5.15.0",
|
||||
"eslint-config-react-app": "^3.0.5",
|
||||
"eslint-plugin-flowtype": "^3.13.0",
|
||||
"eslint-plugin-import": "^2.19.1",
|
||||
"eslint-plugin-jsx-a11y": "^6.2.3",
|
||||
"eslint-plugin-react": "^7.17.0",
|
||||
"husky": "^1.3.0",
|
||||
"less-vars-to-js": "^1.3.0",
|
||||
"lint-staged": "^8.1.0",
|
||||
"mockjs": "^1.1.0",
|
||||
"module": "^1.2.5",
|
||||
"now": "^16.7.0",
|
||||
"prettier": "^1.16.0",
|
||||
"stylelint": "^9.10.0",
|
||||
"stylelint-config-prettier": "^5.3.0",
|
||||
"stylelint-config-standard": "^18.2.0",
|
||||
"typescript": "^3.7.3",
|
||||
"umi": "^2.12.7",
|
||||
"umi-plugin-react": "^1.14.10"
|
||||
},
|
||||
"lingui": {
|
||||
"fallbackLocale": "en",
|
||||
"sourceLocale": "en",
|
||||
"localeDir": "src/locales",
|
||||
"srcPathDirs": [
|
||||
"src/pages",
|
||||
"src/layouts",
|
||||
"src/components",
|
||||
"src/layouts"
|
||||
],
|
||||
"format": "minimal",
|
||||
"extractBabelOptions": {
|
||||
"presets": [
|
||||
"umi/babel"
|
||||
]
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"app-dev": "concurrently \"npm run start\" \"wait-on http://localhost:8000 && npm run electron-dev\"",
|
||||
"electron-dev": "cross-env NODE_ENV=development electron .",
|
||||
"tsc:w": "tsc -w",
|
||||
"analyze": "cross-env ANALYZE=1 umi build",
|
||||
"build": "umi build",
|
||||
"start": "umi dev",
|
||||
"test": "cross-env BABELRC=none umi test",
|
||||
"prettier": "prettier --write 'src/**/*.{js,less}'",
|
||||
"add-locale": "lingui add-locale",
|
||||
"extract": "lingui extract",
|
||||
"trans": "lingui extract --clean && node ./scripts/translate.js"
|
||||
}
|
||||
}
|
BIN
public/favicon.ico
Normal file
BIN
public/favicon.ico
Normal file
Binary file not shown.
39
public/full_logo.svg
Normal file
39
public/full_logo.svg
Normal file
@ -0,0 +1,39 @@
|
||||
<svg id="Capa_2" data-name="Capa 2" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 1391.17 234.17">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1 {
|
||||
fill: #fff;
|
||||
}
|
||||
|
||||
.cls-2 {
|
||||
fill: #00fea1;
|
||||
}
|
||||
|
||||
.cls-3 {
|
||||
fill: #00a079;
|
||||
}
|
||||
</style>
|
||||
<symbol id="TM" data-name="TM" viewBox="0 0 46.03 24.05">
|
||||
<path class="cls-1" d="M19.68.52a1.31,1.31,0,0,1,.42,1,1.31,1.31,0,0,1-.42,1A1.7,1.7,0,0,1,18.53,3H11.7l0,19.43a1.54,1.54,0,0,1-.48,1.18A1.71,1.71,0,0,1,10,24a1.72,1.72,0,0,1-1.18-.45,1.51,1.51,0,0,1-.5-1.17l0-19.44H1.57C.52,2.93,0,2.46,0,1.53S.52.13,1.57.13l17,0A1.68,1.68,0,0,1,19.68.52Zm25.93,0A1.65,1.65,0,0,1,46,1.66l0,20.77a1.73,1.73,0,0,1-.39,1.21,1.44,1.44,0,0,1-1.07.41,1.37,1.37,0,0,1-1.06-.42,1.7,1.7,0,0,1-.39-1.2l0-16L36.32,19.34a1.64,1.64,0,0,1-1.57,1.11,1.61,1.61,0,0,1-1.51-1.12L26.48,6.67l0,15.73A1.61,1.61,0,0,1,26,23.61a1.63,1.63,0,0,1-1.12.41,1.39,1.39,0,0,1-1.07-.42,1.7,1.7,0,0,1-.39-1.2l0-20.78A1.58,1.58,0,0,1,23.91.45,1.59,1.59,0,0,1,25.09,0c.6,0,1.1.39,1.51,1.18l8.21,15.69L43,1.2A1.81,1.81,0,0,1,44.52,0,1.42,1.42,0,0,1,45.61.48Z"/>
|
||||
</symbol>
|
||||
<symbol id="Nuevo_símbolo" data-name="Nuevo símbolo" viewBox="0 0 822.09 126.19">
|
||||
<g>
|
||||
<path class="cls-1" d="M1.67,123.38A5.16,5.16,0,0,1,0,119.5V6.34A5.16,5.16,0,0,1,1.67,2.46,5.81,5.81,0,0,1,5.81.88H40q29.4,0,45.5,16t16.1,45.93q0,29.92-16.1,46T40,125H5.81A5.81,5.81,0,0,1,1.67,123.38Zm37.75-7.92q50.7,0,50.69-52.63,0-52.44-50.69-52.45H10.91V115.46Z"/>
|
||||
<path class="cls-1" d="M183.65,45.58q7.66,8.1,7.66,24.47v50.16a5.55,5.55,0,0,1-1.41,4,5.77,5.77,0,0,1-7.74,0,5.55,5.55,0,0,1-1.41-4V109.65A27.59,27.59,0,0,1,170,121.88a30.31,30.31,0,0,1-16.19,4.31,34.05,34.05,0,0,1-15.13-3.34,26.68,26.68,0,0,1-10.83-9.33,23.42,23.42,0,0,1-4-13.2q0-9.51,4.93-14.78T145.2,78q11.43-2.3,31.85-2.29h3.7V69.17q0-11.62-4.75-17t-15-5.36a48.54,48.54,0,0,0-24.82,6.86l-2.73,1.85A7,7,0,0,1,129.71,57a3.67,3.67,0,0,1-2.9-1.32,4.75,4.75,0,0,1-1.15-3.25q0-3.87,6.16-7.57a55.22,55.22,0,0,1,13.73-5.46,60.17,60.17,0,0,1,15-1.93Q176,37.49,183.65,45.58Zm-10.2,63.54q7.29-7.74,7.3-19.71V83.6h-3.34q-16.9,0-25.88,1.41t-12.67,4.84q-3.69,3.44-3.69,9.94A15.4,15.4,0,0,0,140.8,112a20.56,20.56,0,0,0,13.9,4.84Q166.15,116.86,173.45,109.12Z"/>
|
||||
<path class="cls-1" d="M232.4,124.17a46.44,46.44,0,0,1-12.58-5.55,21.46,21.46,0,0,1-4.66-4,5.92,5.92,0,0,1-1.32-3.78,4.2,4.2,0,0,1,1.14-3,3.59,3.59,0,0,1,2.73-1.23q1.57,0,5.45,2.64a57.52,57.52,0,0,0,10.48,5.45,37,37,0,0,0,13.46,2.11q10.38,0,16.19-3.78a12.16,12.16,0,0,0,5.81-10.82,11,11,0,0,0-2.11-7,16.9,16.9,0,0,0-7-4.75,85.62,85.62,0,0,0-14.08-4q-15.68-3.51-22.27-9.06T217,62.66a22.14,22.14,0,0,1,8.8-18.22q8.8-6.94,22.88-6.95a48.33,48.33,0,0,1,13.12,1.76,33.53,33.53,0,0,1,10.82,5.1q6.17,4.23,6.16,8.27a4.55,4.55,0,0,1-1.14,3.08A3.52,3.52,0,0,1,274.91,57c-1.18,0-3-.93-5.46-2.81A53.7,53.7,0,0,0,260,48.84a30,30,0,0,0-11.88-2q-9.16,0-14.61,4.13a13.3,13.3,0,0,0-5.46,11.18,11.41,11.41,0,0,0,1.85,6.69,15,15,0,0,0,6.34,4.66,72.14,72.14,0,0,0,12.93,4q12.15,2.82,18.66,6T277.2,91Q280,95.4,280,102.26,280,113,271,119.59t-24,6.6A53,53,0,0,1,232.4,124.17Z"/>
|
||||
<path class="cls-1" d="M374.17,70.58v49.8a5.51,5.51,0,0,1-1.41,4,5.05,5.05,0,0,1-3.87,1.5,5.14,5.14,0,0,1-5.45-5.46V71.28q0-12.68-5.11-18.48T342.14,47q-12.67,0-20.33,7.75T314.16,75.5v44.88a5.51,5.51,0,0,1-1.41,4,5.05,5.05,0,0,1-3.87,1.5,5.15,5.15,0,0,1-5.46-5.46V5.46a5.32,5.32,0,0,1,1.5-4,5.32,5.32,0,0,1,4-1.5,5.05,5.05,0,0,1,3.87,1.5,5.51,5.51,0,0,1,1.41,4v48.4a28.2,28.2,0,0,1,11.7-12.15,35.69,35.69,0,0,1,17.51-4.22Q374.17,37.49,374.17,70.58Z"/>
|
||||
<path class="cls-1" d="M462.17,42.94a36.27,36.27,0,0,1,13.38,15.4q4.74,9.94,4.75,23.15,0,13.38-4.75,23.49a36.62,36.62,0,0,1-13.38,15.67,36,36,0,0,1-19.89,5.54,34.47,34.47,0,0,1-17.95-4.49,28.13,28.13,0,0,1-11.44-13.11v11.62a5.55,5.55,0,0,1-1.41,4,5.08,5.08,0,0,1-3.87,1.49,5.14,5.14,0,0,1-5.46-5.45V5.46a5.32,5.32,0,0,1,1.5-4,5.35,5.35,0,0,1,4-1.5,5.05,5.05,0,0,1,3.87,1.5,5.51,5.51,0,0,1,1.41,4V55.09A28.13,28.13,0,0,1,424.33,42a34.47,34.47,0,0,1,17.95-4.49A36.47,36.47,0,0,1,462.17,42.94Zm-.44,64.42q7.49-9.33,7.48-25.87t-7.48-25.61q-7.49-9.06-21-9.06-13.38,0-20.59,9.15t-7.22,25.87q0,16.72,7.3,25.78t20.68,9.07Q454.25,116.69,461.73,107.36Z"/>
|
||||
<path class="cls-1" d="M516.29,120.74a36.65,36.65,0,0,1-13.82-15.49q-4.92-10-4.92-23.41t4.92-23.41a36.65,36.65,0,0,1,13.82-15.49,41.79,41.79,0,0,1,41.27,0,35.88,35.88,0,0,1,13.82,15.49q4.83,10,4.84,23.41t-4.84,23.41a35.88,35.88,0,0,1-13.82,15.49,41.79,41.79,0,0,1-41.27,0Zm41.45-13q7.39-9,7.39-25.87,0-16.55-7.48-25.78T537,46.82q-13.38,0-20.77,9.24t-7.39,25.78q0,16.89,7.21,25.87t20.77,9Q550.35,116.69,557.74,107.71Z"/>
|
||||
<path class="cls-1" d="M655.86,45.58q7.65,8.1,7.65,24.47v50.16a5.55,5.55,0,0,1-1.41,4,5.77,5.77,0,0,1-7.74,0,5.55,5.55,0,0,1-1.41-4V109.65a27.62,27.62,0,0,1-10.73,12.23,30.37,30.37,0,0,1-16.2,4.31,34.08,34.08,0,0,1-15.13-3.34,26.75,26.75,0,0,1-10.83-9.33,23.5,23.5,0,0,1-4-13.2q0-9.51,4.93-14.78T617.4,78q11.45-2.3,31.86-2.29H653V69.17q0-11.62-4.75-17t-15-5.36a48.51,48.51,0,0,0-24.81,6.86c-.36.24-1.27.85-2.73,1.85A7.1,7.1,0,0,1,601.91,57,3.67,3.67,0,0,1,599,55.7a4.74,4.74,0,0,1-1.14-3.25q0-3.87,6.15-7.57a55.38,55.38,0,0,1,13.73-5.46,60.28,60.28,0,0,1,15-1.93Q648.2,37.49,655.86,45.58Zm-10.21,63.54q7.3-7.74,7.3-19.71V83.6h-3.34q-16.89,0-25.87,1.41t-12.68,4.84q-3.69,3.44-3.69,9.94A15.4,15.4,0,0,0,613,112a20.59,20.59,0,0,0,13.91,4.84Q638.34,116.86,645.65,109.12Z"/>
|
||||
<path class="cls-1" d="M736,38.72a4.11,4.11,0,0,1,1.41,3.52c0,2.93-1.76,4.58-5.28,4.93l-5.28.53q-12.5,1.23-18.57,9a28.54,28.54,0,0,0-6.07,18.13v45.58a5.48,5.48,0,0,1-1.41,4.05,5.23,5.23,0,0,1-3.87,1.41,5.55,5.55,0,0,1-4-1.41,5.29,5.29,0,0,1-1.5-4.05V43.3a5.29,5.29,0,0,1,1.5-4,5.55,5.55,0,0,1,4-1.41,5,5,0,0,1,3.7,1.41,5.26,5.26,0,0,1,1.4,3.87V54.56Q709.27,39.42,728.81,38l2.46-.18C733.5,37.72,735.08,38,736,38.72Z"/>
|
||||
<path class="cls-1" d="M820.59,1.5a5.32,5.32,0,0,1,1.5,4V120.21a5.14,5.14,0,0,1-5.46,5.45,5.08,5.08,0,0,1-3.87-1.49,5.55,5.55,0,0,1-1.41-4V108.59a28.19,28.19,0,0,1-11.44,13.11A34.49,34.49,0,0,1,782,126.19a36,36,0,0,1-19.89-5.54A36.62,36.62,0,0,1,748.69,105q-4.74-10.11-4.75-23.49,0-13.2,4.75-23.15A35.39,35.39,0,0,1,782,37.49,34.49,34.49,0,0,1,799.91,42a28.19,28.19,0,0,1,11.44,13.11V5.46a5.51,5.51,0,0,1,1.41-4A5.05,5.05,0,0,1,816.63,0,5.35,5.35,0,0,1,820.59,1.5ZM804.05,107.62q7.29-9.06,7.3-25.78T804.13,56q-7.21-9.15-20.59-9.15-13.54,0-20.94,9.06t-7.39,25.61q0,16.73,7.39,26t20.77,9.24Q796.73,116.69,804.05,107.62Z"/>
|
||||
</g>
|
||||
</symbol>
|
||||
</defs>
|
||||
<title>rDashboard-White-TM-T3</title>
|
||||
<use id="TM-3" data-name="TM" width="46.03" height="24.05" transform="translate(1345.14 73.61)" xlink:href="#TM"/>
|
||||
<use id="Dashboard_TEXT" data-name="Dashboard TEXT" width="822.09" height="126.19" transform="translate(514.02 89.17)" xlink:href="#Nuevo_símbolo"/>
|
||||
<path id="RLayer" class="cls-2" d="M664.53,480.3c-1.79-11.1-9.16-47.71-42.06-77.06a144,144,0,0,0-39.93-25.5C567,371.55,545.3,369,540,369c-88.56,0-173.41-.11-262-.17L381.87,480h-154l267,123H585c7.28-.46,27.63,0,45-18,9.86-10.21,12.63-15.37,19.17-25.65h0A119.92,119.92,0,0,0,664.53,480.3Z" transform="translate(-222 -368.83)"/>
|
||||
<polygon id="T1" class="cls-3" points="160 111.17 273 234.17 0 111.17 160 111.17"/>
|
||||
<path class="cls-2" d="M227.92,480" transform="translate(-222 -368.83)"/>
|
||||
</svg>
|
After Width: | Height: | Size: 7.2 KiB |
16
public/logo.svg
Normal file
16
public/logo.svg
Normal file
@ -0,0 +1,16 @@
|
||||
<svg id="Capa_2" data-name="Capa 2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 443.92 234.17">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1 {
|
||||
fill: #00fea1;
|
||||
}
|
||||
|
||||
.cls-2 {
|
||||
fill: #00a079;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<title>RDSeries-T3</title>
|
||||
<path id="RLayer" class="cls-1" d="M664.53,480.3c-1.79-11.1-9.16-47.71-42.06-77.06a144,144,0,0,0-39.93-25.5C567,371.55,545.3,369,540,369c-88.56,0-173.41-.11-262-.17L381.87,480h-154l.31.44c6,2.26,11.16,5.59,16.79,8.5a180.69,180.69,0,0,0,17.5,7.61c12.18,4.74,24.6,8.82,37.06,12.71,12.1,3.77,23.86,7.24,34.95,13.52.86.49,1.73.94,2.61,1.41,3.95.9,7.77,2.71,11.51,4.13,5.34,2,10.55,4.33,15.78,6.59a273.69,273.69,0,0,1,30.79,15.39,302.11,302.11,0,0,0,31.68,16.38c5.45,2.42,10.91,4.91,16.14,7.77l.22.12a5.2,5.2,0,0,1,6.31,1.78c1.79,2.5,7.26,4.21,9.86,5.84,3.74,2.36,7.78,4.18,11.47,6.62a99.34,99.34,0,0,0,11.11,6,16.43,16.43,0,0,1,4.28,2.86,19.8,19.8,0,0,1,1.64,1.77,20.81,20.81,0,0,1,5.7,3l1.24.56H585c7.28-.46,27.63,0,45-18,9.86-10.21,12.63-15.37,19.17-25.65h0A119.92,119.92,0,0,0,664.53,480.3Z" transform="translate(-222 -368.83)"/>
|
||||
<polygon id="T1" class="cls-2" points="160 111.17 273 234.17 0 111.17 160 111.17"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.2 KiB |
135
service-worker.js
Normal file
135
service-worker.js
Normal file
@ -0,0 +1,135 @@
|
||||
// This optional code is used to register a service worker.
|
||||
// register() is not called by default.
|
||||
|
||||
// This lets the app load faster on subsequent visits in production, and gives
|
||||
// it offline capabilities. However, it also means that developers (and users)
|
||||
// will only see deployed updates on subsequent visits to a page, after all the
|
||||
// existing tabs open on the page have been closed, since previously cached
|
||||
// resources are updated in the background.
|
||||
|
||||
// To learn more about the benefits of this model and instructions on how to
|
||||
// opt-in, read http://bit.ly/CRA-PWA
|
||||
|
||||
const isLocalhost = Boolean(
|
||||
window.location.hostname === 'localhost' ||
|
||||
// [::1] is the IPv6 localhost address.
|
||||
window.location.hostname === '[::1]' ||
|
||||
// 127.0.0.1/8 is considered localhost for IPv4.
|
||||
window.location.hostname.match(
|
||||
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
|
||||
)
|
||||
);
|
||||
|
||||
export function register(config) {
|
||||
if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
|
||||
// The URL constructor is available in all browsers that support SW.
|
||||
const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);
|
||||
if (publicUrl.origin !== window.location.origin) {
|
||||
// Our service worker won't work if PUBLIC_URL is on a different origin
|
||||
// from what our page is served on. This might happen if a CDN is used to
|
||||
// serve assets; see https://github.com/facebook/create-react-app/issues/2374
|
||||
return;
|
||||
}
|
||||
|
||||
window.addEventListener('load', () => {
|
||||
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
|
||||
|
||||
if (isLocalhost) {
|
||||
// This is running on localhost. Let's check if a service worker still exists or not.
|
||||
checkValidServiceWorker(swUrl, config);
|
||||
|
||||
// Add some additional logging to localhost, pointing developers to the
|
||||
// service worker/PWA documentation.
|
||||
navigator.serviceWorker.ready.then(() => {
|
||||
console.log(
|
||||
'This web app is being served cache-first by a service ' +
|
||||
'worker. To learn more, visit http://bit.ly/CRA-PWA'
|
||||
);
|
||||
});
|
||||
} else {
|
||||
// Is not localhost. Just register service worker
|
||||
registerValidSW(swUrl, config);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function registerValidSW(swUrl, config) {
|
||||
navigator.serviceWorker
|
||||
.register(swUrl)
|
||||
.then(registration => {
|
||||
registration.onupdatefound = () => {
|
||||
const installingWorker = registration.installing;
|
||||
if (installingWorker == null) {
|
||||
return;
|
||||
}
|
||||
installingWorker.onstatechange = () => {
|
||||
if (installingWorker.state === 'installed') {
|
||||
if (navigator.serviceWorker.controller) {
|
||||
// At this point, the updated precached content has been fetched,
|
||||
// but the previous service worker will still serve the older
|
||||
// content until all client tabs are closed.
|
||||
console.log(
|
||||
'New content is available and will be used when all ' +
|
||||
'tabs for this page are closed. See http://bit.ly/CRA-PWA.'
|
||||
);
|
||||
|
||||
// Execute callback
|
||||
if (config && config.onUpdate) {
|
||||
config.onUpdate(registration);
|
||||
}
|
||||
} else {
|
||||
// At this point, everything has been precached.
|
||||
// It's the perfect time to display a
|
||||
// "Content is cached for offline use." message.
|
||||
console.log('Content is cached for offline use.');
|
||||
|
||||
// Execute callback
|
||||
if (config && config.onSuccess) {
|
||||
config.onSuccess(registration);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error during service worker registration:', error);
|
||||
});
|
||||
}
|
||||
|
||||
function checkValidServiceWorker(swUrl, config) {
|
||||
// Check if the service worker can be found. If it can't reload the page.
|
||||
fetch(swUrl)
|
||||
.then(response => {
|
||||
// Ensure service worker exists, and that we really are getting a JS file.
|
||||
const contentType = response.headers.get('content-type');
|
||||
if (
|
||||
response.status === 404 ||
|
||||
(contentType != null && contentType.indexOf('javascript') === -1)
|
||||
) {
|
||||
// No service worker found. Probably a different app. Reload the page.
|
||||
navigator.serviceWorker.ready.then(registration => {
|
||||
registration.unregister().then(() => {
|
||||
window.location.reload();
|
||||
});
|
||||
});
|
||||
} else {
|
||||
// Service worker found. Proceed as normal.
|
||||
registerValidSW(swUrl, config);
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
console.log(
|
||||
'No internet connection found. App is running in offline mode.'
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
export function unregister() {
|
||||
if ('serviceWorker' in navigator) {
|
||||
navigator.serviceWorker.ready.then(registration => {
|
||||
registration.unregister();
|
||||
});
|
||||
}
|
||||
}
|
6
setupTests.js
Normal file
6
setupTests.js
Normal file
@ -0,0 +1,6 @@
|
||||
const Enzyme = require('enzyme');
|
||||
// this is where we reference the adapter package we installed
|
||||
// earlier
|
||||
const EnzymeAdapter = require('enzyme-adapter-react-16');
|
||||
// This sets up the adapter to be used by Enzyme
|
||||
Enzyme.configure({ adapter: new EnzymeAdapter() });
|
31
src/components/CoreLoader/index.js
Normal file
31
src/components/CoreLoader/index.js
Normal file
@ -0,0 +1,31 @@
|
||||
import React from 'react'
|
||||
import style from './styles.less'
|
||||
class CoreLoader extends React.PureComponent {
|
||||
render(){
|
||||
const { type } = this.props;
|
||||
if ( type == 'circle') {
|
||||
return (
|
||||
<div>
|
||||
<div className={style.loader}>
|
||||
<svg viewBox="0 0 80 80">
|
||||
<circle id="test" cx="40" cy="40" r="32"></circle>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
if ( type == 'box') {
|
||||
return(
|
||||
<div>
|
||||
<div className={style.loader}>
|
||||
<svg viewBox="0 0 80 80">
|
||||
<rect x="8" y="8" width="64" height="64"></rect>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
export default CoreLoader;
|
137
src/components/CoreLoader/styles.less
Normal file
137
src/components/CoreLoader/styles.less
Normal file
@ -0,0 +1,137 @@
|
||||
.loader {
|
||||
--path: #2F3545;
|
||||
// OLDDOT => --dot: #5628EE;
|
||||
--dot: rgb(0, 254, 161);
|
||||
--duration: 3s;
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
position: relative;
|
||||
&:before {
|
||||
content: '';
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
border-radius: 50%;
|
||||
position: absolute;
|
||||
display: block;
|
||||
background: var(--dot);
|
||||
top: 37px;
|
||||
left: 19px;
|
||||
transform: translate(-18px, -18px);
|
||||
animation: dotRect var(--duration) cubic-bezier(0.785, 0.135, 0.15, 0.86) infinite;
|
||||
}
|
||||
svg {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
rect,
|
||||
polygon,
|
||||
circle {
|
||||
fill: none;
|
||||
stroke: var(--path);
|
||||
stroke-width: 10px;
|
||||
stroke-linejoin: round;
|
||||
stroke-linecap: round;
|
||||
}
|
||||
polygon {
|
||||
stroke-dasharray: 145 (221 - 145) 145 (221 - 145);
|
||||
stroke-dashoffset: 0;
|
||||
animation: pathTriangle var(--duration) cubic-bezier(0.785, 0.135, 0.15, 0.86) infinite;
|
||||
}
|
||||
rect {
|
||||
stroke-dasharray: (256 / 4 * 3) (256 / 4) (256 / 4 * 3) (256 / 4);
|
||||
stroke-dashoffset: 0;
|
||||
animation: pathRect 3s cubic-bezier(0.785, 0.135, 0.15, 0.86) infinite;
|
||||
}
|
||||
circle {
|
||||
stroke-dasharray: (200 / 4 * 3) (200 / 4) (200 / 4 * 3) (200 / 4);
|
||||
stroke-dashoffset: 75;
|
||||
animation: pathCircle var(--duration) cubic-bezier(0.785, 0.135, 0.15, 0.86) infinite;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes pathTriangle {
|
||||
33% {
|
||||
stroke-dashoffset: 74;
|
||||
}
|
||||
66% {
|
||||
stroke-dashoffset: 147;
|
||||
}
|
||||
100% {
|
||||
stroke-dashoffset: 221;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes dotTriangle {
|
||||
33% {
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
66% {
|
||||
transform: translate(10px, -18px);
|
||||
}
|
||||
100% {
|
||||
transform: translate(-10px, -18px);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes pathRect {
|
||||
25% {
|
||||
stroke-dashoffset: 64;
|
||||
}
|
||||
50% {
|
||||
stroke-dashoffset: 128;
|
||||
}
|
||||
75% {
|
||||
stroke-dashoffset: 192;
|
||||
}
|
||||
100% {
|
||||
stroke-dashoffset: 256;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes dotRect {
|
||||
25% {
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
50% {
|
||||
transform: translate(18px, -18px);
|
||||
}
|
||||
75% {
|
||||
transform: translate(0, -36px);
|
||||
}
|
||||
100% {
|
||||
transform: translate(-18px, -18px);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes pathCircle {
|
||||
25% {
|
||||
stroke-dashoffset: 125;
|
||||
}
|
||||
50% {
|
||||
stroke-dashoffset: 175;
|
||||
}
|
||||
75% {
|
||||
stroke-dashoffset: 225;
|
||||
}
|
||||
100% {
|
||||
stroke-dashoffset: 275;
|
||||
}
|
||||
}
|
||||
|
||||
.loader {
|
||||
display: inline-block;
|
||||
margin: 0 16px;
|
||||
}
|
||||
|
||||
html {
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
&:before,
|
||||
&:after {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
}
|
34
src/components/DropOption/DropOption.js
Normal file
34
src/components/DropOption/DropOption.js
Normal file
@ -0,0 +1,34 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { Dropdown, Button, Icon, Menu } from 'antd'
|
||||
|
||||
const DropOption = ({
|
||||
onMenuClick,
|
||||
menuOptions = [],
|
||||
buttonStyle,
|
||||
dropdownProps,
|
||||
}) => {
|
||||
const menu = menuOptions.map(item => (
|
||||
<Menu.Item key={item.key}>{item.name}</Menu.Item>
|
||||
))
|
||||
return (
|
||||
<Dropdown overlay= {
|
||||
<Menu onClick={onMenuClick}>{menu}</Menu>
|
||||
} {...dropdownProps}>
|
||||
|
||||
<Button style={{ border: 'none', ...buttonStyle }}>
|
||||
<Icon style={{ marginRight: 2 }} type="bars" />
|
||||
<Icon type="down" />
|
||||
</Button>
|
||||
</Dropdown>
|
||||
)
|
||||
}
|
||||
|
||||
DropOption.propTypes = {
|
||||
onMenuClick: PropTypes.func,
|
||||
menuOptions: PropTypes.array.isRequired,
|
||||
buttonStyle: PropTypes.object,
|
||||
dropdownProps: PropTypes.object,
|
||||
}
|
||||
|
||||
export default DropOption
|
6
src/components/DropOption/package.json
Normal file
6
src/components/DropOption/package.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"name": "DropOption",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"main": "./DropOption.js"
|
||||
}
|
17
src/components/Editor/Editor.js
Normal file
17
src/components/Editor/Editor.js
Normal file
@ -0,0 +1,17 @@
|
||||
import React from 'react';
|
||||
import { Editor } from 'react-draft-wysiwyg';
|
||||
import 'react-draft-wysiwyg/dist/react-draft-wysiwyg.css';
|
||||
import styles from './Editor.less';
|
||||
|
||||
const DraftEditor = props => {
|
||||
return (
|
||||
<Editor
|
||||
toolbarClassName={ styles.toolbar }
|
||||
wrapperClassName={ styles.wrapper }
|
||||
editorClassName={ styles.editor }
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export default DraftEditor
|
106
src/components/Editor/Editor.less
Normal file
106
src/components/Editor/Editor.less
Normal file
@ -0,0 +1,106 @@
|
||||
.wrapper {
|
||||
height: 500px;
|
||||
|
||||
:global {
|
||||
.rdw-dropdownoption-default {
|
||||
padding: 6px;
|
||||
}
|
||||
|
||||
.rdw-dropdown-optionwrapper {
|
||||
box-sizing: content-box;
|
||||
width: 100%;
|
||||
border-radius: 0 0 2px 2px;
|
||||
&:hover {
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
.rdw-inline-wrapper {
|
||||
flex-wrap: wrap;
|
||||
margin-bottom: 0;
|
||||
|
||||
.rdw-option-wrapper {
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
}
|
||||
|
||||
.rdw-option-active {
|
||||
box-shadow: 1px 1px 0 #e8e8e8 inset;
|
||||
}
|
||||
|
||||
.rdw-colorpicker-option {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.rdw-colorpicker-modal,
|
||||
.rdw-embedded-modal,
|
||||
.rdw-emoji-modal,
|
||||
.rdw-image-modal,
|
||||
.rdw-link-modal {
|
||||
box-shadow: 4px 4px 40px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.rdw-colorpicker-modal,
|
||||
.rdw-embedded-modal,
|
||||
.rdw-link-modal {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.rdw-emoji-modal {
|
||||
width: 214px;
|
||||
}
|
||||
|
||||
.rdw-colorpicker-modal {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.rdw-embedded-modal-btn,
|
||||
.rdw-image-modal-btn,
|
||||
.rdw-link-modal-btn {
|
||||
height: 32px;
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.rdw-embedded-modal-input,
|
||||
.rdw-embedded-modal-size-input,
|
||||
.rdw-link-modal-input {
|
||||
padding: 2px 6px;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
.rdw-dropdown-selectedtext {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.rdw-dropdown-wrapper,
|
||||
.rdw-option-wrapper {
|
||||
min-width: 36px;
|
||||
transition: all 0.2s ease;
|
||||
height: 30px;
|
||||
|
||||
&:active {
|
||||
box-shadow: 1px 1px 0 #e8e8e8 inset;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
box-shadow: 1px 1px 0 #e8e8e8;
|
||||
}
|
||||
}
|
||||
|
||||
.rdw-dropdown-wrapper {
|
||||
min-width: 60px;
|
||||
}
|
||||
|
||||
.rdw-editor-main {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
}
|
||||
|
||||
.editor {
|
||||
border: 1px solid #f1f1f1;
|
||||
padding: 5px;
|
||||
border-radius: 2px;
|
||||
height: auto;
|
||||
min-height: 200px;
|
||||
}
|
||||
}
|
6
src/components/Editor/package.json
Normal file
6
src/components/Editor/package.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"name": "Editor",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"main": "./Editor.js"
|
||||
}
|
30
src/components/FilterItem/FilterItem.js
Normal file
30
src/components/FilterItem/FilterItem.js
Normal file
@ -0,0 +1,30 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import styles from './FilterItem.less';
|
||||
|
||||
const FilterItem = ({ label = '', children }) => {
|
||||
const labelArray = label.split('')
|
||||
return (
|
||||
<div className={ styles.filterItem }>
|
||||
{
|
||||
labelArray.length > 0 ? (
|
||||
<div className={ styles.labelWrap }>
|
||||
{labelArray.map((item, index) => (
|
||||
<span className="labelText" key={ index }>
|
||||
{ item }
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
) : ('')
|
||||
}
|
||||
<div className={ styles.item }>{ children }</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
FilterItem.propTypes = {
|
||||
label: PropTypes.string,
|
||||
children: PropTypes.element.isRequired,
|
||||
}
|
||||
|
||||
export default FilterItem
|
17
src/components/FilterItem/FilterItem.less
Normal file
17
src/components/FilterItem/FilterItem.less
Normal file
@ -0,0 +1,17 @@
|
||||
.filterItem {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
.labelWrap {
|
||||
width: 64px;
|
||||
line-height: 28px;
|
||||
margin-right: 12px;
|
||||
justify-content: space-between;
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.item {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
6
src/components/FilterItem/package.json
Normal file
6
src/components/FilterItem/package.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"name": "FilterItem",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"main": "./FilterItem.js"
|
||||
}
|
65
src/components/Layout/Control.js
Normal file
65
src/components/Layout/Control.js
Normal file
@ -0,0 +1,65 @@
|
||||
import React from 'react'
|
||||
import * as antd from 'antd'
|
||||
import * as ycore from 'ycore'
|
||||
import styles from './Control.less'
|
||||
|
||||
import Radium, {StyleRoot}from 'radium';
|
||||
import { fadeInUp, bounceOutDown } from 'react-animations'
|
||||
const animationStyles = {
|
||||
fadeInUp: {
|
||||
animation: 'x 0.5s',
|
||||
animationName: Radium.keyframes(fadeInUp, 'fadeInUp')
|
||||
},
|
||||
bounceOutDown: {
|
||||
animation: 'x 1s',
|
||||
animationName: Radium.keyframes(bounceOutDown, 'bounceOutDown')
|
||||
}
|
||||
}
|
||||
|
||||
export function SetControls(e){
|
||||
window.ControlComponent.DummySetControls(e);
|
||||
return
|
||||
}
|
||||
export function CloseControls(){
|
||||
window.ControlComponent.DummyCloseControls();
|
||||
return
|
||||
}
|
||||
|
||||
class Control extends React.Component {
|
||||
constructor(props){
|
||||
super(props)
|
||||
window.ControlComponent = this;
|
||||
this.state = {
|
||||
Show: false,
|
||||
FadeIN: true,
|
||||
}
|
||||
}
|
||||
DummySetControls = (e) =>{
|
||||
ycore.DevOptions.ShowFunctionsLogs? console.log('Controls recived => ', e) : null
|
||||
if (this.state.Show == false) {
|
||||
this.setState({ FadeIN: true })
|
||||
}
|
||||
this.setState({Show: true, RenderFragment: e})
|
||||
}
|
||||
DummyCloseControls(){
|
||||
ycore.DevOptions.ShowFunctionsLogs? console.log('Closing Control Bar...') : null
|
||||
this.setState({FadeIN: false})
|
||||
setTimeout(() => this.setState({ Show: false, RenderFragment: null}), 1000)
|
||||
}
|
||||
|
||||
render(){
|
||||
const {RenderFragment, Show, FadeIN} = this.state
|
||||
return(
|
||||
Show? (
|
||||
<StyleRoot>
|
||||
<div style={FadeIN? animationStyles.fadeInUp : animationStyles.bounceOutDown }>
|
||||
<antd.Card bordered={false} className={styles.ControlCard}>
|
||||
<React.Fragment>{RenderFragment} </React.Fragment>
|
||||
</antd.Card>
|
||||
</div>
|
||||
</StyleRoot>
|
||||
) : null
|
||||
)
|
||||
}
|
||||
}
|
||||
export default Control;
|
21
src/components/Layout/Control.less
Normal file
21
src/components/Layout/Control.less
Normal file
@ -0,0 +1,21 @@
|
||||
.ControlCard{
|
||||
background-color: rgba(0, 0, 0, 0.1);
|
||||
width: auto;
|
||||
max-width: 60%;
|
||||
padding: 0 5px 0 5px;
|
||||
margin: 0 0 0 50%;
|
||||
height: auto;
|
||||
position: absolute;
|
||||
z-index: 10000;
|
||||
bottom: 0;
|
||||
text-align: center;
|
||||
:global {
|
||||
.ant-card-body {
|
||||
padding: 5px;
|
||||
}
|
||||
.ant-btn {
|
||||
background-color: rgba(0, 0, 0, 0.1);
|
||||
margin: 3px;
|
||||
}
|
||||
}
|
||||
}
|
144
src/components/Layout/Header.js
Normal file
144
src/components/Layout/Header.js
Normal file
@ -0,0 +1,144 @@
|
||||
import React, { PureComponent, Fragment } from 'react'
|
||||
import { Menu, Icon, Layout, Avatar, Popover, Badge, List, Switch, Tooltip } from 'antd'
|
||||
import { Trans, withI18n } from '@lingui/react'
|
||||
import { Ellipsis } from 'ant-design-pro'
|
||||
import classnames from 'classnames'
|
||||
import PropTypes from 'prop-types'
|
||||
import styles from './Header.less'
|
||||
import * as ycore from 'ycore'
|
||||
import router from 'umi/router'
|
||||
import moment from 'moment'
|
||||
import Bread from './Bread'
|
||||
|
||||
|
||||
let userData = ycore.SDCP()
|
||||
|
||||
|
||||
|
||||
|
||||
@withI18n()
|
||||
class Header extends PureComponent {
|
||||
|
||||
isDarkMode = () => {
|
||||
const {theme} = this.props
|
||||
if (theme == "light") {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
render() {
|
||||
const {
|
||||
i18n,
|
||||
fixed,
|
||||
theme,
|
||||
collapsed,
|
||||
newRouteList,
|
||||
notifications,
|
||||
onCollapseChange,
|
||||
onAllNotificationsRead,
|
||||
} = this.props
|
||||
|
||||
|
||||
|
||||
|
||||
const menuContent = (
|
||||
<Popover
|
||||
placement="bottomRight"
|
||||
trigger="click"
|
||||
key="notifications"
|
||||
overlayClassName={styles.notificationPopover}
|
||||
getPopupContainer={() => document.querySelector('#layoutHeader')}
|
||||
content={
|
||||
<div className={styles.notification}>
|
||||
<List
|
||||
itemLayout="horizontal"
|
||||
dataSource={notifications}
|
||||
locale={{
|
||||
emptyText: <Trans>You have viewed all notifications.</Trans>,
|
||||
}}
|
||||
renderItem={item => (
|
||||
<List.Item className={styles.notificationItem}>
|
||||
<List.Item.Meta
|
||||
title={
|
||||
<Ellipsis tooltip lines={1}>
|
||||
{' '}
|
||||
{item.title}{' '}
|
||||
</Ellipsis>
|
||||
}
|
||||
description={moment(item.date).fromNow()}
|
||||
/>
|
||||
<Icon
|
||||
style={{ fontSize: 10, color: '#ccc' }}
|
||||
type="right"
|
||||
theme="outlined"
|
||||
/>
|
||||
</List.Item>
|
||||
)}
|
||||
/>
|
||||
{notifications.length ? (
|
||||
<div
|
||||
onClick={onAllNotificationsRead}
|
||||
className={styles.clearButton}
|
||||
>
|
||||
<Trans>Clear notifications</Trans>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<Badge
|
||||
count={notifications.length}
|
||||
dot
|
||||
offset={[-10, 10]}
|
||||
className={styles.iconButton}
|
||||
>
|
||||
<Icon className={styles.iconFont} type="bell" />
|
||||
</Badge>
|
||||
</Popover>
|
||||
)
|
||||
|
||||
return (
|
||||
<Layout.Header
|
||||
style={{ padding: 0 }}
|
||||
className={classnames(styles.header, {
|
||||
[styles.fixed]: fixed,
|
||||
[styles.collapsed]: collapsed,
|
||||
})}
|
||||
id={this.isDarkMode()? styles.header_dark : styles.header_light}
|
||||
>
|
||||
<div className={styles.button} onClick={onCollapseChange.bind(this, !collapsed)} >
|
||||
<Icon
|
||||
style={{ fontSize: '23px' }}
|
||||
type={classnames({
|
||||
'pic-right': collapsed,
|
||||
'pic-center': !collapsed,
|
||||
})}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.bread}><Bread theme={theme} routeList={newRouteList} /></div>
|
||||
<div className={styles.rightContainer}>
|
||||
<Tooltip title={'Search'}><a target="_blank" href="" rel="noopener noreferrer"><Icon type="search" className={styles.iconButton} style={{ fontSize: '18px' }} /></a></Tooltip>
|
||||
<Tooltip title={'Help'}><a target="_blank" href="" rel="noopener noreferrer"><Icon type="question-circle-o" className={styles.iconButton} style={{ fontSize: '18px' }} /></a></Tooltip>
|
||||
{menuContent}
|
||||
|
||||
</div>
|
||||
|
||||
</Layout.Header>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Header.propTypes = {
|
||||
fixed: PropTypes.bool,
|
||||
menus: PropTypes.array,
|
||||
theme: PropTypes.string,
|
||||
newRouteList: PropTypes.array,
|
||||
collapsed: PropTypes.bool,
|
||||
onSignOut: PropTypes.func,
|
||||
notifications: PropTypes.array,
|
||||
onThemeChange: PropTypes.func,
|
||||
onCollapseChange: PropTypes.func,
|
||||
onAllNotificationsRead: PropTypes.func,
|
||||
}
|
||||
|
||||
export default Header
|
195
src/components/Layout/Header.less
Normal file
195
src/components/Layout/Header.less
Normal file
@ -0,0 +1,195 @@
|
||||
@import '~themes/vars.less';
|
||||
|
||||
.bread {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.darkmode_btn {
|
||||
margin-bottom: 8px;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
margin-top: 4px;
|
||||
padding: 0 16px;
|
||||
overflow: hidden;
|
||||
font-size: 13px;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
#header_dark{
|
||||
background-color: @DarkMode-backgroud_container;
|
||||
color: @DarkMode-color;
|
||||
transition: background-color 200ms linear;
|
||||
|
||||
}
|
||||
#header_light{
|
||||
background-color: @LightMode-backgroud;
|
||||
color: @LightMode-color;
|
||||
transition: background-color 200ms linear;
|
||||
|
||||
}
|
||||
|
||||
.header {
|
||||
padding: 0;
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
height: 64px;
|
||||
z-index: 9;
|
||||
align-items: center;
|
||||
|
||||
&.fixed {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
width: ~'calc(100% - 370px)';
|
||||
z-index: 10;
|
||||
transition: width 0.2s;
|
||||
|
||||
&.collapsed {
|
||||
width: ~'calc(100% - 115px)';
|
||||
}
|
||||
}
|
||||
|
||||
:global {
|
||||
.ant-menu-submenu-title {
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
|
||||
.ant-menu-horizontal {
|
||||
line-height: 40px;
|
||||
|
||||
&>.ant-menu-submenu:hover {
|
||||
color: @primary-color;
|
||||
background-color: @hover-color;
|
||||
}
|
||||
}
|
||||
|
||||
.ant-menu {
|
||||
border-bottom: none;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.ant-menu-horizontal>.ant-menu-submenu {
|
||||
top: 0;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.ant-menu-horizontal>.ant-menu-item,
|
||||
.ant-menu-horizontal>.ant-menu-submenu {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.ant-menu-horizontal>.ant-menu-item-active,
|
||||
.ant-menu-horizontal>.ant-menu-item-open,
|
||||
.ant-menu-horizontal>.ant-menu-item-selected,
|
||||
.ant-menu-horizontal>.ant-menu-item:hover,
|
||||
.ant-menu-horizontal>.ant-menu-submenu-active,
|
||||
.ant-menu-horizontal>.ant-menu-submenu-open,
|
||||
.ant-menu-horizontal>.ant-menu-submenu-selected,
|
||||
.ant-menu-horizontal>.ant-menu-submenu:hover {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
|
||||
.rightContainer {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.button {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
text-align: center;
|
||||
font-size: 18px;
|
||||
cursor: pointer;
|
||||
transition: @transition-ease-in;
|
||||
|
||||
&:hover {
|
||||
color: @primary-color;
|
||||
background-color: @hover-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
.iconButton {
|
||||
color: #b2b0c7;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border-radius: 24px;
|
||||
cursor: pointer;
|
||||
.background-hover();
|
||||
|
||||
&:hover {
|
||||
.iconFont {
|
||||
color: @primary-color;
|
||||
}
|
||||
}
|
||||
|
||||
&+.iconButton {
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.iconFont {
|
||||
color: #b2b0c7;
|
||||
font-size: 24px;
|
||||
}
|
||||
}
|
||||
.search {
|
||||
padding: 0 12px;
|
||||
&:hover {
|
||||
background: transparent;
|
||||
}
|
||||
}
|
||||
.avatar {
|
||||
margin:~'calc((64px - 24px) / 4.4)'0;
|
||||
margin-right: 8px;
|
||||
color: @primary-color;
|
||||
vertical-align: top;
|
||||
background: rgba(255, 255, 255, 0.85);
|
||||
}
|
||||
|
||||
.notification {
|
||||
padding: 24px 0;
|
||||
|
||||
.notificationItem {
|
||||
transition: all 0.3s;
|
||||
padding: 12px 24px;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
background-color: @hover-color;
|
||||
}
|
||||
}
|
||||
|
||||
.clearButton {
|
||||
text-align: center;
|
||||
height: 48px;
|
||||
line-height: 48px;
|
||||
cursor: pointer;
|
||||
.background-hover();
|
||||
}
|
||||
}
|
||||
|
||||
.notificationPopover {
|
||||
:global {
|
||||
.ant-popover-inner-content {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.ant-popover-arrow {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.ant-list-item-content {
|
||||
flex: 0;
|
||||
margin-left: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
95
src/components/Layout/L_Sider.js
Normal file
95
src/components/Layout/L_Sider.js
Normal file
@ -0,0 +1,95 @@
|
||||
import React, { PureComponent } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { Icon, Switch, Layout, Tag, Divider} from 'antd'
|
||||
import { withI18n, Trans } from '@lingui/react'
|
||||
import ScrollBar from '../ScrollBar'
|
||||
import { config } from 'utils'
|
||||
import styles from './L_Sider.less'
|
||||
import { ycore_worker, DevOptions } from 'ycore';
|
||||
import SiderMenu from './Menu.js'
|
||||
import { CustomMenu } from './local_components'
|
||||
|
||||
@withI18n()
|
||||
class L_Sider extends PureComponent {
|
||||
|
||||
StrictMode = () =>{
|
||||
const { theme } = this.props;
|
||||
if (DevOptions.StrictLightMode == false) {
|
||||
return "dark"
|
||||
}
|
||||
if (DevOptions.StrictLightMode == true && theme == "light") {
|
||||
return "light"
|
||||
}
|
||||
if (DevOptions.StrictLightMode == true && theme == "dark") {
|
||||
return "dark"
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
i18n,
|
||||
menus,
|
||||
theme,
|
||||
isMobile,
|
||||
collapsed,
|
||||
onThemeChange,
|
||||
onCollapseChange,
|
||||
} = this.props
|
||||
|
||||
return (
|
||||
<div className={styles.siderhandler}>
|
||||
<Layout.Sider
|
||||
width={215}
|
||||
style={{ height: '100%' }}
|
||||
theme={this.StrictMode()}
|
||||
// style={{ backgroundColor: '#2d2d2d' }}
|
||||
breakpoint="lg"
|
||||
trigger={null}
|
||||
collapsible
|
||||
collapsed={collapsed}
|
||||
onBreakpoint={isMobile ? null : onCollapseChange}
|
||||
className={styles.sider}
|
||||
>
|
||||
<div className={styles.brand}>
|
||||
{collapsed? <div className={styles.logo}><img className={styles.logocollapsed} src={config.logoPath} /></div> : <div className={styles.logo}><img className={styles.logonotcollapsed} src={config.logoPath} /></div> }
|
||||
</div>
|
||||
|
||||
<div className={styles.menuContainer}>
|
||||
<ScrollBar
|
||||
options={{
|
||||
// Disabled horizontal scrolling, https://github.com/utatti/perfect-scrollbar#options
|
||||
suppressScrollX: true,
|
||||
}}
|
||||
>
|
||||
<SiderMenu
|
||||
menus={menus}
|
||||
theme={this.StrictMode()}
|
||||
isMobile={isMobile}
|
||||
collapsed={collapsed}
|
||||
onCollapseChange={onCollapseChange}
|
||||
/>
|
||||
<CustomMenu
|
||||
menus={menus}
|
||||
theme={this.StrictMode()}
|
||||
isMobile={isMobile}
|
||||
collapsed={collapsed}
|
||||
onCollapseChange={onCollapseChange}
|
||||
/>
|
||||
</ScrollBar>
|
||||
</div>
|
||||
</Layout.Sider>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
L_Sider.propTypes = {
|
||||
menus: PropTypes.array,
|
||||
theme: PropTypes.string,
|
||||
isMobile: PropTypes.bool,
|
||||
collapsed: PropTypes.bool,
|
||||
onThemeChange: PropTypes.func,
|
||||
onCollapseChange: PropTypes.func,
|
||||
}
|
||||
|
||||
export default L_Sider
|
138
src/components/Layout/L_Sider.less
Normal file
138
src/components/Layout/L_Sider.less
Normal file
@ -0,0 +1,138 @@
|
||||
@import '~themes/vars.less';
|
||||
@import (inline) './fonty.css';
|
||||
|
||||
.siderhandler {
|
||||
overflow-x: hidden;
|
||||
height: 100vh;
|
||||
bottom: 0;
|
||||
:global {
|
||||
letter-spacing: 0.6px;
|
||||
font-weight: 500;
|
||||
font-size: 1.4447884416924666vh;
|
||||
.ant-layout-sider-dark {
|
||||
background-color: @DarkMode-backgroud;
|
||||
color: @DarkMode-color;
|
||||
-webkit-box-shadow: 13px 4px 34px 0px rgba(0, 0, 0, 0.05);
|
||||
-moz-box-shadow: 13px 4px 34px 0px rgba(0, 0, 0, 0.05);
|
||||
box-shadow: 13px 4px 34px 0px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
.ant-layout-sider-light {
|
||||
background-color: @LightMode-backgroud;
|
||||
color: @LightMode-color;
|
||||
-webkit-box-shadow: 13px 4px 34px 0px rgba(0, 0, 0, 0.05);
|
||||
-moz-box-shadow: 13px 4px 34px 0px rgba(0, 0, 0, 0.05);
|
||||
box-shadow: 13px 4px 34px 0px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
.ant-menu-dark {
|
||||
background-color: @DarkMode-backgroud;
|
||||
color: @DarkMode-color;
|
||||
-webkit-box-shadow: 13px 4px 34px 0px rgba(0, 0, 0, 0.005);
|
||||
-moz-box-shadow: 13px 4px 34px 0px rgba(0, 0, 0, 0.005);
|
||||
box-shadow: 13px 4px 34px 0px rgba(0, 0, 0, 0.005);
|
||||
:global{
|
||||
color: @DarkMode-color;
|
||||
}
|
||||
}
|
||||
.ant-menu-light {
|
||||
background-color: @LightMode-backgroud;
|
||||
color: @LightMode-color;
|
||||
-webkit-box-shadow: 13px 4px 34px 0px rgba(0, 0, 0, 0.005);
|
||||
-moz-box-shadow: 13px 4px 34px 0px rgba(0, 0, 0, 0.005);
|
||||
box-shadow: 13px 4px 34px 0px rgba(0, 0, 0, 0.005);
|
||||
}
|
||||
.ant-menu-dark .ant-menu-inline .ant-menu-sub {
|
||||
-webkit-box-shadow: 0px 27px 29px -18px rgba(23, 23, 23, 0);
|
||||
-moz-box-shadow: 0px 27px 29px -18px rgba(23, 23, 23, 0);
|
||||
box-shadow: 0px 27px 29px -18px rgba(23, 23, 23, 0);
|
||||
background-color: @DarkMode-backgroud;
|
||||
}
|
||||
.ant-menu-light .ant-menu-inline .ant-menu-sub {
|
||||
-webkit-box-shadow: 0px 27px 29px -18px rgba(23, 23, 23, 0);
|
||||
-moz-box-shadow: 0px 27px 29px -18px rgba(23, 23, 23, 0);
|
||||
box-shadow: 0px 27px 29px -18px rgba(23, 23, 23, 0);
|
||||
background-color: @LightMode-backgroud;
|
||||
}
|
||||
.ant-menu-dark .ant-menu-item::after {
|
||||
border-right: 3px solid #00FEA1;
|
||||
}
|
||||
.ant-menu-light .ant-menu-item::after {
|
||||
border-right: 3px solid #00FEA1;
|
||||
}
|
||||
.ant-menu-dark .ant-menu-item-selected {
|
||||
background: rgb(80, 78, 82);
|
||||
}
|
||||
.ant-menu-light .ant-menu-item-selected {
|
||||
background: rgb(219, 219, 219);
|
||||
}
|
||||
.ant-layout-sider-children {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
.sider {
|
||||
.brand {
|
||||
z-index: 1;
|
||||
height: 70px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0 23px;
|
||||
.logo {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
.logocollapsed{
|
||||
width: 68px;
|
||||
transition: width 0.1s;
|
||||
}
|
||||
.logonotcollapsed {
|
||||
width: 90px;
|
||||
transition: width 0.1s;
|
||||
}
|
||||
}
|
||||
}
|
||||
.menuContainer {
|
||||
height: ~'calc(100vh - 120px)';
|
||||
overflow-x: hidden;
|
||||
flex: 1;
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background-color: transparent;
|
||||
}
|
||||
&:hover {
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background-color: rgba(59, 59, 59, 0.2);
|
||||
}
|
||||
}
|
||||
:global {
|
||||
.ant-menu-inline .ant-menu-item {
|
||||
font-size: 14px;
|
||||
}
|
||||
.ant-menu-dark .ant-menu-item a {
|
||||
color: @DarkMode-color;
|
||||
}
|
||||
.ant-menu-light .ant-menu-item a {
|
||||
color: @LightMode-color;
|
||||
}
|
||||
.ant-menu-item a:hover {
|
||||
color: #00FEA1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@keyframes fadeLeftIn {
|
||||
0% {
|
||||
transform: translateX(5px);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translateX(0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
132
src/components/Layout/Menu.js
Normal file
132
src/components/Layout/Menu.js
Normal file
@ -0,0 +1,132 @@
|
||||
import React, { PureComponent, Fragment } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { Menu, Icon } from 'antd'
|
||||
import Navlink from 'umi/navlink'
|
||||
import withRouter from 'umi/withRouter'
|
||||
import {SDCP} from 'ycore'
|
||||
import {
|
||||
arrayToTree,
|
||||
queryAncestors,
|
||||
pathMatchRegexp,
|
||||
addLangPrefix,
|
||||
} from 'utils'
|
||||
import store from 'store'
|
||||
import styles from './Menu.less'
|
||||
|
||||
|
||||
const { SubMenu } = Menu
|
||||
|
||||
|
||||
@withRouter
|
||||
class SiderMenu extends PureComponent {
|
||||
state = {
|
||||
openKeys: store.get('openKeys') || [],
|
||||
}
|
||||
|
||||
onOpenChange = openKeys => {
|
||||
const { menus } = this.props
|
||||
const rootSubmenuKeys = menus.filter(_ => !_.menuParentId).map(_ => _.id)
|
||||
|
||||
const latestOpenKey = openKeys.find(
|
||||
key => this.state.openKeys.indexOf(key) === -1
|
||||
)
|
||||
|
||||
let newOpenKeys = openKeys
|
||||
if (rootSubmenuKeys.indexOf(latestOpenKey) !== -1) {
|
||||
newOpenKeys = latestOpenKey ? [latestOpenKey] : []
|
||||
}
|
||||
|
||||
this.setState({
|
||||
openKeys: newOpenKeys,
|
||||
})
|
||||
store.set('openKeys', newOpenKeys)
|
||||
}
|
||||
|
||||
generateMenus = data => {
|
||||
return data.map(item => {
|
||||
if (item.children) {
|
||||
return (
|
||||
<SubMenu
|
||||
key={item.id}
|
||||
className={styles.SubMenuItems}
|
||||
title={
|
||||
<Fragment>
|
||||
{item.icon && <Icon type={item.icon} />}
|
||||
<span className={styles.SubItemTitle}>{item.name}</span>
|
||||
</Fragment>
|
||||
}
|
||||
>
|
||||
{this.generateMenus(item.children)}
|
||||
</SubMenu>
|
||||
)
|
||||
}
|
||||
return (
|
||||
<Menu.Item key={item.id} >
|
||||
<Navlink to={addLangPrefix(item.route) || '#'}>
|
||||
{item.icon && <Icon type={item.icon} />}
|
||||
<span>{item.name}</span>
|
||||
</Navlink>
|
||||
</Menu.Item>
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
collapsed,
|
||||
theme,
|
||||
menus,
|
||||
location,
|
||||
isMobile,
|
||||
onCollapseChange,
|
||||
} = this.props
|
||||
|
||||
// Generating tree-structured data for menu content.
|
||||
const menuTree = arrayToTree(menus, 'id', 'menuParentId')
|
||||
|
||||
// Find a menu that matches the pathname.
|
||||
const currentMenu = menus.find(
|
||||
_ => _.route && pathMatchRegexp(_.route, location.pathname)
|
||||
)
|
||||
|
||||
// Find the key that should be selected according to the current menu.
|
||||
const selectedKeys = currentMenu
|
||||
? queryAncestors(menus, currentMenu, 'menuParentId').map(_ => _.id)
|
||||
: []
|
||||
|
||||
const menuProps = collapsed
|
||||
? {}
|
||||
: {
|
||||
openKeys: this.state.openKeys,
|
||||
}
|
||||
|
||||
return (
|
||||
<Menu
|
||||
theme={theme}
|
||||
mode="inline"
|
||||
onOpenChange={this.onOpenChange}
|
||||
selectedKeys={selectedKeys}
|
||||
onClick={
|
||||
isMobile
|
||||
? () => {
|
||||
onCollapseChange(true)
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
{...menuProps}
|
||||
>
|
||||
{this.generateMenus(menuTree)}
|
||||
</Menu>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
SiderMenu.propTypes = {
|
||||
menus: PropTypes.array,
|
||||
theme: PropTypes.string,
|
||||
isMobile: PropTypes.bool,
|
||||
collapsed: PropTypes.bool,
|
||||
onCollapseChange: PropTypes.func,
|
||||
}
|
||||
|
||||
export default SiderMenu
|
5
src/components/Layout/Menu.less
Normal file
5
src/components/Layout/Menu.less
Normal file
@ -0,0 +1,5 @@
|
||||
@import '~themes/vars.less';
|
||||
|
||||
.SubItemTitle {
|
||||
font-size: 14px;
|
||||
}
|
125
src/components/Layout/R_Sider.js
Normal file
125
src/components/Layout/R_Sider.js
Normal file
@ -0,0 +1,125 @@
|
||||
import React, { PureComponent, StrictMode } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { Icon, Switch, Layout, Tag, Divider, Drawer, Avatar, Menu} from 'antd'
|
||||
import { withI18n, Trans } from '@lingui/react'
|
||||
import classNames from 'classnames'
|
||||
import router from 'umi/router'
|
||||
import { SDCP, LogoutCall, DevOptions} from 'ycore'
|
||||
|
||||
import styles from './R_Sider.less'
|
||||
|
||||
let userData = SDCP()
|
||||
|
||||
@withI18n()
|
||||
class R_Sider extends PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
isHover: false
|
||||
};
|
||||
this.hover = this.hover.bind(this);
|
||||
}
|
||||
hover(e) {
|
||||
this.setState({
|
||||
isHover: !this.state.isHover
|
||||
});
|
||||
}
|
||||
handleClickMenu = e => {
|
||||
e.key === 'SignOut' && LogoutCall()
|
||||
e.key === 'settingpage' && router.push('/settings')
|
||||
e.key === 'accountpage' && router.push('/account')
|
||||
}
|
||||
Balancer() {
|
||||
const { collapsed, } = this.props;
|
||||
const { isHover } = this.state;
|
||||
if (collapsed == false) {
|
||||
return false
|
||||
}
|
||||
if (isHover == false ){
|
||||
if (collapsed == true) {
|
||||
return true
|
||||
}
|
||||
return true
|
||||
}else{
|
||||
return false
|
||||
}
|
||||
|
||||
}
|
||||
StrictMode = () =>{
|
||||
const { theme } = this.props;
|
||||
if (DevOptions.StrictLightMode == false) {
|
||||
return "dark"
|
||||
}
|
||||
if (DevOptions.StrictLightMode == true && theme == "light") {
|
||||
return "light"
|
||||
}
|
||||
if (DevOptions.StrictLightMode == true && theme == "dark") {
|
||||
return "dark"
|
||||
}
|
||||
}
|
||||
render() {
|
||||
const { theme, onThemeChange} = this.props;
|
||||
|
||||
return (
|
||||
<div className={styles.siderwrapper}>
|
||||
<Layout.Sider
|
||||
collapsedWidth="30"
|
||||
theme={this.StrictMode()}
|
||||
width="140"
|
||||
collapsed={this.Balancer()}
|
||||
className={styles.sider}
|
||||
style={this.Balancer()? {backgroundColor: 'rgba(0, 0, 0, 0.1)'} : null}
|
||||
onMouseEnter={this.hover}
|
||||
onMouseLeave={this.hover}
|
||||
>
|
||||
|
||||
<div className={styles.siderhead}>
|
||||
<Avatar size={this.Balancer()? "small" : "large"} shape={this.Balancer()? "circle" : "square"} src={userData.avatar} className={styles.avatar} />
|
||||
{this.Balancer()? null : <span>{userData.username}</span>}
|
||||
</div>
|
||||
{this.Balancer()? <div style={{ height: "100%", textAlign: "center" }} ><Icon onClick={this.hover} type="left" style={{ color: "#2F2E30", position: "absolute", bottom: "50%" }} /></div> :
|
||||
<div className={styles.sidercontainer}>
|
||||
<Menu className={styles.menuItems} mode="vertical" onClick={this.handleClickMenu}>
|
||||
<Menu.Item key="accountpage">
|
||||
<Icon type="idcard" />
|
||||
<Trans>Account</Trans>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="settingpage">
|
||||
<Icon type="setting" />
|
||||
<Trans>Settings</Trans>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="LightMode" disabled={false}>
|
||||
<Icon type="bg-colors" />
|
||||
<Switch
|
||||
onChange={onThemeChange.bind(
|
||||
this,
|
||||
theme === 'light' ? 'dark' : 'light'
|
||||
)}
|
||||
checkedChildren="Dark"
|
||||
unCheckedChildren="Light"
|
||||
defaultChecked={theme === 'dark'}
|
||||
/>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="SignOut" className={styles.SignOut} >
|
||||
<Icon type="logout" style={{ color: 'red' }} />
|
||||
<Trans>Logout</Trans>
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
</div>
|
||||
}
|
||||
</Layout.Sider>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
R_Sider.propTypes = {
|
||||
menus: PropTypes.array,
|
||||
theme: PropTypes.string,
|
||||
isMobile: PropTypes.bool,
|
||||
collapsed: PropTypes.bool,
|
||||
onThemeChange: PropTypes.func,
|
||||
onCollapseChange: PropTypes.func,
|
||||
}
|
||||
|
||||
export default R_Sider
|
131
src/components/Layout/R_Sider.less
Normal file
131
src/components/Layout/R_Sider.less
Normal file
@ -0,0 +1,131 @@
|
||||
@import '~themes/vars.less';
|
||||
@import (inline) './fonty.css';
|
||||
|
||||
@LDarkMode-backgroud: rgba(47, 46, 48, 0.74);
|
||||
@LLightMode-backgroud: #fff;
|
||||
|
||||
@LDarkMode-color: #fff;
|
||||
@LLightMode-color: #2F2E30;
|
||||
|
||||
.siderwrapper {
|
||||
height: 100%;
|
||||
right: 0;
|
||||
position: absolute;
|
||||
:global {
|
||||
.ant-menu-inline, .ant-menu-vertical, .ant-menu-vertical-left {
|
||||
:hover {
|
||||
color: #00FEA1;
|
||||
}
|
||||
border-right: 1px solid transparent;
|
||||
}
|
||||
.ant-layout-sider-dark {
|
||||
background-color: @LDarkMode-backgroud;
|
||||
color: @DarkMode-color;
|
||||
}
|
||||
.ant-layout-sider-light {
|
||||
background-color: @LightMode-backgroud;
|
||||
color: @LightMode-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
.sider {
|
||||
height: 100%;
|
||||
z-index: 50;
|
||||
:global {
|
||||
.ant-menu-sub {
|
||||
font-size: 14px;
|
||||
-webkit-box-shadow: 13px 4px 34px 0px rgba(0, 0, 0, 0.005);
|
||||
-moz-box-shadow: 13px 4px 34px 0px rgba(0, 0, 0, 0.005);
|
||||
box-shadow: 13px 4px 34px 0px rgba(0, 0, 0, 0.005);
|
||||
}
|
||||
.ant-menu-dark {
|
||||
background-color: @LDarkMode-backgroud;
|
||||
color: @LDarkMode-color;
|
||||
}
|
||||
.ant-menu-light {
|
||||
background-color: @LLightMode-backgroud;
|
||||
color: @LLightMode-color;
|
||||
}
|
||||
}
|
||||
.siderhead{
|
||||
font-family: 'Source Sans Pro', sans-serif;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
::first-letter{
|
||||
margin-left: 7px;
|
||||
}
|
||||
height: 60px;
|
||||
font-size: 17px;
|
||||
}
|
||||
.sidercontainer{
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.menuItems{
|
||||
background-color: transparent;
|
||||
color: @LDarkMode-color;
|
||||
margin-bottom: 8px;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
animation: fadein 0.5s;
|
||||
:global {
|
||||
.ant-menu-item-selected{
|
||||
background-color: rgba(82, 82, 82, 0.562);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
.SignOut{
|
||||
margin-bottom: 7px;
|
||||
bottom: 0;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
}
|
||||
.menuContainer {
|
||||
height: ~'calc(100vh - 120px)';
|
||||
overflow-x: hidden;
|
||||
flex: 1;
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background-color: rgba(59, 59, 59, 0.2);
|
||||
}
|
||||
}
|
||||
|
||||
:global {
|
||||
.ant-menu-inline .ant-menu-item {
|
||||
font-size: 14px;
|
||||
font-family: 'Source Sans Pro', sans-serif;
|
||||
}
|
||||
|
||||
.ant-menu-dark .ant-menu-item a {
|
||||
color: rgb(197, 197, 197);
|
||||
}
|
||||
|
||||
.ant-menu-item a:hover {
|
||||
color: #00FEA1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeLeftIn {
|
||||
0% {
|
||||
transform: translateX(5px);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translateX(0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
4
src/components/Layout/fonty.css
Normal file
4
src/components/Layout/fonty.css
Normal file
@ -0,0 +1,4 @@
|
||||
@import url('https://fonts.googleapis.com/css?family=Alata&display=swap');
|
||||
@import url('https://fonts.googleapis.com/css?family=Poppins:300,300i,500,500i,700');
|
||||
@import url('https://fonts.googleapis.com/css?family=Source+Sans+Pro&display=swap');
|
||||
@import url('https://fonts.googleapis.com/css?family=Kulim+Park&display=swap');
|
7
src/components/Layout/index.js
Normal file
7
src/components/Layout/index.js
Normal file
@ -0,0 +1,7 @@
|
||||
import Header from './Header'
|
||||
import Bread from './Bread'
|
||||
import L_Sider from './L_Sider'
|
||||
import R_Sider from './R_Sider'
|
||||
import Control from './Control'
|
||||
|
||||
export { Header, Bread, L_Sider, R_Sider, Control }
|
132
src/components/Layout/local_components/CustomMenu/index.js
Normal file
132
src/components/Layout/local_components/CustomMenu/index.js
Normal file
@ -0,0 +1,132 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { Menu, Icon, Button, Divider, Tooltip, message } from 'antd'
|
||||
import Navlink from 'umi/navlink'
|
||||
import withRouter from 'umi/withRouter'
|
||||
import { arrayToTree, addLangPrefix} from 'utils'
|
||||
import store from 'store'
|
||||
import styles from './style.less'
|
||||
|
||||
@withRouter
|
||||
class CustomMenu extends React.Component {
|
||||
constructor(props){
|
||||
super(props)
|
||||
this.state = {
|
||||
pins: store.get('pins') || [],
|
||||
EditMode: false
|
||||
}
|
||||
this.HandleEditMode = this.HandleEditMode.bind(this);
|
||||
}
|
||||
SetDefaultPins(){
|
||||
this.setState({ pins: [{id: "1", icon: "bug", name: "Debug", route: "/debug"}, {id: "2", icon: "fire", name: "Empty Pin", route: ""}] })
|
||||
}
|
||||
DeletePin = (item) => {
|
||||
const items = this.state.pins.filter(pin => pin.id !== item.id);
|
||||
this.setState({ pins: items });
|
||||
message.success(`Deleted ${item.name} of your pins...`)
|
||||
}
|
||||
HandleEditMode(){
|
||||
if (this.state.EditMode == true) {
|
||||
store.set('pins', this.state.pins)
|
||||
message.success('Changes have been saved successfully')
|
||||
}
|
||||
this.setState({ EditMode: !this.state.EditMode })
|
||||
}
|
||||
|
||||
generateMenus = data => {
|
||||
const { EditMode } = this.state;
|
||||
return data.map(item => {
|
||||
if (EditMode == true) {
|
||||
return (
|
||||
<div className={styles.RemovePin} key={item.id}>
|
||||
<Button className={styles.RemovePin} onClick={ () => this.DeletePin(item)} type='dashed'>
|
||||
<Icon type="delete" style={{ color: 'rgb(245, 48, 48)' }} />
|
||||
<span>{item.name}</span>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
)
|
||||
}else {
|
||||
return (
|
||||
<Menu.Item key={item.id} >
|
||||
<Navlink to={addLangPrefix(item.route) || '#'}>
|
||||
{item.icon && <Icon type={item.icon} />}
|
||||
<span>{item.name}</span>
|
||||
</Navlink>
|
||||
</Menu.Item>
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
componentDidUpdate(){
|
||||
const { EditMode } = this.state;
|
||||
const { collapsed } = this.props;
|
||||
if (EditMode == true && collapsed){
|
||||
this.HandleEditMode()
|
||||
}
|
||||
}
|
||||
isDarkMode = () => {
|
||||
const { theme } = this.props
|
||||
if (theme == "light") {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
render() {
|
||||
const {
|
||||
collapsed,
|
||||
theme,
|
||||
isMobile,
|
||||
onCollapseChange,
|
||||
} = this.props
|
||||
const { pins, EditMode } = this.state;
|
||||
// Generating tree-structured data for menu content.
|
||||
const menuTree = arrayToTree(pins, 'id', 'menuParentId')
|
||||
const menuProps = collapsed
|
||||
? {}
|
||||
: {
|
||||
openKeys: this.state.openKeys,
|
||||
}
|
||||
return (
|
||||
<Menu
|
||||
theme={theme}
|
||||
mode="inline"
|
||||
onClick={
|
||||
isMobile
|
||||
? () => {
|
||||
onCollapseChange(true)
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
{...menuProps}
|
||||
>
|
||||
<div className={styles.DividerZT}><Divider dashed className={ styles.DividerZT } style={{ margin: '15px 0 5px 0' }} /></div>
|
||||
{collapsed? null : <div className={styles.EditBTN}>
|
||||
<Button className={EditMode? styles.edit_pins_active : styles.edit_pins} onClick={this.HandleEditMode} id={this.isDarkMode()? styles.edit_btn_dark : styles.edit_btn_light} type="link">
|
||||
<span className={styles.circle}><Icon className={EditMode? styles.icon_active : styles.icon} type={EditMode? "save" : "pushpin"}/> </span>
|
||||
<span className={styles.button_text}>{EditMode? 'Save' : 'Edit pins'}</span>
|
||||
</Button>
|
||||
|
||||
</div>}
|
||||
|
||||
|
||||
{this.generateMenus(menuTree)}
|
||||
|
||||
{EditMode? (pins.length < 1)? <div style={{ marginTop: '15px', textAlign: 'center', }} ><Button type='ghost' style={{ width: 'auto' }} onClick={() => this.SetDefaultPins()}>Set Default Pins</Button></div> : null : (pins.length < 1)? <Icon style={{ marginTop: '15px', width: '100%', fontSize: '20px', color: '#666' }} type="unordered-list" /> : null }
|
||||
|
||||
</Menu>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
CustomMenu.propTypes = {
|
||||
menus: PropTypes.array,
|
||||
theme: PropTypes.string,
|
||||
isMobile: PropTypes.bool,
|
||||
collapsed: PropTypes.bool,
|
||||
onCollapseChange: PropTypes.func,
|
||||
}
|
||||
|
||||
export default CustomMenu
|
181
src/components/Layout/local_components/CustomMenu/style.less
Normal file
181
src/components/Layout/local_components/CustomMenu/style.less
Normal file
@ -0,0 +1,181 @@
|
||||
@import '~themes/vars.less';
|
||||
|
||||
|
||||
#edit_btn_dark {
|
||||
background-color: @DarkMode-backgroud;
|
||||
color: @DarkMode-color;
|
||||
}
|
||||
#edit_btn_light {
|
||||
background-color: @LightMode-backgroud;
|
||||
color: @LightMode-color;
|
||||
}
|
||||
|
||||
.SubItemTitle {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.SubMenuItems {
|
||||
z-index: 98;
|
||||
}
|
||||
|
||||
@keyframes fadein {
|
||||
from { opacity: 0; }
|
||||
to { opacity: 1; }
|
||||
}
|
||||
|
||||
.RemovePin {
|
||||
color: #6b686e;
|
||||
margin-bottom: 8px;
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
font-size: 14px;
|
||||
background: transparent;
|
||||
border-color: transparent;
|
||||
animation: fadein 0.5s;
|
||||
:hover {
|
||||
color: rgb(245, 48, 48);
|
||||
border-left-style: solid;
|
||||
}
|
||||
:global {
|
||||
.ant-btn:hover,
|
||||
.ant-btn:focus,
|
||||
.ant-btn:active,
|
||||
.ant-btn.active {
|
||||
border-width: 1px 1px 1px 25px;
|
||||
width: 85%;
|
||||
background: transparent;
|
||||
transform: translate(10px, 0px);
|
||||
border-color: rgb(245, 48, 48);
|
||||
color: #fff;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.EditBTN {
|
||||
@bg: #f3f8fa;
|
||||
@white: #fff;
|
||||
@black: #282936;
|
||||
|
||||
.transition(@property: all, @duration: 0.45s, @ease: cubic-bezier(0.65,0,.076,1)) {
|
||||
transition: @property @duration @ease;
|
||||
}
|
||||
|
||||
button {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
outline: none;
|
||||
border: 0;
|
||||
vertical-align: middle;
|
||||
background: transparent;
|
||||
padding: 0;
|
||||
|
||||
&.edit_pins {
|
||||
width: 12rem;
|
||||
height: auto;
|
||||
.circle {
|
||||
.transition(all, 0.45s, cubic-bezier(0.65,0,.076,1));
|
||||
position: relative;
|
||||
display: block;
|
||||
margin: 0;
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
background: transparent;
|
||||
border-radius: 0rem;
|
||||
.icon {
|
||||
.transition(all, 0.45s, cubic-bezier(0.65, 0, .076, 1));
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
display: none;
|
||||
padding: 0.45rem 0;
|
||||
margin: 0 0 0 1.85rem;
|
||||
font-weight: 500;
|
||||
line-height: 1.6;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.button_text {
|
||||
.transition(all, 0.45s, cubic-bezier(0.65,0,.076,1));
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 1;
|
||||
bottom: 0;
|
||||
padding: 0.45rem 0;
|
||||
margin: 0 0 0 1.85rem;
|
||||
font-weight: 500;
|
||||
line-height: 1.6;
|
||||
text-align: center;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
}
|
||||
|
||||
&.edit_pins_active {
|
||||
width: 12rem;
|
||||
height: auto;
|
||||
.circle {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 2rem;
|
||||
|
||||
.icon_active {
|
||||
position: absolute;
|
||||
padding: 0.45rem 0;
|
||||
font-weight: 500;
|
||||
line-height: 1.9;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.button_text {
|
||||
transform: translate(25px,0);
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 1;
|
||||
bottom: 0;
|
||||
padding: 0.45rem 0;
|
||||
margin: 0 0 0 1.85rem;
|
||||
|
||||
font-weight: 500;
|
||||
line-height: 1.6;
|
||||
text-align: center;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
}
|
||||
|
||||
.circle_btn_light {
|
||||
background-color: @LightMode-backgroud;
|
||||
color: @LightMode-color;
|
||||
}
|
||||
&:hover {
|
||||
.circle {
|
||||
background-color: @white;
|
||||
width: 100%;
|
||||
.icon {
|
||||
color: @black;
|
||||
display: block;
|
||||
transform: translate(1rem, 0);
|
||||
}
|
||||
}
|
||||
.button_text {
|
||||
transform: translate(25px,0);
|
||||
color: @black;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.DividerZT {
|
||||
z-index: 99;
|
||||
transform: translate(0px, -3px);
|
||||
border-width: 2px 5px 0;
|
||||
border-color: rgba(236, 236, 236, 0.24);
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,32 @@
|
||||
@import '~antd/es/style/themes/default.less';
|
||||
|
||||
.headerSearch {
|
||||
:global(.anticon-search) {
|
||||
font-size: 16px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.input {
|
||||
width: 0;
|
||||
background: transparent;
|
||||
border-radius: 0;
|
||||
transition: width 0.3s, margin-left 0.3s;
|
||||
:global(.ant-select-selection) {
|
||||
background: transparent;
|
||||
}
|
||||
input {
|
||||
padding-right: 0;
|
||||
padding-left: 0;
|
||||
border: 0;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
&,
|
||||
&:hover,
|
||||
&:focus {
|
||||
border-bottom: 1px solid @border-color-base;
|
||||
}
|
||||
&.show {
|
||||
width: 210px;
|
||||
margin-left: 8px;
|
||||
}
|
||||
}
|
||||
}
|
147
src/components/Layout/local_components/HeaderSearch/index.tsx
Normal file
147
src/components/Layout/local_components/HeaderSearch/index.tsx
Normal file
@ -0,0 +1,147 @@
|
||||
import { AutoComplete, Icon, Input } from 'antd';
|
||||
import { AutoCompleteProps, DataSourceItemType } from 'antd/es/auto-complete';
|
||||
import React, { Component } from 'react';
|
||||
|
||||
import classNames from 'classnames';
|
||||
import debounce from 'lodash/debounce';
|
||||
var styles = require('./index.less')
|
||||
|
||||
export interface HeaderSearchProps {1
|
||||
onPressEnter: (value: string) => void;
|
||||
onSearch: (value: string) => void;
|
||||
onChange: (value: string) => void;
|
||||
onVisibleChange: (b: boolean) => void;
|
||||
className: string;
|
||||
placeholder: string;
|
||||
defaultActiveFirstOption: boolean;
|
||||
dataSource: DataSourceItemType[];
|
||||
defaultOpen: boolean;
|
||||
open?: boolean;
|
||||
defaultValue?: string;
|
||||
}
|
||||
|
||||
interface HeaderSearchState {
|
||||
value?: string;
|
||||
searchMode: boolean;
|
||||
}
|
||||
|
||||
export default class HeaderSearch extends Component<HeaderSearchProps, HeaderSearchState> {
|
||||
static defaultProps = {
|
||||
defaultActiveFirstOption: false,
|
||||
onPressEnter: () => {},
|
||||
onSearch: () => {},
|
||||
onChange: () => {},
|
||||
className: '',
|
||||
placeholder: '',
|
||||
dataSource: [],
|
||||
defaultOpen: false,
|
||||
onVisibleChange: () => {},
|
||||
};
|
||||
|
||||
static getDerivedStateFromProps(props: HeaderSearchProps) {
|
||||
if ('open' in props) {
|
||||
return {
|
||||
searchMode: props.open,
|
||||
};
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private inputRef: Input | null = null;
|
||||
|
||||
constructor(props: HeaderSearchProps) {
|
||||
super(props);
|
||||
this.state = {
|
||||
searchMode: props.defaultOpen,
|
||||
value: props.defaultValue,
|
||||
};
|
||||
// this.debouncePressEnter = debounce(this.debouncePressEnter, 500, {
|
||||
// leading: true,
|
||||
// trailing: false,
|
||||
// });
|
||||
}
|
||||
|
||||
// onKeyDown = (e: React.KeyboardEvent) => {
|
||||
// if (e.key === 'Enter') {
|
||||
// this.debouncePressEnter();
|
||||
// }
|
||||
// };
|
||||
|
||||
// onChange: AutoCompleteProps['onChange'] = value => {
|
||||
// if (typeof value === 'string') {
|
||||
// const { onSearch, onChange } = this.props;
|
||||
// this.setState({ value });
|
||||
// if (onSearch) {
|
||||
// onSearch(value);
|
||||
// }
|
||||
// if (onChange) {
|
||||
// onChange(value);
|
||||
// }
|
||||
// }
|
||||
// };
|
||||
|
||||
// enterSearchMode = () => {
|
||||
// const { onVisibleChange } = this.props;
|
||||
// onVisibleChange(true);
|
||||
// this.setState({ searchMode: true }, () => {
|
||||
// const { searchMode } = this.state;
|
||||
// if (searchMode && this.inputRef) {
|
||||
// this.inputRef.focus();
|
||||
// }
|
||||
// });
|
||||
// };
|
||||
|
||||
// leaveSearchMode = () => {
|
||||
// this.setState({
|
||||
// searchMode: false,
|
||||
// });
|
||||
// };
|
||||
|
||||
// debouncePressEnter = () => {
|
||||
// const { onPressEnter } = this.props;
|
||||
// const { value } = this.state;
|
||||
// onPressEnter(value || '');
|
||||
// };
|
||||
|
||||
render() {
|
||||
const { className, defaultValue, placeholder, open, ...restProps } = this.props;
|
||||
const { searchMode, value } = this.state;
|
||||
delete restProps.defaultOpen; // for rc-select not affected
|
||||
const inputClass = classNames(styles.input, {
|
||||
[styles.show]: searchMode,
|
||||
});
|
||||
|
||||
return (
|
||||
<span
|
||||
className={classNames(className, styles.headerSearch)}
|
||||
// onClick={this.enterSearchMode}
|
||||
onTransitionEnd={({ propertyName }) => {
|
||||
if (propertyName === 'width' && !searchMode) {
|
||||
const { onVisibleChange } = this.props;
|
||||
onVisibleChange(searchMode);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Icon type="search" key="Icon" />
|
||||
<AutoComplete
|
||||
key="AutoComplete"
|
||||
{...restProps}
|
||||
className={inputClass}
|
||||
value={value}
|
||||
// onChange={this.onChange}
|
||||
>
|
||||
<Input
|
||||
// ref={node => {
|
||||
// this.inputRef = node;
|
||||
// }}
|
||||
defaultValue={defaultValue}
|
||||
aria-label={placeholder}
|
||||
placeholder={placeholder}
|
||||
// onKeyDown={this.onKeyDown}
|
||||
// onBlur={this.leaveSearchMode}
|
||||
/>
|
||||
</AutoComplete>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
}
|
4
src/components/Layout/local_components/index.js
Normal file
4
src/components/Layout/local_components/index.js
Normal file
@ -0,0 +1,4 @@
|
||||
import CustomMenu from './CustomMenu'
|
||||
|
||||
|
||||
export { CustomMenu }
|
13
src/components/Layout/logo.scss
Normal file
13
src/components/Layout/logo.scss
Normal file
@ -0,0 +1,13 @@
|
||||
@import url('https://fonts.googleapis.com/css?family=Nunito:400&display=swap');
|
||||
|
||||
.typo1 {
|
||||
font-family: 'Nunito', sans-serif;
|
||||
vertical-align: text-top;
|
||||
color: #333333;
|
||||
font-size: 25px;
|
||||
display: inline-block;
|
||||
font-weight: 400;
|
||||
white-space: nowrap;
|
||||
margin-left: 13px;
|
||||
margin-top: 25px;
|
||||
}
|
36
src/components/Loader/Loader.js
Normal file
36
src/components/Loader/Loader.js
Normal file
@ -0,0 +1,36 @@
|
||||
import React from 'react'
|
||||
import {CoreLoader} from 'components'
|
||||
import { DevOptions } from 'ycore'
|
||||
import PropTypes from 'prop-types'
|
||||
import classNames from 'classnames'
|
||||
import styles from './Loader.less'
|
||||
|
||||
const Loader = ({ spinning = true, fullScreen }) => {
|
||||
if (DevOptions.InfiniteLoading == true) {
|
||||
return (
|
||||
<div className={styles.loader}>
|
||||
<div className={styles.warpper}>
|
||||
<CoreLoader type='circle' />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
return (
|
||||
<div
|
||||
className={classNames(styles.loader, {
|
||||
[styles.hidden]: !spinning,
|
||||
[styles.fullScreen]: fullScreen,
|
||||
})}
|
||||
>
|
||||
<div className={styles.warpper}>
|
||||
<CoreLoader type='circle' />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Loader.propTypes = {
|
||||
spinning: PropTypes.bool,
|
||||
fullScreen: PropTypes.bool,
|
||||
}
|
||||
|
||||
export default Loader;
|
68
src/components/Loader/Loader.less
Normal file
68
src/components/Loader/Loader.less
Normal file
@ -0,0 +1,68 @@
|
||||
.loader {
|
||||
background-color: rgba(255, 255, 255, 0.945);
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
z-index: 100000;
|
||||
display: flex;
|
||||
justify-content: right;
|
||||
float: right;
|
||||
opacity: 1;
|
||||
text-align: center;
|
||||
|
||||
&.fullScreen {
|
||||
position: fixed;
|
||||
}
|
||||
|
||||
.warpper {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
display: inline-flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-around;
|
||||
}
|
||||
|
||||
.inner {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
margin: 0 auto;
|
||||
text-indent: -12345px;
|
||||
border-top: 1px solid rgba(0, 0, 0, 0.08);
|
||||
border-right: 1px solid rgba(0, 0, 0, 0.08);
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.08);
|
||||
border-left: 1px solid rgba(0, 0, 0, 0.7);
|
||||
border-radius: 50%;
|
||||
z-index: 100001;
|
||||
|
||||
:local {
|
||||
animation: spinner 600ms infinite linear;
|
||||
}
|
||||
}
|
||||
|
||||
.text {
|
||||
width: 100px;
|
||||
height: 20px;
|
||||
text-align: center;
|
||||
font-size: 12px;
|
||||
letter-spacing: 4px;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
&.hidden {
|
||||
z-index: -1;
|
||||
opacity: 0;
|
||||
transition: opacity 1s ease 0.5s, z-index 0.1s ease 1.5s;
|
||||
}
|
||||
}
|
||||
@keyframes spinner {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
33
src/components/Page/Page.js
Normal file
33
src/components/Page/Page.js
Normal file
@ -0,0 +1,33 @@
|
||||
import React, { Component } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import classnames from 'classnames'
|
||||
import Loader from '../Loader/Loader.js'
|
||||
import styles from './Page.less'
|
||||
|
||||
export default class Page extends Component {
|
||||
render() {
|
||||
const { className, children, loading = false, inner = false } = this.props
|
||||
const loadingStyle = {
|
||||
height: 'calc(100vh - 184px)',
|
||||
overflow: 'hidden',
|
||||
}
|
||||
return (
|
||||
<div
|
||||
className={classnames(className, {
|
||||
[styles.contentInner]: inner,
|
||||
})}
|
||||
style={loading ? loadingStyle : null}
|
||||
>
|
||||
{loading ? <Loader spinning /> : ''}
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Page.propTypes = {
|
||||
className: PropTypes.string,
|
||||
children: PropTypes.node,
|
||||
loading: PropTypes.bool,
|
||||
inner: PropTypes.bool,
|
||||
}
|
16
src/components/Page/Page.less
Normal file
16
src/components/Page/Page.less
Normal file
@ -0,0 +1,16 @@
|
||||
@import '~themes/vars.less';
|
||||
|
||||
.contentInner {
|
||||
background: #fff;
|
||||
padding: 24px;
|
||||
box-shadow: @shadow-1;
|
||||
min-height: ~'calc(100vh - 230px)';
|
||||
position: relative;
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.contentInner {
|
||||
padding: 12px;
|
||||
min-height: ~'calc(100vh - 160px)';
|
||||
}
|
||||
}
|
6
src/components/Page/package.json
Normal file
6
src/components/Page/package.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"name": "Page",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"main": "./Page.js"
|
||||
}
|
5
src/components/ScrollBar/index.js
Normal file
5
src/components/ScrollBar/index.js
Normal file
@ -0,0 +1,5 @@
|
||||
import ScrollBar from 'react-perfect-scrollbar'
|
||||
import 'react-perfect-scrollbar/dist/css/styles.css'
|
||||
import './index.less'
|
||||
|
||||
export default ScrollBar
|
31
src/components/ScrollBar/index.less
Normal file
31
src/components/ScrollBar/index.less
Normal file
@ -0,0 +1,31 @@
|
||||
:global {
|
||||
.ps--active-x > .ps__rail-x,
|
||||
.ps--active-y > .ps__rail-y {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.ps__rail-x:hover > .ps__thumb-x,
|
||||
.ps__rail-x:focus > .ps__thumb-x {
|
||||
height: 8px;
|
||||
}
|
||||
|
||||
.ps__rail-y:hover > .ps__thumb-y,
|
||||
.ps__rail-y:focus > .ps__thumb-y {
|
||||
width: 8px;
|
||||
}
|
||||
|
||||
.ps__rail-y,
|
||||
.ps__rail-x {
|
||||
z-index: 9;
|
||||
}
|
||||
|
||||
.ps__thumb-y {
|
||||
width: 4px;
|
||||
right: 4px;
|
||||
}
|
||||
|
||||
.ps__thumb-x {
|
||||
height: 4px;
|
||||
bottom: 4px;
|
||||
}
|
||||
}
|
@ -0,0 +1 @@
|
||||
{"version":3,"file":"StatusBoxC.js","sourceRoot":"","sources":["StatusBoxC.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,+BAAyC;AACzC,6BAA4B;AAC5B,wCAAiC;AAEjC,yCAAmC;AAEnC;IAAwB,6BAAS;IAE7B,mBAAY,KAAK;QAAjB,YACI,kBAAM,KAAK,CAAC,SAIf;QAHG,KAAI,CAAC,KAAK,GAAG;YACT,QAAQ,EAAE,SAAS;SACtB,CAAA;;IACL,CAAC;IACD,qCAAiB,GAAjB;QACY,IAAA,gCAAS,CAAgB;QACjC,IAAI,CAAC,QAAQ,CAAC,EAAC,QAAQ,EAAE,SAAS,EAAE,CAAC,CAAC;IAC1C,CAAC;IACD,0BAAM,GAAN;QACY,IAAA,8BAAQ,CAAgB;QAEhC,IAAI,QAAQ,IAAI,SAAS,EAAE;YACvB,OAAO,CACL,0CAAK,SAAS,EAAE,qBAAM,CAAC,gBAAgB,EAAE,EAAE,EAAC,YAAY;gBACtD;oBAAK,iCAAC,WAAI,IAAC,IAAI,EAAC,SAAS,EAAC,KAAK,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,IAAI,SAAG,CAAM;gBAChF;oBACE,4CAAM;oBAAA,4CAAM;oBAAA,4CAAM;oBAClB,0CAAK,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE;wBAAE,yCAAI,SAAS,EAAE,qBAAM,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,oBAAoB,CAAM,CAClI,CACF,CACP,CAAA;SACJ;QACD,IAAI,QAAQ,IAAI,KAAK,EAAE;YACnB,OAAO,CACL,0CAAK,SAAS,EAAE,qBAAM,CAAC,gBAAgB,EAAE,EAAE,EAAC,YAAY;gBACtD;oBACE,4CAAM;oBAAA,4CAAM;oBAAA,4CAAM;oBAClB,0CAAK,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE;wBAAE,yCAAI,SAAS,EAAE,qBAAM,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,CAAM,CACvH,CACF,CACP,CAAA;SACD;QACJ,IAAI,QAAQ,IAAI,KAAK,EAAE;YACrB,OAAO,CACL,0CAAK,SAAS,EAAE,qBAAM,CAAC,gBAAgB,EAAE,EAAE,EAAC,YAAY;gBACtD;oBACE,4CAAM;oBAAA,4CAAM;oBAAA,4CAAM;oBAClB,0CAAK,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE;wBAAE,yCAAI,SAAS,EAAE,qBAAM,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,CAAM,CACvH,CACF,CACP,CAAA;SACD;QAEF,OAAO,IAAI,CAAA;IACf,CAAC;IACL,gBAAC;AAAD,CAAC,AAjDD,CAAwB,iBAAS,GAiDhC;AAED,SAAS,CAAC,SAAS,GAAG;IAClB,YAAY,EAAE,uBAAS,CAAC,IAAI;IAC5B,OAAO,EAAE,uBAAS,CAAC,IAAI;IACvB,SAAS,EAAE,uBAAS,CAAC,MAAM;CAC9B,CAAA;AAED,qBAAe,SAAS,CAAC"}
|
@ -0,0 +1,64 @@
|
||||
import React, { Component } from 'react';
|
||||
import { Icon } from 'antd';
|
||||
import styles from '../yid.scss';
|
||||
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
class StatusBox extends Component {
|
||||
|
||||
constructor(props){
|
||||
super(props)
|
||||
this.state = {
|
||||
Reactive: 'loading',
|
||||
}
|
||||
}
|
||||
componentDidMount(){
|
||||
const { StateCode } = this.props;
|
||||
this.setState({Reactive: StateCode });
|
||||
}
|
||||
render(){
|
||||
const { Reactive } = this.state;
|
||||
|
||||
if (Reactive == 'loading') {
|
||||
return (
|
||||
<div className={styles.spinner__wrapper} id="loadingspn" >
|
||||
<div><Icon type="loading" style={{ fontSize: 24, margin: '13px' }} spin /></div>
|
||||
<div>
|
||||
<br /><br /><br />
|
||||
<div style={{ margin: 'auto' }}><h6 className={styles.h6lp} style={{ textAlign: 'center', marginTop: '15%' }}>Wait a sec...</h6></div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
if (Reactive == '200') {
|
||||
return (
|
||||
<div className={styles.spinner__wrapper} id="loadingspn" >
|
||||
<div>
|
||||
<br /><br /><br />
|
||||
<div style={{ margin: 'auto' }}><h6 className={styles.h6lp} style={{ textAlign: 'center', marginTop: '15%' }}>SI</h6></div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
if (Reactive == '400') {
|
||||
return (
|
||||
<div className={styles.spinner__wrapper} id="loadingspn" >
|
||||
<div>
|
||||
<br /><br /><br />
|
||||
<div style={{ margin: 'auto' }}><h6 className={styles.h6lp} style={{ textAlign: 'center', marginTop: '15%' }}>NO</h6></div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
StatusBox.propTypes = {
|
||||
handleStatus: PropTypes.func,
|
||||
Loading: PropTypes.bool,
|
||||
StateCode: PropTypes.string
|
||||
}
|
||||
|
||||
export default StatusBox;
|
@ -0,0 +1,74 @@
|
||||
var __extends = (this && this.__extends) || (function () {
|
||||
var extendStatics = function (d, b) {
|
||||
extendStatics = Object.setPrototypeOf ||
|
||||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
||||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
|
||||
return extendStatics(d, b);
|
||||
};
|
||||
return function (d, b) {
|
||||
extendStatics(d, b);
|
||||
function __() { this.constructor = d; }
|
||||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||||
};
|
||||
})();
|
||||
import * as PropTypes from 'prop-types';
|
||||
var react = require("react");
|
||||
var antd = require("antd");
|
||||
var yid_scss = require("../yid.scss");
|
||||
|
||||
|
||||
var StatusBox = /** @class */ (function (_super) {
|
||||
__extends(StatusBox, _super);
|
||||
function StatusBox(props) {
|
||||
var _this = _super.call(this, props) || this;
|
||||
_this.state = {
|
||||
Reactive: 'loading'
|
||||
};
|
||||
return _this;
|
||||
}
|
||||
StatusBox.prototype.componentDidMount = function () {
|
||||
var StateCode = this.props.StateCode;
|
||||
this.setState({ Reactive: StateCode });
|
||||
};
|
||||
StatusBox.prototype.render = function () {
|
||||
var Reactive = this.state.Reactive;
|
||||
if (Reactive == 'loading') {
|
||||
return (react.createElement("div", { className: yid_scss.spinner__wrapper, id: "loadingspn" },
|
||||
react.createElement("div", null,
|
||||
react.createElement(antd.Icon, { type: "loading", style: { fontSize: 24, margin: '13px' }, spin: true })),
|
||||
react.createElement("div", null,
|
||||
react.createElement("br", null),
|
||||
react.createElement("br", null),
|
||||
react.createElement("br", null),
|
||||
react.createElement("div", { style: { margin: 'auto' } },
|
||||
react.createElement("h6", { className: yid_scss.h6lp, style: { textAlign: 'center', marginTop: '15%' } }, "Wait a sec...")))));
|
||||
}
|
||||
if (Reactive == '200') {
|
||||
return (react.createElement("div", { className: yid_scss.spinner__wrapper, id: "loadingspn" },
|
||||
react.createElement("div", null,
|
||||
react.createElement("br", null),
|
||||
react.createElement("br", null),
|
||||
react.createElement("br", null),
|
||||
react.createElement("div", { style: { margin: 'auto' } },
|
||||
react.createElement("h6", { className: yid_scss.h6lp, style: { textAlign: 'center', marginTop: '15%' } }, "SI")))));
|
||||
}
|
||||
if (Reactive == '400') {
|
||||
return (react.createElement("div", { className: yid_scss.spinner__wrapper, id: "loadingspn" },
|
||||
react.createElement("div", null,
|
||||
react.createElement("br", null),
|
||||
react.createElement("br", null),
|
||||
react.createElement("br", null),
|
||||
react.createElement("div", { style: { margin: 'auto' } },
|
||||
react.createElement("h6", { className: yid_scss.h6lp, style: { textAlign: 'center', marginTop: '15%' } }, "NO")))));
|
||||
}
|
||||
return null;
|
||||
};
|
||||
return StatusBox;
|
||||
}(react.Component));
|
||||
StatusBox.PropTypes = {
|
||||
handleStatus: PropTypes.func,
|
||||
Loading: PropTypes.bool,
|
||||
StateCode: PropTypes.string
|
||||
};
|
||||
exports["default"] = StatusBox;
|
||||
//# sourceMappingURL=StatusBoxC.js.map
|
86
src/components/YulioID/experimental/formstyle.less
Normal file
86
src/components/YulioID/experimental/formstyle.less
Normal file
@ -0,0 +1,86 @@
|
||||
.inputform {
|
||||
:global{
|
||||
input {
|
||||
height: 50px;
|
||||
font-size: 16px;
|
||||
border: 2px solid #d1d3d4;
|
||||
width: 100%;
|
||||
padding: 12px;
|
||||
font-family: "Poppins";
|
||||
border-radius: 6px;
|
||||
color: black
|
||||
}
|
||||
input:focus {
|
||||
outline: none;
|
||||
border-color: black;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.check {
|
||||
animation-delay: 0s;
|
||||
}
|
||||
.checkmark {
|
||||
opacity: 0;
|
||||
}
|
||||
.Oval {
|
||||
opacity: 1;
|
||||
transform-origin: 30px 30px;
|
||||
stroke-dasharray: 200px;
|
||||
transform: rotate(-75deg);
|
||||
animation: 3s spin infinite ;
|
||||
stroke-dashoffset: 200;
|
||||
/* animation-play-state: paused; */
|
||||
}
|
||||
|
||||
.animateCheck {
|
||||
animation: 0.5s check_animation linear forwards;
|
||||
}
|
||||
|
||||
.animateOvaloop {
|
||||
animation: 3s spin infinite ;
|
||||
}
|
||||
|
||||
@keyframes spin{
|
||||
0%{
|
||||
opacity: 1;
|
||||
stroke-dasharray: 360;
|
||||
stroke-dashoffset: 360;
|
||||
transform: rotate(-720deg);
|
||||
|
||||
}
|
||||
50% {
|
||||
opacity: 1;
|
||||
stroke-dasharray: 360;
|
||||
stroke-dashoffset: 260;
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
100%{
|
||||
opacity: 1;
|
||||
stroke-dasharray: 360;
|
||||
stroke-dashoffset: 360;
|
||||
transform: rotate(720deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes circle_animation {
|
||||
60% {
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
stroke-dasharray: 400px;
|
||||
transform: rotate(40deg);
|
||||
}
|
||||
}
|
||||
@keyframes check_animation {
|
||||
0% {
|
||||
stroke-dasharray: 126;
|
||||
stroke-dashoffset: 126;
|
||||
|
||||
}
|
||||
100% {
|
||||
stroke-dasharray: 45;
|
||||
stroke-dashoffset: 94
|
||||
}
|
||||
}
|
216
src/components/YulioID/experimental/index.js
Normal file
216
src/components/YulioID/experimental/index.js
Normal file
@ -0,0 +1,216 @@
|
||||
import React, { Component } from 'react'
|
||||
import {GetAuth, InitSDCP, DevOptions, asyncSDCP} from 'ycore';
|
||||
import PropTypes from 'prop-types';
|
||||
import { connect } from 'dva';
|
||||
import { Button, Form, Input, Drawer, Icon, Collapse } from 'antd'
|
||||
import styles from './yid.scss';
|
||||
import formstyle from './formstyle.less'
|
||||
|
||||
const FormItem = Form.Item
|
||||
const RenderInclude = ({ data }) => { if (!data) { return null; } else { return data; } }
|
||||
|
||||
@connect(({ loading }) => ({ loading }))
|
||||
@Form.create()
|
||||
class YulioID extends Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props)
|
||||
this.state = {
|
||||
// Drawers Visibility (Default on False)
|
||||
MainLoginVisible: true,
|
||||
ShowLoading: false,
|
||||
Answered: false,
|
||||
}
|
||||
this.handleRetry = this.handleRetry.bind(this);
|
||||
}
|
||||
// Handlers & others
|
||||
handleUsername(text) {
|
||||
this.setState({ RawUsername: text.target.value });
|
||||
}
|
||||
handlePassword(text) {
|
||||
this.setState({ RawPassword: text.target.value });
|
||||
}
|
||||
handleRetry() {
|
||||
this.setState({ShowLoading: false, StateException: false, StateIcon: ''})
|
||||
}
|
||||
handleEnter = (e) => {
|
||||
this.handleLogin();
|
||||
}
|
||||
|
||||
handleLogin = () => {
|
||||
var prefix = '[YID]: ';
|
||||
const { RawUsername, RawPassword } = this.state;
|
||||
var EncPassword = btoa(RawPassword);
|
||||
var EncUsername = btoa(RawUsername);
|
||||
|
||||
const OriginalPayload = {EncUsername, EncPassword}
|
||||
|
||||
if (!EncUsername || !EncPassword) {
|
||||
var message = 'Incomplete information!'
|
||||
console.log(prefix, message)
|
||||
}
|
||||
|
||||
if (EncUsername && EncPassword){
|
||||
this.setState({ ShowLoading: true, StateMessage: 'Wait a sec...' });
|
||||
if (DevOptions.InfiniteLogin == true) {
|
||||
console.log(prefix, 'InfiniteLogin is enabled! Disabled getAuth')
|
||||
}
|
||||
else {
|
||||
console.log(prefix, 'Initialising login process...')
|
||||
GetAuth(EncUsername, EncPassword, (exception, response) => exception? this.handleResponse(response) : ( this.setState({ AuthResponse: response }), this.handleResponse(response, OriginalPayload) ))
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
handleResponse = (response) => {
|
||||
var identState = JSON.parse(response)['api_status'];
|
||||
if (identState == 200) {
|
||||
const { dispatch } = this.props;
|
||||
const UserID = JSON.parse(response)['user_id'];
|
||||
const UserToken = JSON.parse(response)['access_token'];
|
||||
let FramePayload = { UserID, UserToken }
|
||||
DevOptions.ShowFunctionsLogs ? console.log(FramePayload) : null
|
||||
this.setState({ StateIcon: 'login', StateMessage: 'Wait a sec...', StateException: false })
|
||||
InitSDCP({UserID, UserToken}, (done) => done? dispatch({type: 'login/login', payload: FramePayload}) : null )
|
||||
}
|
||||
if (identState == 400) {
|
||||
this.setState({ StateIcon: 'exclamation-circle', StateMessage: 'Invalid credentials', StateException: true })
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
const { getFieldDecorator } = this.props.form;
|
||||
const { ShowLoading, StateIcon, StateMessage, StateException } = this.state;
|
||||
const { Panel } = Collapse;
|
||||
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Drawer
|
||||
width={520}
|
||||
closable={false}
|
||||
visible={this.state.MainLoginVisible}
|
||||
>
|
||||
<main className={styles.mainlp}>
|
||||
<section className={styles.forms}>
|
||||
<h6 className={styles.h6lp}>YulioID™</h6>
|
||||
<h1 className={styles.h1lp}>Welcome Back !</h1>
|
||||
|
||||
{/* <RenderInclude data={include} /> */}
|
||||
|
||||
<form className={styles.formlogin}>
|
||||
{ShowLoading ? (
|
||||
<div style={{ height: '329px' }}>
|
||||
<div className={styles.spinner__wrapper} id="loadingspn">
|
||||
{StateIcon ? (<Icon type={StateIcon} className={StateException? styles.StateIcon_exception : styles.StateIcon} /> ) : (<Icon type="loading" style={{ fontSize: 24, margin: '13px' }} spin />)}
|
||||
<div><br/><br/><br/>
|
||||
<div style={{ margin: 'auto' }}>
|
||||
<h6 className={styles.h6lp} style={{ textAlign: 'center', marginTop: '15%' }} > {StateMessage} </h6>
|
||||
{StateException ? <div className={styles.retryBTN}><Button style={{ width: '270px' }} type='dashed' onClick={this.handleRetry}>Retry</Button></div> : null}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div>
|
||||
<div className={styles.input__wrapper}>
|
||||
<label className={styles.labelform}>
|
||||
<Icon type="user" style={{ fontSize: '15px' }} />{' '}
|
||||
Username
|
||||
</label>
|
||||
<FormItem>
|
||||
{getFieldDecorator('Username', {
|
||||
rules: [{ required: true }],
|
||||
})(
|
||||
<Input
|
||||
onPressEnter={this.handleEnter}
|
||||
className={styles.inputform}
|
||||
type="text"
|
||||
placeholder="Username"
|
||||
onChange={text => {
|
||||
this.handleUsername(text)
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</FormItem>
|
||||
</div>
|
||||
|
||||
<div className={styles.input__wrapper}>
|
||||
<label className={styles.labelform}>
|
||||
<Icon type="unlock" style={{ fontSize: '15px' }} />{' '}
|
||||
Password
|
||||
</label>
|
||||
<FormItem>
|
||||
{getFieldDecorator('Password', {
|
||||
rules: [{ required: true }],
|
||||
})(
|
||||
<Input.Password
|
||||
onPressEnter={this.handleEnter}
|
||||
className={formstyle.inputform}
|
||||
placeholder="Password"
|
||||
onChange={text => {
|
||||
this.handlePassword(text)
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</FormItem>
|
||||
</div>
|
||||
|
||||
<div style={{ margin: 'auto' }}>
|
||||
<a
|
||||
className={styles.buttonlp}
|
||||
id="login"
|
||||
onClick={this.handleLogin}
|
||||
>
|
||||
Login
|
||||
</a>
|
||||
</div>
|
||||
<h2
|
||||
style={{
|
||||
textAlign: 'center',
|
||||
margin: '8px',
|
||||
color: '#666',
|
||||
}}
|
||||
>
|
||||
Or
|
||||
</h2>
|
||||
<div style={{ float: 'left' }}>
|
||||
<Button
|
||||
type="dashed"
|
||||
onClick={this.initFPassword}
|
||||
style={{ top: '8px' }}
|
||||
>
|
||||
<Icon type="exclamation-circle" /> Forgotten password
|
||||
</Button>
|
||||
</div>
|
||||
<div style={{ float: 'right' }}>
|
||||
<Button
|
||||
type="dashed"
|
||||
onClick={this.initRegister}
|
||||
style={{ top: '8px' }}
|
||||
>
|
||||
<Icon type="user-add" /> Create an account
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</form>
|
||||
</section>
|
||||
</main>
|
||||
</Drawer>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
YulioID.propTypes = {
|
||||
form: PropTypes.object,
|
||||
dispatch: PropTypes.func,
|
||||
loading: PropTypes.object,
|
||||
include: PropTypes.object,
|
||||
}
|
||||
|
||||
export default YulioID
|
29
src/components/YulioID/experimental/model.js
Normal file
29
src/components/YulioID/experimental/model.js
Normal file
@ -0,0 +1,29 @@
|
||||
import { router, pathMatchRegexp } from 'utils'
|
||||
import api from 'api'
|
||||
|
||||
const { loginUser } = api
|
||||
|
||||
export default {
|
||||
namespace: 'login',
|
||||
|
||||
state: {},
|
||||
|
||||
effects: {
|
||||
*login({ payload }, { put, call, select }) {
|
||||
const data = yield call(loginUser, payload)
|
||||
const { locationQuery } = yield select(_ => _.app)
|
||||
if (data.success) {
|
||||
const { from } = locationQuery
|
||||
yield put({ type: 'app/query' })
|
||||
if (!pathMatchRegexp('/login', from)) {
|
||||
if (from === '/') router.push('/dashboard')
|
||||
else router.push(from)
|
||||
} else {
|
||||
router.push('/dashboard')
|
||||
}
|
||||
} else {
|
||||
throw data
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
769
src/components/YulioID/experimental/yid.scss
Normal file
769
src/components/YulioID/experimental/yid.scss
Normal file
@ -0,0 +1,769 @@
|
||||
@import url('https://cdnjs.cloudflare.com/ajax/libs/simple-line-icons/2.4.1/css/simple-line-icons.min.css');
|
||||
@import url('https://fonts.googleapis.com/css?family=Poppins:300,300i,500,500i,700');
|
||||
|
||||
.retryBTN{
|
||||
margin-top: 150px;
|
||||
text-align: center;
|
||||
}
|
||||
.StateIcon {
|
||||
font-size: 24px;
|
||||
margin: 13px;
|
||||
}
|
||||
|
||||
.StateIcon_exception {
|
||||
color: red;
|
||||
font-size: 24px;
|
||||
margin: 13px;
|
||||
}
|
||||
|
||||
.mainlp {
|
||||
--neutralShade0: #f8f8f8;
|
||||
--neutralShade1: #f2f2f2;
|
||||
--neutralShade2: #e8e9e9;
|
||||
--neutralShade3: #d1d3d4;
|
||||
--neutralShade4: #babdbf;
|
||||
--neutralShade5: #808488;
|
||||
--neutralShade6: #666a6d;
|
||||
--neutralShade7: #4d5052;
|
||||
--neutralShade8: #212122;
|
||||
--grayColor: #999;
|
||||
--lightGrayColor: #ddd;
|
||||
--borderRadius: 6px;
|
||||
--boxShadow: 0 2px 5px rgba(#333, 0.2);
|
||||
}
|
||||
|
||||
/*overall layout*/
|
||||
.mainlp {
|
||||
width: 90%;
|
||||
max-width: 1050px;
|
||||
margin: 3em auto 0;
|
||||
display: grid;
|
||||
grid: repeat(5, fit-content(300px))/100%;
|
||||
color: var(--foregroundColor);
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.mainlp .sectionlp {
|
||||
border: 1px solid var(--accentColor);
|
||||
position: relative;
|
||||
padding: 40px 40px 50px;
|
||||
}
|
||||
.mainlp .sectionlp > h6 {
|
||||
color: var(--accentColor);
|
||||
background: var(--canvasColor);
|
||||
position: absolute;
|
||||
top: -10px;
|
||||
left: 20px;
|
||||
padding: 0 10px;
|
||||
}
|
||||
.mainlp .sectionlp .h6lp.subheader {
|
||||
color: var(--grayColor);
|
||||
margin-top: 20px;
|
||||
margin-bottom: 20px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@media (max-width: 992px) {
|
||||
section:not(:last-child) {
|
||||
border-width: 0 0 1px;
|
||||
}
|
||||
|
||||
section:last-child {
|
||||
border-width: 0;
|
||||
}
|
||||
}
|
||||
@media (min-width: 992px) {
|
||||
main {
|
||||
grid: repeat(9, auto)/45% 1fr 45%;
|
||||
grid-auto-flow: dense;
|
||||
}
|
||||
|
||||
.media-card-1 {
|
||||
grid-column: 1 / 2;
|
||||
border-width: 1px 0;
|
||||
}
|
||||
|
||||
.media-card-2 {
|
||||
grid-column: 2 / 4;
|
||||
border-width: 1px 0 1px 1px;
|
||||
}
|
||||
|
||||
.media-card-3 {
|
||||
grid-column: 1 / 4;
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
.filter-section {
|
||||
grid-column: 3 / 4;
|
||||
grid-row: 1 / 2;
|
||||
border-width: 0 0 0 1px;
|
||||
}
|
||||
|
||||
.well-cta-1 {
|
||||
grid-row: 3;
|
||||
grid-column: 1 / 3;
|
||||
border-width: 1px 1px 0 0;
|
||||
}
|
||||
|
||||
.well-cta-2 {
|
||||
grid-row: 2;
|
||||
grid-column: 2 / 4;
|
||||
border-width: 1px 0 0;
|
||||
}
|
||||
|
||||
.tables {
|
||||
grid-row: 4;
|
||||
grid-column: 1 / -1;
|
||||
border-width: 1px 0 0;
|
||||
}
|
||||
|
||||
.forms {
|
||||
grid-column: 1 / 3;
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
.comments {
|
||||
grid-row: 2;
|
||||
grid-column: 1 / 2;
|
||||
border-width: 1px 1px 0 0;
|
||||
padding-top: 60px;
|
||||
}
|
||||
|
||||
.modals {
|
||||
grid-row: 3;
|
||||
grid-column: 3 / 4;
|
||||
justify-content: center;
|
||||
border-width: 1px 0 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*checkboxes*/
|
||||
input:disabled ~ * {
|
||||
opacity: 0.3;
|
||||
user-select: none;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.checkboxtoggle input {
|
||||
display: none;
|
||||
}
|
||||
.checkboxtoggle label {
|
||||
outline: 0;
|
||||
display: block;
|
||||
width: 45px;
|
||||
height: 16px;
|
||||
background: var(--grayColor);
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
border-radius: 2em;
|
||||
padding: 2px;
|
||||
transition: all 0.4s ease;
|
||||
margin: 0;
|
||||
}
|
||||
.checkboxtoggle .labellp:after {
|
||||
position: relative;
|
||||
display: block;
|
||||
content: "";
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border-radius: 50%;
|
||||
background: #fff;
|
||||
transition: all 0.2s ease;
|
||||
border: 1px solid var(--grayColor);
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
|
||||
left: -4px;
|
||||
top: -5px;
|
||||
}
|
||||
.checkboxtoggle input:checked + .labellp {
|
||||
background: var(--accent2Color);
|
||||
}
|
||||
.checkboxtoggle input:checked + .labellp:after {
|
||||
left: 52%;
|
||||
}
|
||||
|
||||
.checkbox {
|
||||
position: relative;
|
||||
user-select: none;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.checkbox input {
|
||||
display: none;
|
||||
}
|
||||
.checkbox .labellp {
|
||||
position: relative;
|
||||
vertical-align: middle;
|
||||
cursor: pointer;
|
||||
font-weight: 500;
|
||||
padding-left: 35px;
|
||||
}
|
||||
.checkbox .box {
|
||||
display: inline-block;
|
||||
width: 20px;
|
||||
border-radius: var(--borderRadius);
|
||||
border: 1px solid var(--grayColor);
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
vertical-align: middle;
|
||||
margin-right: 3px;
|
||||
transition: 0.3s ease;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
}
|
||||
.checkbox .box:before, .checkbox .box:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
width: 4px;
|
||||
height: 16px;
|
||||
border-radius: 40px;
|
||||
background: var(--backgroundColor);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
.checkbox .spanlp.box:before {
|
||||
transform: rotate(45deg) translateY(-5px) translateX(10px) scale(0);
|
||||
}
|
||||
.checkbox .spanlp.box:after {
|
||||
height: 8px;
|
||||
transform: rotate(-45deg) translateY(10px) translateX(-4px) scale(0);
|
||||
}
|
||||
.checkbox input:checked + .labellp .spanlp.box {
|
||||
background: var(--accent2Color);
|
||||
border-color: var(--accent2Color);
|
||||
}
|
||||
.checkbox input:checked + .labellp .spanlp.box:before {
|
||||
transform: rotate(45deg) translateY(-5px) translateX(10px) scale(1);
|
||||
}
|
||||
.checkbox input:checked + .labellp .spanlp.box:after {
|
||||
height: 8px;
|
||||
transform: rotate(-45deg) translateY(10px) translateX(-4px) scale(1);
|
||||
}
|
||||
.checkbox input:disabled:checked + .spanlp.box {
|
||||
background: var(--grayColor);
|
||||
border: var(--grayColor);
|
||||
}
|
||||
.checkbox input:disabled:checked ~ .labellp:before, .checkbox input:disabled:checked ~ .labellp:after {
|
||||
background: black;
|
||||
}
|
||||
|
||||
/*buttons & links*/
|
||||
.links__sec {
|
||||
margin: 10px 0 30px;
|
||||
}
|
||||
.links a.link {
|
||||
display: inline;
|
||||
margin: 10px 30px 5px 0;
|
||||
border-bottom: 2px dashed;
|
||||
font-weight: 500;
|
||||
line-height: 2.5;
|
||||
cursor: pointer;
|
||||
color: var(--neutralShade5);
|
||||
}
|
||||
.links a.link:hover, .links a.link.hover {
|
||||
color: var(--neutralShade6);
|
||||
border-bottom: 2px solid;
|
||||
}
|
||||
.links a.link.primary {
|
||||
color: var(--primaryColor);
|
||||
}
|
||||
.links a.link.primary:hover, .links a.link.primary.hover {
|
||||
color: var(--primaryShade5);
|
||||
}
|
||||
.links a.link.secondary {
|
||||
color: var(--secondaryColor);
|
||||
}
|
||||
.links a.link.secondary:hover, .links a.link.secondary.hover {
|
||||
color: var(--secondaryShade5);
|
||||
}
|
||||
|
||||
.buttons {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
}
|
||||
.buttons > * {
|
||||
flex: 1 1 calc(50% - 20px);
|
||||
margin-top: 20px;
|
||||
}
|
||||
.buttons > *:nth-child(odd) {
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
a.buttonlp,
|
||||
input.buttonlp,
|
||||
.buttonlp {
|
||||
outline: none;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
display: inline-block;
|
||||
border: none;
|
||||
font: 500 16px/1 "Poppins", sans-serif;
|
||||
padding: 20px;
|
||||
cursor: pointer;
|
||||
border-radius: var(--borderRadius);
|
||||
background: var(--primaryColor);
|
||||
color: var(--backgroundColor);
|
||||
position: relative;
|
||||
top: 0;
|
||||
transition: 0.2s ease;
|
||||
}
|
||||
a.buttonlp:hover, a.buttonlp.hover,
|
||||
input.buttonlp:hover,
|
||||
input.buttonlp.hover,
|
||||
.buttonlp:hover,
|
||||
.buttonlp.hover {
|
||||
top: -3px;
|
||||
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
a.buttonlp:active, a.buttonlp.active,
|
||||
input.buttonlp:active,
|
||||
.input.buttonlp.active,
|
||||
.buttonlp:active,
|
||||
.buttonlp.active {
|
||||
background: var(--primaryShade4);
|
||||
outline: none;
|
||||
box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
|
||||
top: 0;
|
||||
}
|
||||
a.buttonlp.disabled,
|
||||
input.buttonlp.disabled,
|
||||
.buttonlp.disabled {
|
||||
opacity: 0.4;
|
||||
user-select: none;
|
||||
pointer-events: none;
|
||||
}
|
||||
a.buttonlp.medium,
|
||||
input.buttonlp.medium,
|
||||
.buttonlp.medium {
|
||||
padding: 15px 18px;
|
||||
width: auto;
|
||||
}
|
||||
a.buttonlp.small,
|
||||
input.buttonlp.small,
|
||||
.buttonlp.small {
|
||||
padding: 10px 12px;
|
||||
width: auto;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
}
|
||||
a.buttonlp.secondary,
|
||||
input.buttonlp.secondary,
|
||||
.buttonlp.secondary {
|
||||
background: var(--secondaryColor);
|
||||
}
|
||||
a.buttonlp.secondary:active, a.buttonlp.secondary:focus, a.buttonlp.secondary.active,
|
||||
input.buttonlp.secondary:active,
|
||||
input.buttonlp.secondary:focus,
|
||||
input.buttonlp.secondary.active,
|
||||
.buttonlp.secondary:active,
|
||||
.buttonlp.secondary:focus,
|
||||
.buttonlp.secondary.active {
|
||||
background: var(--secondaryShade4);
|
||||
outline: none;
|
||||
}
|
||||
a.buttonlp.accent,
|
||||
input.buttonlp.accent,
|
||||
.buttonlp.accent {
|
||||
background: var(--accentColor);
|
||||
}
|
||||
a.buttonlp.accent:active, a.buttonlp.accent:focus, a.buttonlp.accent.active,
|
||||
input.buttonlp.accent:active,
|
||||
input.buttonlp.accent:focus,
|
||||
input.buttonlp.accent.active,
|
||||
.buttonlp.accent:active,
|
||||
.buttonlp.accent:focus,
|
||||
.buttonlp.accent.active {
|
||||
background: var(--accentShade4);
|
||||
}
|
||||
a.buttonlp.accent2,
|
||||
input.buttonlp.accent2,
|
||||
.buttonlp.accent2 {
|
||||
background: var(--accent2Color);
|
||||
}
|
||||
a.buttonlp.accent2:active, a.buttonlp.accent2:focus, a.buttonlp.accent2.active,
|
||||
input.buttonlp.accent2:active,
|
||||
input.buttonlp.accent2:focus,
|
||||
input.buttonlp.accent2.active,
|
||||
.buttonlp.accent2:active,
|
||||
.buttonlp.accent2:focus,
|
||||
.buttonlp.accent2.active {
|
||||
background: var(--accent2Shade4);
|
||||
}
|
||||
a.buttonlp.accent3,
|
||||
input.buttonlp.accent3,
|
||||
.buttonlp.accent3 {
|
||||
background: var(--accent3Color);
|
||||
}
|
||||
a.buttonlp.accent3:active, a.buttonlp.accent3:focus, a.buttonlp.accent3.active,
|
||||
input.buttonlp.accent3:active,
|
||||
input.buttonlp.accent3:focus,
|
||||
input.buttonlp.accent3.active,
|
||||
.buttonlp.accent3:active,
|
||||
.buttonlp.accent3:focus,
|
||||
.buttonlp.accent3.active {
|
||||
background: var(--accent3Shade4);
|
||||
}
|
||||
|
||||
/*inputs*/
|
||||
.input__wrapper {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.inputRG__wrapper {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
.labelform {
|
||||
font-weight: 500;
|
||||
display: block;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.inputform,
|
||||
select,
|
||||
textarea {
|
||||
height: 50px;
|
||||
font-size: 16px;
|
||||
border: 2px solid var(--neutralShade3);
|
||||
width: 100%;
|
||||
padding: 12px;
|
||||
font-family: "Poppins";
|
||||
border-radius: var(--borderRadius);
|
||||
color: var(--foregroundColor);
|
||||
background: var(--backgroundColor);
|
||||
}
|
||||
.inputform:focus, .inputform.active,
|
||||
select:focus,
|
||||
select.active,
|
||||
textarea:focus,
|
||||
textarea.active {
|
||||
outline: none;
|
||||
border-color: var(--primaryColor);
|
||||
}
|
||||
.inputform:disabled,
|
||||
select:disabled,
|
||||
textarea:disabled {
|
||||
cursor: not-allowed;
|
||||
background: var(--neutralShade1);
|
||||
opacity: 0.6;
|
||||
}
|
||||
Input .inputPasswordform {
|
||||
height: 50px;
|
||||
font-size: 16px;
|
||||
border: 2px solid var(--neutralShade3);
|
||||
width: 100%;
|
||||
padding: 12px;
|
||||
font-family: "Poppins";
|
||||
border-radius: var(--borderRadius);
|
||||
color: var(--foregroundColor);
|
||||
background: var(--backgroundColor);
|
||||
}
|
||||
|
||||
Input .inputPasswordform:focus {
|
||||
outline: none;
|
||||
border-color: var(--primaryColor);
|
||||
}
|
||||
|
||||
.inputform.input {
|
||||
height: 56px;
|
||||
font-size: 18px;
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.TOSAccept {
|
||||
margin: 7px;
|
||||
}
|
||||
.TOSAccept span::first-letter {
|
||||
color: blue;
|
||||
}
|
||||
|
||||
/*spinner*/
|
||||
.spinner + .labellp {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
margin-top: 8px;
|
||||
display: inline-block;
|
||||
text-transform: uppercase;
|
||||
color: var(--primaryShade4);
|
||||
}
|
||||
|
||||
.spinner1 .spinner {
|
||||
max-width: 50px;
|
||||
margin: auto;
|
||||
height: 20px;
|
||||
position: relative;
|
||||
}
|
||||
.spinner1 .spinner:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
left: -10%;
|
||||
background: var(--primaryColor);
|
||||
animation: spinnerLeftRight 1s infinite;
|
||||
}
|
||||
.spinner1 .spinner:before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
left: -10%;
|
||||
background: var(--primaryShade2);
|
||||
opacity: 1;
|
||||
animation: spinnerLeftRight 1s infinite 0.06s;
|
||||
}
|
||||
|
||||
@keyframes spinnerLeftRight {
|
||||
0% {
|
||||
left: 85%;
|
||||
}
|
||||
50% {
|
||||
left: -10%;
|
||||
}
|
||||
100% {
|
||||
left: 85%;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#sunset + .labellp {
|
||||
background: linear-gradient(to right, #ff9557 50%, #ffcc67 50%);
|
||||
}
|
||||
.mainlp {
|
||||
--canvasColor: #f9f9f9;
|
||||
--backgroundColor: #fff;
|
||||
--foregroundColor: #111;
|
||||
--primaryColor: #373F51;
|
||||
--primaryShade1: #ffe2d1;
|
||||
--primaryShade2: #ffceb2;
|
||||
--primaryShade3: #ffb184;
|
||||
--primaryShade4: #e88850;
|
||||
--primaryShade5: #d17a48;
|
||||
--secondaryColor: #ffcc67;
|
||||
--secondaryShade1: #fff1d5;
|
||||
--secondaryShade2: #ffde9e;
|
||||
--secondaryShade3: #ffd074;
|
||||
--secondaryShade4: #e8ba5e;
|
||||
--secondaryShade5: #ba954b;
|
||||
--accentColor: #4e5166;
|
||||
--accentShade1: #cecfd5;
|
||||
--accentShade2: #aeafb9;
|
||||
--accentShade3: #8e909d;
|
||||
--accentShade4: #6e7081;
|
||||
--accentShade5: #404354;
|
||||
--accent2Color: #588b8b;
|
||||
--accent2Shade1: #c2d4d4;
|
||||
--accent2Shade2: #a3bfbf;
|
||||
--accent2Shade3: #85aaaa;
|
||||
--accent2Shade4: #507f7f;
|
||||
--accent2Shade5: #497272;
|
||||
--accent3Color: #fe5f55;
|
||||
--accent3Shade1: #fec4c1;
|
||||
--accent3Shade2: #fea7a2;
|
||||
--accent3Shade3: #fe7c73;
|
||||
--accent3Shade4: #e7574e;
|
||||
--accent3Shade5: #b9463e;
|
||||
}
|
||||
|
||||
.formlogin {
|
||||
border-radius: 10px;
|
||||
padding: 30px;
|
||||
box-shadow: 0 3px 15px rgba(51, 51, 51, 0.2);
|
||||
background: var(--backgroundColor);
|
||||
margin-top: 30px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.formlogin .checkbox {
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
.formlogin .spinner__wrapper {
|
||||
place-items: center;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
left: 0;
|
||||
top: 0;
|
||||
background: rgba(255, 255, 255, 0.85);
|
||||
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.formlogin {
|
||||
grid: auto / 1fr 40%;
|
||||
}
|
||||
.formlogin .input__wrapper {
|
||||
grid-column: span 2;
|
||||
}
|
||||
.formlogin .inputRG__wrapper {
|
||||
grid-column: span 2;
|
||||
}
|
||||
.formlogin .checkbox {
|
||||
align-self: center;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
#dark:checked ~ .mainlp .spinner__wrapper,
|
||||
#pinkaru:checked ~ .mainlp .spinner__wrapper {
|
||||
background: rgba(20, 20, 20, 0.85);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*typography 2*/
|
||||
.stonglp {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.emlp {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.h1lp {
|
||||
font: 700 48px/1.2 "Poppins", sans-serif;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.h2lp {
|
||||
font: 700 32px/1.2 "Poppins", sans-serif;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.h3lp {
|
||||
font: 700 24px/1.2 "Poppins", sans-serif;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.h4lp {
|
||||
font: 700 20px/1.2 "Poppins", sans-serif;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.h5lp {
|
||||
font: 500 18px/1.2 "Poppins", sans-serif;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.h6lp {
|
||||
font: 500 16px/1.2 "Poppins", sans-serif;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.apierrort {
|
||||
font: 700 20px/1.2 "Poppins", sans-serif;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.apierrort::first-letter {
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.devServer{
|
||||
color: orangered;
|
||||
text-align: left;
|
||||
margin: 10px;
|
||||
float: left;
|
||||
position: fixed;
|
||||
z-index: 104;
|
||||
font-size: 16px;
|
||||
|
||||
}
|
||||
.devServer span{
|
||||
text-shadow: 2px 0 0 #fff, -2px 0 0 #fff, 0 2px 0 #fff, 0 -2px 0 #fff, 1px 1px #fff, -1px -1px 0 #fff, 1px -1px 0 #fff, -1px 1px 0 #fff;
|
||||
}
|
||||
|
||||
|
||||
.bgHero iframe {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
z-index: 103;
|
||||
}
|
||||
|
||||
$circle-length: 340px;
|
||||
$check-length: 230px;
|
||||
|
||||
@keyframes scaleAnimation {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: scale(1.5);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes drawCircle {
|
||||
0% {
|
||||
stroke-dashoffset: $circle-length;
|
||||
}
|
||||
100% {
|
||||
stroke-dashoffset: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes drawCheck {
|
||||
0% {
|
||||
stroke-dashoffset: $check-length;
|
||||
}
|
||||
100% {
|
||||
stroke-dashoffset: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeOut {
|
||||
0% {
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
#successAnimationCircle {
|
||||
stroke-dasharray: $circle-length $circle-length;
|
||||
stroke: #FFF;
|
||||
}
|
||||
|
||||
#successAnimationCheck {
|
||||
stroke-dasharray: $check-length $check-length;
|
||||
stroke: #FFF;
|
||||
}
|
||||
|
||||
#successAnimationResult {
|
||||
fill: #FFF;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
#successAnimation .animated {
|
||||
animation: 1s ease-out 0s 1 both scaleAnimation;
|
||||
|
||||
#successAnimationCircle {
|
||||
animation: 1s cubic-bezier(0.77, 0, 0.175, 1) 0s 1 both drawCircle,
|
||||
0.3s linear 0.9s 1 both fadeOut;
|
||||
}
|
||||
|
||||
#successAnimationCheck {
|
||||
animation: 1s cubic-bezier(0.77, 0, 0.175, 1) 0s 1 both drawCheck,
|
||||
0.3s linear 0.9s 1 both fadeOut;
|
||||
}
|
||||
|
||||
#successAnimationResult {
|
||||
animation: 0.3s linear 0.9s both fadeIn;
|
||||
}
|
||||
}
|
357
src/components/YulioID/legacy/forms.js
Normal file
357
src/components/YulioID/legacy/forms.js
Normal file
@ -0,0 +1,357 @@
|
||||
//****************************************|
|
||||
//**** Yulio ID v1.6 *****|
|
||||
//****************************************|
|
||||
//
|
||||
// @ Licensed by RageStudio(c) 2019
|
||||
// @ Build 03102019EU21700 F/WIAPIS
|
||||
// @ https://api.ragestudio.net/RS-YIBTP
|
||||
//
|
||||
//****************************************|
|
||||
|
||||
import React, { PureComponent } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { connect } from 'dva'
|
||||
import { Button, Row, Form, Input, Drawer, Icon, Collapse, Select, Checkbox, Result, Layout, message, notification } from 'antd'
|
||||
import { Trans, withI18n } from '@lingui/react'
|
||||
import { setLocale } from 'utils'
|
||||
import { UIFxPY, UIFxList, DevOptions } from 'ycore';
|
||||
import { endpoints } from 'ycore';
|
||||
import $ from 'jquery';
|
||||
import styles from './yid.scss';
|
||||
import {resetToken} from './ycore_sdcp.js'
|
||||
|
||||
import Cookies from 'universal-cookie';
|
||||
import Cryptr from 'cryptr';
|
||||
|
||||
const cookies = new Cookies();
|
||||
|
||||
const FormItem = Form.Item
|
||||
|
||||
@withI18n()
|
||||
@connect(({ loading }) => ({ loading }))
|
||||
@Form.create()
|
||||
class YulioIDForms extends PureComponent {
|
||||
constructor() {
|
||||
super()
|
||||
this.state = {
|
||||
// Drawers Visibility (Default on False)
|
||||
MainLoginVisible: false,
|
||||
NOTFdrawer: false,
|
||||
SOTFdrawer: false,
|
||||
RGSOTFdrawer: false,
|
||||
registerVisible: false,
|
||||
ForggotPasswordVisible: false,
|
||||
// Arrays
|
||||
ErrorType: '',
|
||||
FailArray: '',
|
||||
username: '',
|
||||
password: '',
|
||||
server_key: '',
|
||||
access_token: '',
|
||||
user_data: [],
|
||||
ExceptionID: '',
|
||||
EXCPMS: '',
|
||||
CompleteFORM: '',
|
||||
TSDCP: '',
|
||||
user_id: '',
|
||||
api_response: {},
|
||||
api_response_ud: [],
|
||||
RGUsername: '',
|
||||
RGEmail: '',
|
||||
RGPassword: '',
|
||||
RGGender: '',
|
||||
}
|
||||
this.initRegister = this.initRegister.bind(this);
|
||||
this.initFPassword = this.initFPassword.bind(this);
|
||||
this.cancelRegister = this.cancelRegister.bind(this);
|
||||
this.cancelRecoverPassword = this.cancelRecoverPassword.bind(this);
|
||||
this.closeNOTF = this.closeNOTF.bind(this);
|
||||
this.closeSOTF = this.closeSOTF.bind(this);
|
||||
this.closeRGSOTF = this.closeSOTF.bind(this);
|
||||
|
||||
}
|
||||
// Handlers & others
|
||||
handleUsername(text) {
|
||||
this.setState({ username: text.target.value })
|
||||
}
|
||||
handlePassword(text) {
|
||||
this.setState({ password: text.target.value })
|
||||
}
|
||||
handleRGUsername(text) {
|
||||
this.setState({ RGUsername: text.target.value })
|
||||
}
|
||||
handleRGPassword(text) {
|
||||
this.setState({ RGPassword: text.target.value })
|
||||
}
|
||||
handleRGEmail(text) {
|
||||
this.setState({ RGEmail: text.target.value })
|
||||
}
|
||||
handleRGGender(Ivalue) {
|
||||
this.setState({ RGGender: Ivalue })
|
||||
}
|
||||
handleFPEmail(Ivalue) {
|
||||
this.setState({ FGEmail: Ivalue })
|
||||
}
|
||||
|
||||
|
||||
triggerNOTF() {
|
||||
this.setState({ NOTFdrawer: true });
|
||||
}
|
||||
closeNOTF() {
|
||||
this.setState({ NOTFdrawer: false });
|
||||
}
|
||||
|
||||
triggerSOTF() {
|
||||
this.setState({ SOTFdrawer: true });
|
||||
}
|
||||
closeSOTF() {
|
||||
this.setState({ SOTFdrawer: false });
|
||||
}
|
||||
|
||||
triggerRGSOTF() {
|
||||
this.setState({ RGSOTFdrawer: true });
|
||||
}
|
||||
closeRGSOTF() {
|
||||
this.setState({ RGSOTFdrawer: false });
|
||||
}
|
||||
|
||||
cancelRegister() {
|
||||
this.setState({ registerVisible: false })
|
||||
}
|
||||
cancelRecoverPassword(){
|
||||
this.setState({ ForggotPasswordVisible: false })
|
||||
}
|
||||
|
||||
initRegister() {
|
||||
var messageListener = message.loading('Initialising YulioID ', 1.5)
|
||||
{ messageListener }
|
||||
if (DevOptions.DisableRegister == false) {
|
||||
this.setState({ registerVisible: true })
|
||||
}
|
||||
else {
|
||||
messageListener.then(() => message.error('Cannot connect to YulioID Services (Disabled Register)', 2.5))
|
||||
}
|
||||
}
|
||||
|
||||
initFPassword() {
|
||||
var messageListener = message.loading('Initialising YulioID ', 1.5)
|
||||
{ messageListener }
|
||||
if (DevOptions.DisablePasswordRecover == false) {
|
||||
this.setState({ ForggotPasswordVisible: true })
|
||||
}
|
||||
else {
|
||||
messageListener.then(() => message.error('Cannot connect to YulioID Services (Disabled Password Recovery)', 2.5))
|
||||
}
|
||||
}
|
||||
ValidateSession() {
|
||||
if (DevOptions.DisableLogin == false) {
|
||||
this.setState({ MainLoginVisible: true })
|
||||
}
|
||||
else {
|
||||
message.error('Error trying to connect to YulioID services', 2.5)
|
||||
$("#ErrorNotification").css({ display: 'block' })
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
// INIT
|
||||
this.setState({ server_key: endpoints.server_key });
|
||||
this.ValidateSession();
|
||||
|
||||
const istoken = localStorage.getItem('access_token');
|
||||
const isdone = this.state.CompleteFORM;
|
||||
const getSDCP = localStorage.getItem('SDCP');
|
||||
const availableToken = cookies.get('access_token')
|
||||
if (availableToken) {
|
||||
resetToken()
|
||||
}
|
||||
|
||||
if (isdone == 'true') {
|
||||
setTimeout(() => { location.reload() }, 3000);
|
||||
}
|
||||
if (!getSDCP) {
|
||||
localStorage.setItem('GetNewData', true);
|
||||
}
|
||||
}
|
||||
render() {
|
||||
const { loading, form, i18n } = this.props
|
||||
const MensageException = this.state.EXCPMS;
|
||||
const ExceptionID = this.state.ExceptionID;
|
||||
const { Panel } = Collapse;
|
||||
|
||||
const { getFieldDecorator } = this.props.form;
|
||||
|
||||
return (
|
||||
<div>
|
||||
{/* LOGIN SECTION */}
|
||||
<Drawer width={520} closable={false} visible={this.state.MainLoginVisible}>
|
||||
|
||||
<main className={styles.mainlp}>
|
||||
<section className={styles.forms}>
|
||||
|
||||
<h6 className={styles.h6lp}>YulioID™</h6>
|
||||
<h1 className={styles.h1lp}>Welcome Back !</h1>
|
||||
<form className={styles.formlogin}>
|
||||
|
||||
<div className={styles.input__wrapper}>
|
||||
|
||||
<label className={styles.labelform}><Icon type="user" style={{ fontSize: '15px' }} /> Username</label>
|
||||
<FormItem hasFeedback>{getFieldDecorator('Username', { rules: [{ required: true }] })(
|
||||
<input className={styles.inputform} type="text" placeholder="Username" onChange={(text) => { this.handleUsername(text) }} />
|
||||
)}
|
||||
</FormItem>
|
||||
</div>
|
||||
|
||||
<div className={styles.input__wrapper}>
|
||||
<label className={styles.labelform}><Icon type="unlock" style={{ fontSize: '15px' }} /> Password</label>
|
||||
<FormItem hasFeedback>{getFieldDecorator('Password', { rules: [{ required: true }] })(
|
||||
<input className={styles.inputform} type="password" placeholder="Password (At least 8 characters)" onChange={(text) => { this.handlePassword(text) }} />
|
||||
)}
|
||||
</FormItem>
|
||||
</div>
|
||||
|
||||
<div style={{ margin: 'auto' }}><a className={styles.buttonlp} id="login" onClick={this.getAuth}>Login</a></div>
|
||||
<h2 style={{ textAlign: 'center', margin: '8px', color: '#666' }}>Or</h2>
|
||||
<div style={{ float: 'left' }}><Button type="dashed" onClick={this.initFPassword} style={{ top: '8px' }}><Icon type="exclamation-circle" /> Forgotten password</Button></div>
|
||||
<div style={{ float: 'right' }}><Button type="dashed" onClick={this.initRegister} style={{ top: '8px' }}><Icon type="user-add" /> Create an account</Button></div>
|
||||
|
||||
<div className={styles.spinner__wrapper} id="loadingspn">
|
||||
<div><Icon type="loading" style={{ fontSize: 24, margin: '13px' }} spin /></div>
|
||||
<div>
|
||||
<br /><br /><br />
|
||||
<div style={{ margin: 'auto' }}><h6 className={styles.h6lp} style={{ textAlign: 'center', marginTop: '15%' }}>Wait a sec...</h6></div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
</main>
|
||||
|
||||
</Drawer>
|
||||
|
||||
{/* REGISTER SECTION */}
|
||||
<Drawer width={680} closable={true} onClose={this.cancelRegister} visible={this.state.registerVisible}>
|
||||
<main className={styles.mainlp}>
|
||||
<section className={styles.forms}>
|
||||
<h6 className={styles.h6lp}>YulioID™</h6>
|
||||
<h1 className={styles.h1lp}>Register</h1>
|
||||
<h3>Wow congratulations, very soon you will begin to discover rStudio, but first you will have to start by filling out this form</h3>
|
||||
<form className={styles.formlogin}>
|
||||
<div className={styles.inputRG__wrapper}>
|
||||
<label className={styles.labelform}> Choose your Username</label>
|
||||
<FormItem hasFeedback>{getFieldDecorator('rgUsername', { rules: [{ required: true }] })(
|
||||
<Input type="text" prefix={<Icon type="user" style={{ color: 'rgba(0,0,0,.25)' }} />} placeholder="Username" onChange={(text) => { this.handleRGUsername(text) }} />
|
||||
)}
|
||||
</FormItem>
|
||||
</div>
|
||||
<div className={styles.inputRG__wrapper}>
|
||||
<label className={styles.labelform}> Fill with your email</label>
|
||||
<FormItem hasFeedback>{getFieldDecorator('rgEmail', { rules: [{ required: true }] })(
|
||||
<Input type="text" prefix={<Icon type="link" style={{ color: 'rgba(0,0,0,.25)' }} />} placeholder="Email" onChange={(text) => { this.handleRGEmail(text) }} />
|
||||
)}
|
||||
</FormItem>
|
||||
</div>
|
||||
<div className={styles.inputRG__wrapper}>
|
||||
<label className={styles.labelform}> Fill with your password</label>
|
||||
<FormItem hasFeedback>{getFieldDecorator('rgPassword', { rules: [{ required: true }] })(
|
||||
<Input type="password" prefix={<Icon type="key" style={{ color: 'rgba(0,0,0,.25)' }} />} placeholder="Password" onChange={(text) => { this.handleRGPassword(text) }} />
|
||||
)}
|
||||
</FormItem>
|
||||
</div>
|
||||
<div className={styles.inputRG__wrapper}>
|
||||
</div>
|
||||
<div className={styles.TOSAccept}><span><span style={{ color: 'red', fontSize: '17px' }}>*</span> Clicking the register button you accept our <a href="#">terms and conditions</a></span> </div>
|
||||
<a className={styles.buttonlp} id="register" onClick={this.getRegister}>Register</a>
|
||||
<div className={styles.spinner__wrapper} id="loadingRGspn">
|
||||
<div style={{ position: 'absolute', marginLeft: '86%', marginTop: '-65%' }}><Icon type="loading" style={{ fontSize: 24 }} spin /></div>
|
||||
<div>
|
||||
<div><Icon style={{ fontSize: '160px', margin: '30px', color: '#5B2A86' }} type="smile" /></div>
|
||||
<h6 className={styles.h6lp} style={{ textAlign: 'center' }}>Ok thanks, wait a minute...</h6>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
</main>
|
||||
</Drawer>
|
||||
|
||||
{/* FORGOTTEN PASSWORD SECTION */}
|
||||
<Drawer width={420} closable={true} onClose={this.cancelRecoverPassword} visible={this.state.ForggotPasswordVisible}>
|
||||
<main className={styles.mainlp}>
|
||||
<section className={styles.forms}>
|
||||
<h6 className={styles.h6lp}>YulioID™</h6>
|
||||
<h1 className={styles.h1lp}>Forgotten Password!</h1>
|
||||
<h3>To recover your account enter the email used to register</h3>
|
||||
<form className={styles.formlogin}>
|
||||
<div className={styles.input__wrapper}>
|
||||
<label className={styles.labelform}><Icon type="mail" style={{ fontSize: '15px' }} /> Email</label>
|
||||
<FormItem hasFeedback>{getFieldDecorator('Email', { rules: [{ required: true }] })(
|
||||
<input className={styles.inputform} type="text" placeholder="myaccount@example.com" onChange={(text) => { this.handleFPEmail(text) }} /> )}
|
||||
</FormItem>
|
||||
</div>
|
||||
{/* <div style={{ margin: 'auto' }}><a className={styles.buttonlp} id="login" onClick={this.RecoverPassword(this.state.FGEmail)}>Recover</a></div> */}
|
||||
<div className={styles.spinner__wrapper} id="loadingspn">
|
||||
<div><Icon type="loading" style={{ fontSize: 24, margin: '13px' }} spin /></div>
|
||||
<div>
|
||||
<br /><br /><br />
|
||||
<div style={{ margin: 'auto' }}><h6 className={styles.h6lp} style={{ textAlign: 'center', marginTop: '15%' }}>Wait a sec...</h6></div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
</main>
|
||||
</Drawer>
|
||||
|
||||
{/* NOTF */}
|
||||
<Drawer width={320} closable={false} visible={this.state.NOTFdrawer} >
|
||||
<div style={{ textAlign: 'center', color: 'orange' }} ><Icon type="warning" style={{ fontSize: '230px' }} />
|
||||
<h2 className={styles.h2lp}> {this.state.FailArray} </h2>
|
||||
<h4 className={styles.apierrort}> {MensageException} </h4> <hr />
|
||||
<div id="details-collapse" style={{ textAlign: 'center' }}>
|
||||
<Collapse bordered={false} defaultActiveKey={['0']} expandIcon={({ isActive }) => <Icon type="caret-right" rotate={isActive ? 90 : 0} />}>
|
||||
<Panel header="Details" key="1" style={{ borderRadius: 4, marginBottom: 24, border: 0, overflow: 'hidden', }}>
|
||||
<Icon type="exception" />
|
||||
<h6>STATUS HANDLER => {this.state.ErrorType} </h6>
|
||||
<h6>EXCEPTION => {this.state.api_response} </h6>
|
||||
<h6>EXCEPTION MENSAGE => {MensageException}</h6>
|
||||
<h6><strong>ID {ExceptionID}</strong></h6>
|
||||
</Panel>
|
||||
</Collapse>
|
||||
<hr /><Button type="danger" onClick={this.closeNOTF}>TRY AGAIN</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Drawer>
|
||||
|
||||
|
||||
{/* SOTF */}
|
||||
<Drawer width={320} closable={false} visible={this.state.SOTFdrawer}>
|
||||
<div style={{ textAlign: 'center', color: '#4BB543' }} ><Icon type="check" style={{ fontSize: '200px' }} />
|
||||
<h2 className={styles.h2lp} style={{ color: '#4BB543' }} > Success </h2>
|
||||
<h4>Please wait while process your data ...</h4>
|
||||
</div>
|
||||
</Drawer>
|
||||
{/* RGSOTF */}
|
||||
<Drawer width={320} closable={false} visible={this.state.RGSOTFdrawer}>
|
||||
<div style={{ textAlign: 'center', color: 'green' }} >
|
||||
<Icon type="check" style={{ fontSize: '200px' }} />
|
||||
<h2 className={styles.h2lp} style={{ color: 'green' }} > Registered </h2>
|
||||
<h4 className={styles.apierrort}> Welcome to Dashboard, you will start discovering now</h4>
|
||||
<h4>Please check your new data while we are process you ...</h4>
|
||||
</div>
|
||||
</Drawer>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
YulioIDForms.propTypes = {
|
||||
form: PropTypes.object,
|
||||
dispatch: PropTypes.func,
|
||||
loading: PropTypes.object,
|
||||
}
|
||||
|
||||
export default YulioIDForms
|
551
src/components/YulioID/legacy/index.js
Normal file
551
src/components/YulioID/legacy/index.js
Normal file
@ -0,0 +1,551 @@
|
||||
//****************************************|
|
||||
//**** Yulio ID v1.6 *****|
|
||||
//****************************************|
|
||||
//
|
||||
// @ Licensed by RageStudio(c) 2019
|
||||
// @ Build 03102019EU21700 F/WIAPIS
|
||||
// @ https://api.ragestudio.net/RS-YIBTP
|
||||
//
|
||||
//****************************************|
|
||||
|
||||
import React, { PureComponent } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { connect } from 'dva'
|
||||
import { Button, Row, Form, Input, Drawer, Icon, Collapse, Select, Checkbox, Result, Layout, message, notification } from 'antd'
|
||||
import { Trans, withI18n } from '@lingui/react'
|
||||
import { setLocale } from 'utils'
|
||||
import { UIFxPY, UIFxList, DevOptions } from 'ycore';
|
||||
import { endpoints } from 'ycore';
|
||||
import $ from 'jquery';
|
||||
import styles from './yid.scss';
|
||||
import './ycore_sdcp';
|
||||
import YIDForms from './forms.js'
|
||||
|
||||
// import {getUserData, getUserRGData, getRegister, getAuth, resetToken, processError, processSuccess, processRGSuccess, processJSON, processRGJSON} from './loginFunctions.js';
|
||||
|
||||
import Cookies from 'universal-cookie';
|
||||
import Cryptr from 'cryptr';
|
||||
|
||||
const cookies = new Cookies();
|
||||
|
||||
const FormItem = Form.Item
|
||||
|
||||
@withI18n()
|
||||
@connect(({ loading }) => ({ loading }))
|
||||
@Form.create()
|
||||
class YulioID extends PureComponent {
|
||||
constructor() {
|
||||
super()
|
||||
this.state = {
|
||||
// Drawers Visibility (Default on False)
|
||||
MainLoginVisible: false,
|
||||
NOTFdrawer: false,
|
||||
SOTFdrawer: false,
|
||||
RGSOTFdrawer: false,
|
||||
registerVisible: false,
|
||||
ForggotPasswordVisible: false,
|
||||
// Arrays
|
||||
ErrorType: '',
|
||||
FailArray: '',
|
||||
username: '',
|
||||
password: '',
|
||||
server_key: '',
|
||||
access_token: '',
|
||||
user_data: [],
|
||||
ExceptionID: '',
|
||||
EXCPMS: '',
|
||||
CompleteFORM: '',
|
||||
TSDCP: '',
|
||||
user_id: '',
|
||||
api_response: {},
|
||||
api_response_ud: [],
|
||||
RGUsername: '',
|
||||
RGEmail: '',
|
||||
RGPassword: '',
|
||||
RGGender: '',
|
||||
}
|
||||
this.getAuth = this.getAuth.bind(this);
|
||||
this.getRegister = this.getRegister.bind(this);
|
||||
this.getUserData = this.getUserData.bind(this);
|
||||
this.initRegister = this.initRegister.bind(this);
|
||||
this.initFPassword = this.initFPassword.bind(this);
|
||||
this.cancelRegister = this.cancelRegister.bind(this);
|
||||
this.cancelRecoverPassword = this.cancelRecoverPassword.bind(this);
|
||||
this.closeNOTF = this.closeNOTF.bind(this);
|
||||
this.closeSOTF = this.closeSOTF.bind(this);
|
||||
this.closeRGSOTF = this.closeSOTF.bind(this);
|
||||
this.processSuccess = this.processSuccess.bind(this);
|
||||
this.processRGSuccess = this.processSuccess.bind(this);
|
||||
this.processJSON = this.processJSON.bind(this);
|
||||
this.processRGJSON = this.processJSON.bind(this);
|
||||
}
|
||||
// Handlers & others
|
||||
handleUsername(text) {
|
||||
this.setState({ username: text.target.value })
|
||||
}
|
||||
handlePassword(text) {
|
||||
this.setState({ password: text.target.value })
|
||||
}
|
||||
handleRGUsername(text) {
|
||||
this.setState({ RGUsername: text.target.value })
|
||||
}
|
||||
handleRGPassword(text) {
|
||||
this.setState({ RGPassword: text.target.value })
|
||||
}
|
||||
handleRGEmail(text) {
|
||||
this.setState({ RGEmail: text.target.value })
|
||||
}
|
||||
handleRGGender(Ivalue) {
|
||||
this.setState({ RGGender: Ivalue })
|
||||
}
|
||||
handleFPEmail(Ivalue) {
|
||||
this.setState({ FGEmail: Ivalue })
|
||||
}
|
||||
|
||||
|
||||
triggerNOTF() {
|
||||
this.setState({ NOTFdrawer: true });
|
||||
}
|
||||
closeNOTF() {
|
||||
this.setState({ NOTFdrawer: false });
|
||||
}
|
||||
|
||||
triggerSOTF() {
|
||||
this.setState({ SOTFdrawer: true });
|
||||
}
|
||||
closeSOTF() {
|
||||
this.setState({ SOTFdrawer: false });
|
||||
}
|
||||
|
||||
triggerRGSOTF() {
|
||||
this.setState({ RGSOTFdrawer: true });
|
||||
}
|
||||
closeRGSOTF() {
|
||||
this.setState({ RGSOTFdrawer: false });
|
||||
}
|
||||
|
||||
cancelRegister() {
|
||||
this.setState({ registerVisible: false })
|
||||
}
|
||||
cancelRecoverPassword(){
|
||||
this.setState({ ForggotPasswordVisible: false })
|
||||
}
|
||||
|
||||
initRegister() {
|
||||
var messageListener = message.loading('Initialising YulioID ', 1.5)
|
||||
{ messageListener }
|
||||
if (DevOptions.DisableRegister == false) {
|
||||
this.setState({ registerVisible: true })
|
||||
}
|
||||
else {
|
||||
messageListener.then(() => message.error('Cannot connect to YulioID Services (Disabled Register)', 2.5))
|
||||
}
|
||||
}
|
||||
|
||||
initFPassword() {
|
||||
var messageListener = message.loading('Initialising YulioID ', 1.5)
|
||||
{ messageListener }
|
||||
if (DevOptions.DisablePasswordRecover == false) {
|
||||
this.setState({ ForggotPasswordVisible: true })
|
||||
}
|
||||
else {
|
||||
messageListener.then(() => message.error('Cannot connect to YulioID Services (Disabled Password Recovery)', 2.5))
|
||||
}
|
||||
}
|
||||
ValidateSession() {
|
||||
if (DevOptions.DisableLogin == false) {
|
||||
this.setState({ MainLoginVisible: true })
|
||||
}
|
||||
else {
|
||||
message.error('Error trying to connect to YulioID services', 2.5)
|
||||
$("#ErrorNotification").css({ display: 'block' })
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
// INIT
|
||||
this.setState({ server_key: endpoints.server_key });
|
||||
this.ValidateSession();
|
||||
|
||||
const istoken = localStorage.getItem('access_token');
|
||||
const isdone = this.state.CompleteFORM;
|
||||
const getSDCP = localStorage.getItem('SDCP');
|
||||
const availableToken = cookies.get('access_token')
|
||||
if (availableToken) {
|
||||
this.resetToken()
|
||||
}
|
||||
|
||||
if (isdone == 'true') {
|
||||
setTimeout(() => { location.reload() }, 3000);
|
||||
}
|
||||
if (!getSDCP) {
|
||||
localStorage.setItem('GetNewData', true);
|
||||
}
|
||||
}
|
||||
|
||||
resetToken() {
|
||||
let _this = this;
|
||||
const tojb1 = endpoints.removeToken;
|
||||
const tobj2 = cookies.get('access_token')
|
||||
let urlOBJ = `${tojb1}${tobj2}`;
|
||||
UIFxPY(UIFxList.notifyWarning)
|
||||
var form = new FormData();
|
||||
form.append("server_key", endpoints.server_key);
|
||||
|
||||
|
||||
var settings = {
|
||||
"url": urlOBJ,
|
||||
"method": "POST",
|
||||
"timeout": 0,
|
||||
"processData": false,
|
||||
"mimeType": "multipart/form-data",
|
||||
"contentType": false,
|
||||
"data": form
|
||||
};
|
||||
$.ajax(settings).done(function (response) {
|
||||
notification.open({
|
||||
placement: 'topLeft',
|
||||
message: 'For continue your request, is necessary to login with YulioID™ again',
|
||||
description:
|
||||
'LoginBridge™ report a access token expiration, and is required you for continue login again with security reasons.',
|
||||
icon: <Icon type="login" style={{ color: '#108ee9' }} />,
|
||||
});
|
||||
cookies.remove('access_token', { path: '/' })
|
||||
});
|
||||
}
|
||||
getUserData() {
|
||||
const nonProccesContainer = this.state.api_response;
|
||||
const IdFromLRApi = JSON.parse(nonProccesContainer)['user_id'];
|
||||
const getStoragedToken = JSON.parse(nonProccesContainer)['access_token'];
|
||||
|
||||
var form2 = new FormData();
|
||||
form2.append("server_key", endpoints.server_key);
|
||||
form2.append("fetch", "user_data,email,username,avatar");
|
||||
form2.append("user_id", IdFromLRApi);
|
||||
|
||||
let _this = this;
|
||||
const yCore_GUDEP = endpoints.get_userData_endpoint;
|
||||
let urlOBJ = `${yCore_GUDEP}${getStoragedToken}`;
|
||||
|
||||
var settings2 = {
|
||||
"url": urlOBJ,
|
||||
"method": "POST",
|
||||
"timeout": 0,
|
||||
"processData": false,
|
||||
"mimeType": "multipart/form-data",
|
||||
"contentType": false,
|
||||
"data": form2
|
||||
};
|
||||
$.ajax(settings2)
|
||||
.done(function (response2) {
|
||||
_this.setState({ api_response_ud: response2 }),
|
||||
_this.processSuccess();
|
||||
})
|
||||
}
|
||||
getUserRGData() {
|
||||
const nonProccesContainer = this.state.api_response;
|
||||
const IdFromLRApi = JSON.parse(nonProccesContainer)['user_id'];
|
||||
const getStoragedToken = JSON.parse(nonProccesContainer)['access_token'];
|
||||
|
||||
var form2 = new FormData();
|
||||
form2.append("server_key", endpoints.server_key);
|
||||
form2.append("fetch", "user_data,email,username,avatar");
|
||||
form2.append("user_id", IdFromLRApi);
|
||||
|
||||
let _this = this;
|
||||
const yCore_GUDEP = endpoints.get_userData_endpoint;
|
||||
let urlOBJ = `${yCore_GUDEP}${getStoragedToken}`;
|
||||
|
||||
var settings2 = {
|
||||
"url": urlOBJ,
|
||||
"method": "POST",
|
||||
"timeout": 0,
|
||||
"processData": false,
|
||||
"mimeType": "multipart/form-data",
|
||||
"contentType": false,
|
||||
"data": form2
|
||||
};
|
||||
|
||||
$.ajax(settings2)
|
||||
.done(function (response2) {
|
||||
_this.setState({ api_response_ud: response2 }),
|
||||
_this.processRGSuccess();
|
||||
})
|
||||
|
||||
|
||||
}
|
||||
|
||||
getRegister() {
|
||||
$("#loadingRGspn").css({ opacity: 1, "z-index": 5 });
|
||||
const username = this.state.RGUsername;
|
||||
const password = this.state.RGPassword;
|
||||
const email = this.state.RGEmail;
|
||||
const confirm_password = this.state.RGPassword;
|
||||
const server_key = this.state.server_key;
|
||||
|
||||
var form = new FormData();
|
||||
|
||||
form.append("server_key", server_key);
|
||||
form.append("username", username);
|
||||
form.append("email", email);
|
||||
form.append("password", password);
|
||||
form.append("confirm_password", confirm_password);
|
||||
|
||||
var settings = {
|
||||
"url": endpoints.register_endpoint,
|
||||
"method": "POST",
|
||||
"timeout": 0,
|
||||
"processData": false,
|
||||
"mimeType": "multipart/form-data",
|
||||
"contentType": false,
|
||||
"data": form,
|
||||
};
|
||||
|
||||
let _this = this;
|
||||
$.ajax(settings)
|
||||
.done(function (response) {
|
||||
_this.setState({ api_response: response }),
|
||||
_this.processRGJSON();
|
||||
})
|
||||
.fail(function (response) {
|
||||
|
||||
_this.setState({
|
||||
FailArray: 'Server Failure',
|
||||
ErrorType: '1',
|
||||
api_response: 'Cannot catch response, Error 500',
|
||||
ExceptionID: '500',
|
||||
EXCPMS: 'Cannot catch response, Error 500',
|
||||
|
||||
}),
|
||||
$("#loadingRGspn").css({ opacity: 0, "z-index": -1 }),
|
||||
_this.triggerNOTF();
|
||||
})
|
||||
}
|
||||
|
||||
RecoverPassword(inputIO){
|
||||
const cookies = new Cookies();
|
||||
let _this = this;
|
||||
const tojb1 = endpoints.resetPassword_endpoint;
|
||||
const tobj2 = cookies.get('access_token')
|
||||
let urlOBJ = `${tojb1}${tobj2}`;
|
||||
UIFxPY(UIFxList.notifyWarning)
|
||||
var form = new FormData();
|
||||
form.append("server_key", endpoints.server_key);
|
||||
form.append("email", inputIO);
|
||||
|
||||
var settings = {
|
||||
"url": urlOBJ,
|
||||
"method": "POST",
|
||||
"timeout": 0,
|
||||
"processData": false,
|
||||
"mimeType": "multipart/form-data",
|
||||
"contentType": false,
|
||||
"data": form
|
||||
};
|
||||
$.ajax(settings).done(function (response) {
|
||||
notification.open({
|
||||
placement: 'topLeft',
|
||||
message: 'The instructions to recover your account have been sent to the email',
|
||||
description:
|
||||
'If you cant find the email, try looking for it in the spam folder or try again',
|
||||
icon: <Icon type="mail" style={{ color: '#108ee9' }} />,
|
||||
});
|
||||
console.log(response)
|
||||
});
|
||||
}
|
||||
|
||||
getAuth() {
|
||||
$("#loadingspn").css({ opacity: 1, "z-index": 5 });
|
||||
const username = this.state.username;
|
||||
const password = this.state.password;
|
||||
const server_key = this.state.server_key;
|
||||
|
||||
var form = new FormData();
|
||||
|
||||
form.append("server_key", server_key);
|
||||
form.append("username", username);
|
||||
form.append("password", password);
|
||||
var settings = {
|
||||
"url": endpoints.auth_endpoint,
|
||||
"method": "POST",
|
||||
"timeout": 0,
|
||||
"processData": false,
|
||||
"mimeType": "multipart/form-data",
|
||||
"contentType": false,
|
||||
"data": form,
|
||||
};
|
||||
|
||||
let _this = this;
|
||||
$.ajax(settings)
|
||||
.done(function (response) {
|
||||
_this.setState({ api_response: response }),
|
||||
_this.processJSON();
|
||||
})
|
||||
.fail(function (response) {
|
||||
|
||||
_this.setState({
|
||||
FailArray: 'Server Failure',
|
||||
ErrorType: '1',
|
||||
api_response: 'Cannot catch response, Error 500',
|
||||
ExceptionID: '500',
|
||||
EXCPMS: 'Cannot catch response, Error 500',
|
||||
|
||||
}),
|
||||
notification.open({
|
||||
placement: 'topLeft',
|
||||
message: 'Currently our servers are having operating problems',
|
||||
description: 'Please be patient until the services become available again, try again later. We apologize for the inconveniences',
|
||||
icon: <Icon type="login" style={{ color: '#ff0f2f' }} />
|
||||
}),
|
||||
$("#loadingspn").css({ opacity: 0, "z-index": -1 }),
|
||||
_this.triggerNOTF();
|
||||
})
|
||||
|
||||
|
||||
}
|
||||
|
||||
processError() {
|
||||
const nonProccesContainer = this.state.api_response;
|
||||
const stringParsed = JSON.parse(nonProccesContainer)['api_status'];
|
||||
const ExceptionMensage = JSON.parse(this.state.api_response)['errors'];
|
||||
const ExcepID = ExceptionMensage.error_id;
|
||||
const ExceptionMensagePRC = ExceptionMensage.error_text;
|
||||
|
||||
if (stringParsed == '400') {
|
||||
this.triggerNOTF();
|
||||
this.setState({ FailArray: 'Bad credentials' });
|
||||
this.setState({
|
||||
ErrorType: stringParsed,
|
||||
ExceptionID: ExcepID
|
||||
});
|
||||
$("#loadingspn").css({ opacity: 0, "z-index": -1 });
|
||||
$("#loadingRGspn").css({ opacity: 0, "z-index": -1 });
|
||||
this.setState({ EXCPMS: ExceptionMensagePRC });
|
||||
}
|
||||
if (stringParsed == '404') {
|
||||
this.triggerNOTF();
|
||||
this.setState({ ErrorType: stringParsed });
|
||||
$("#loadingspn").css({ opacity: 0, "z-index": -1 });
|
||||
$("#loadingRGspn").css({ opacity: 0, "z-index": -1 });
|
||||
this.setState({ EXCPMS: ExceptionMensagePRC });
|
||||
}
|
||||
}
|
||||
|
||||
processSuccess() {
|
||||
// CREATE SDCP PACKAGE
|
||||
const nonProccesContainer = this.state.api_response;
|
||||
const accessTokesParsed = JSON.parse(this.state.api_response)['access_token'];
|
||||
const userDataParsed = JSON.parse(this.state.api_response_ud)['user_data'];
|
||||
this.setState({ user_data: userDataParsed });
|
||||
const proccessForParse = JSON.stringify(this.state.user_data);
|
||||
const icryptr = new Cryptr(accessTokesParsed);
|
||||
const encryptedString = icryptr.encrypt(proccessForParse);
|
||||
|
||||
this.setState({ access_token: accessTokesParsed, TSDCP: encryptedString });
|
||||
|
||||
cookies.set('access_token', accessTokesParsed, { path: '/' });
|
||||
cookies.set('last_api_response', nonProccesContainer, { path: '/' });
|
||||
cookies.set('last_api_response_ud', (this.state.TSDCP), { path: '/' });
|
||||
|
||||
localStorage.setItem('UIfx', 0.6);
|
||||
localStorage.setItem('SDCP', (this.state.TSDCP));
|
||||
|
||||
const usernameST = this.state.username;
|
||||
const password = this.state.password;
|
||||
|
||||
this.triggerSOTF();
|
||||
|
||||
const userID = JSON.parse(proccessForParse)['user_id'];
|
||||
let avatar = JSON.parse(proccessForParse)['avatar'];
|
||||
|
||||
const { dispatch } = this.props;
|
||||
let dispatchPayloadValue = { userID, usernameST, avatar, accessTokesParsed };
|
||||
setTimeout(function () { dispatch({ type: 'login/login', payload: dispatchPayloadValue }) }, 1300)
|
||||
UIFxPY(UIFxList.notifySuccess, 0.5);
|
||||
console.log('%c 🎉 Your data has been storaged in SDCP with this values 🎉 =>', 'background: orange; font-size: 16px; color: white; display: block;', dispatchPayloadValue);
|
||||
|
||||
}
|
||||
processRGSuccess() {
|
||||
// CREATE SDCP PACKAGE
|
||||
const nonProccesContainer = this.state.api_response;
|
||||
const accessTokesParsed = JSON.parse(this.state.api_response)['access_token'];
|
||||
const userDataParsed = JSON.parse(this.state.api_response_ud)['user_data'];
|
||||
this.setState({ user_data: userDataParsed });
|
||||
const proccessForParse = JSON.stringify(this.state.user_data);
|
||||
const icryptr = new Cryptr(accessTokesParsed);
|
||||
const encryptedString = icryptr.encrypt(proccessForParse);
|
||||
|
||||
this.setState({ access_token: accessTokesParsed, TSDCP: encryptedString });
|
||||
|
||||
cookies.set('access_token', accessTokesParsed, { path: '/' });
|
||||
cookies.set('last_api_response', nonProccesContainer, { path: '/' });
|
||||
cookies.set('last_api_response_ud', (this.state.TSDCP), { path: '/' });
|
||||
|
||||
localStorage.setItem('UIfx', 0.6);
|
||||
localStorage.setItem('SDCP', (this.state.TSDCP));
|
||||
|
||||
const usernameST = this.state.RGUsername;
|
||||
|
||||
this.triggerRGSOTF();
|
||||
|
||||
const userID = JSON.parse(proccessForParse)['user_id'];
|
||||
const identADMINType = JSON.parse(proccessForParse)['admin'];
|
||||
const identDEVELOPERType = JSON.parse(proccessForParse)['dev'];
|
||||
|
||||
let avatar = JSON.parse(proccessForParse)['avatar'];
|
||||
|
||||
const { dispatch } = this.props;
|
||||
let dispatchPayloadValue = { userID, usernameST, avatar, accessTokesParsed };
|
||||
setTimeout(function () { dispatch({ type: 'login/login', payload: dispatchPayloadValue }) }, 1300)
|
||||
UIFxPY(UIFxList.notifySuccess, 0.3);
|
||||
console.log('%c 🎉 Your data has been storaged in SDCP with this values 🎉 =>', 'background: orange; font-size: 16px; color: white; display: block;', dispatchPayloadValue);
|
||||
|
||||
}
|
||||
|
||||
processJSON() {
|
||||
const nonProccesContainer = this.state.api_response;
|
||||
const stringParsed = JSON.parse(nonProccesContainer);
|
||||
const identStatus = JSON.parse(nonProccesContainer)['api_status'];
|
||||
if (DevOptions.InfiniteLogin == false) {
|
||||
if (identStatus == '400') {
|
||||
this.processError();
|
||||
}
|
||||
|
||||
if (identStatus == '200') {
|
||||
this.getUserData();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
processRGJSON() {
|
||||
const nonProccesContainer = this.state.api_response;
|
||||
const stringParsed = JSON.parse(nonProccesContainer);
|
||||
const identStatus = JSON.parse(nonProccesContainer)['api_status'];
|
||||
if (identStatus == '400') {
|
||||
$("#loadingRGspn").css({ opacity: 0, "z-index": -1 }),
|
||||
this.processError();
|
||||
}
|
||||
|
||||
if (identStatus == '200') {
|
||||
this.getRGUserData();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
render() {
|
||||
const ErrorType = this.state.ErrorType;
|
||||
const MensageException = this.state.EXCPMS;
|
||||
const ExceptionID = this.state.ExceptionID;
|
||||
const { Panel } = Collapse;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div id='ErrorNotification' style={{ display: 'none', marginTop: '15%' }}><Result status="error" title="There are some problems with your operation." /></div>
|
||||
<YIDForms />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export default YulioID
|
738
src/components/YulioID/legacy/legacy.js
Normal file
738
src/components/YulioID/legacy/legacy.js
Normal file
@ -0,0 +1,738 @@
|
||||
//****************************************|
|
||||
//**** Yulio ID v1.6 *****|
|
||||
//****************************************|
|
||||
//
|
||||
// @ Licensed by RageStudio(c) 2019
|
||||
// @ Build 03102019EU21700 F/WIAPIS
|
||||
// @ https://api.ragestudio.net/RS-YIBTP
|
||||
//
|
||||
//****************************************|
|
||||
|
||||
import React, { PureComponent } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { connect } from 'dva'
|
||||
import { Button, Row, Form, Input, Drawer, Icon, Collapse, Select, Checkbox, Result, Layout, message, notification } from 'antd'
|
||||
import { Trans, withI18n } from '@lingui/react'
|
||||
import { setLocale } from 'utils'
|
||||
import { UIFxPY, UIFxList, DevOptions, avilableSDCP } from 'ycore';
|
||||
import { endpoints } from 'ycore';
|
||||
import router from 'umi/router'
|
||||
import $ from 'jquery';
|
||||
import styles from './yid.scss';
|
||||
|
||||
// import {getUserData, getUserRGData, getRegister, getAuth, resetToken, processError, processSuccess, processRGSuccess, processJSON, processRGJSON} from './loginFunctions.js';
|
||||
|
||||
import Cookies from 'universal-cookie';
|
||||
import Cryptr from 'cryptr';
|
||||
|
||||
const cookies = new Cookies();
|
||||
|
||||
const FormItem = Form.Item
|
||||
|
||||
|
||||
const RenderInclude = ({data}) => {if (!data) {return null;} else {return data;}}
|
||||
|
||||
|
||||
|
||||
@withI18n()
|
||||
@connect(({ loading }) => ({ loading }))
|
||||
@Form.create()
|
||||
class YulioID extends PureComponent {
|
||||
|
||||
constructor(props) {
|
||||
super()
|
||||
this.state = {
|
||||
// Drawers Visibility (Default on False)
|
||||
MainLoginVisible: false,
|
||||
NOTFdrawer: false,
|
||||
SOTFdrawer: false,
|
||||
RGSOTFdrawer: false,
|
||||
registerVisible: false,
|
||||
ForggotPasswordVisible: false,
|
||||
// Arrays
|
||||
ErrorType: '',
|
||||
FailArray: '',
|
||||
username: '',
|
||||
password: '',
|
||||
server_key: '',
|
||||
access_token: '',
|
||||
user_data: [],
|
||||
ExceptionID: '',
|
||||
EXCPMS: '',
|
||||
CompleteFORM: '',
|
||||
TSDCP: '',
|
||||
user_id: '',
|
||||
api_response: {},
|
||||
api_response_ud: [],
|
||||
RGUsername: '',
|
||||
RGEmail: '',
|
||||
RGPassword: '',
|
||||
RGGender: '',
|
||||
}
|
||||
this.getAuth = this.getAuth.bind(this);
|
||||
this.getRegister = this.getRegister.bind(this);
|
||||
this.getUserData = this.getUserData.bind(this);
|
||||
this.initRegister = this.initRegister.bind(this);
|
||||
this.initFPassword = this.initFPassword.bind(this);
|
||||
this.cancelRegister = this.cancelRegister.bind(this);
|
||||
this.cancelRecoverPassword = this.cancelRecoverPassword.bind(this);
|
||||
this.closeNOTF = this.closeNOTF.bind(this);
|
||||
this.closeSOTF = this.closeSOTF.bind(this);
|
||||
this.closeRGSOTF = this.closeSOTF.bind(this);
|
||||
this.processSuccess = this.processSuccess.bind(this);
|
||||
this.processRGSuccess = this.processSuccess.bind(this);
|
||||
this.processJSON = this.processJSON.bind(this);
|
||||
this.processRGJSON = this.processJSON.bind(this);
|
||||
this.handleKeyDown = this.handleKeyDown.bind(this);
|
||||
}
|
||||
// Handlers & others
|
||||
handleUsername(text) {
|
||||
this.setState({ username: text.target.value })
|
||||
}
|
||||
handlePassword(text) {
|
||||
this.setState({ password: text.target.value })
|
||||
}
|
||||
handleRGUsername(text) {
|
||||
this.setState({ RGUsername: text.target.value })
|
||||
}
|
||||
handleRGPassword(text) {
|
||||
this.setState({ RGPassword: text.target.value })
|
||||
}
|
||||
handleRGEmail(text) {
|
||||
this.setState({ RGEmail: text.target.value })
|
||||
}
|
||||
handleRGGender(Ivalue) {
|
||||
this.setState({ RGGender: Ivalue })
|
||||
}
|
||||
handleFPEmail(Ivalue) {
|
||||
this.setState({ FGEmail: Ivalue })
|
||||
}
|
||||
|
||||
triggerNOTF() {
|
||||
this.setState({ NOTFdrawer: true });
|
||||
}
|
||||
closeNOTF() {
|
||||
this.setState({ NOTFdrawer: false });
|
||||
}
|
||||
|
||||
triggerSOTF() {
|
||||
this.setState({ SOTFdrawer: true });
|
||||
}
|
||||
closeSOTF() {
|
||||
this.setState({ SOTFdrawer: false });
|
||||
}
|
||||
|
||||
triggerRGSOTF() {
|
||||
this.setState({ RGSOTFdrawer: true });
|
||||
}
|
||||
closeRGSOTF() {
|
||||
this.setState({ RGSOTFdrawer: false });
|
||||
}
|
||||
|
||||
cancelRegister() {
|
||||
this.setState({ registerVisible: false })
|
||||
}
|
||||
cancelRecoverPassword(){
|
||||
this.setState({ ForggotPasswordVisible: false })
|
||||
}
|
||||
|
||||
initRegister() {
|
||||
var messageListener = message.loading('Initialising YulioID...', 1.5)
|
||||
{ messageListener }
|
||||
if (DevOptions.DisableRegister == false) {
|
||||
this.setState({ registerVisible: true })
|
||||
}
|
||||
else {
|
||||
messageListener.then(() => message.error('Cannot connect to YulioID Services (Disabled Register)', 2.5))
|
||||
}
|
||||
}
|
||||
|
||||
initFPassword() {
|
||||
var messageListener = message.loading('Initialising YulioID...', 1.5)
|
||||
{ messageListener }
|
||||
if (DevOptions.DisablePasswordRecover == false) {
|
||||
this.setState({ ForggotPasswordVisible: true })
|
||||
}
|
||||
else {
|
||||
messageListener.then(() => message.error('Cannot connect to YulioID Services (Disabled Password Recovery)', 2.5))
|
||||
}
|
||||
}
|
||||
ValidateSession() {
|
||||
if (DevOptions.DisableLogin == false) {
|
||||
this.setState({ MainLoginVisible: true })
|
||||
}
|
||||
else {
|
||||
message.error('Error trying to connect to YulioID services', 2.5)
|
||||
$("#ErrorNotification").css({ display: 'block' })
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
// INIT
|
||||
this.setState({ server_key: endpoints.server_key });
|
||||
this.ValidateSession();
|
||||
|
||||
const istoken = localStorage.getItem('access_token');
|
||||
const isdone = this.state.CompleteFORM;
|
||||
const getSDCP = localStorage.getItem('SDCP');
|
||||
const availableToken = cookies.get('access_token')
|
||||
if (availableToken) {
|
||||
this.resetToken()
|
||||
|
||||
}
|
||||
|
||||
if (isdone == 'true') {
|
||||
setTimeout(() => { location.reload() }, 3000);
|
||||
}
|
||||
if (!getSDCP) {
|
||||
localStorage.setItem('GetNewData', true);
|
||||
}
|
||||
}
|
||||
|
||||
resetToken() {
|
||||
let _this = this;
|
||||
const tojb1 = endpoints.removeToken;
|
||||
const tobj2 = cookies.get('access_token')
|
||||
let urlOBJ = `${tojb1}${tobj2}`;
|
||||
UIFxPY(UIFxList.notifyWarning)
|
||||
var form = new FormData();
|
||||
form.append("server_key", endpoints.server_key);
|
||||
|
||||
|
||||
var settings = {
|
||||
"url": urlOBJ,
|
||||
"method": "POST",
|
||||
"timeout": 0,
|
||||
"processData": false,
|
||||
"mimeType": "multipart/form-data",
|
||||
"contentType": false,
|
||||
"data": form
|
||||
};
|
||||
$.ajax(settings).done(function (response) {
|
||||
notification.open({
|
||||
placement: 'topLeft',
|
||||
message: 'For continue your request, is necessary to login with YulioID™ again',
|
||||
description:
|
||||
'LoginBridge™ report a access token expiration, and is required you for continue login again with security reasons.',
|
||||
icon: <Icon type="login" style={{ color: '#108ee9' }} />,
|
||||
});
|
||||
cookies.remove('access_token', { path: '/' })
|
||||
});
|
||||
}
|
||||
getUserData() {
|
||||
const nonProccesContainer = this.state.api_response;
|
||||
const IdFromLRApi = JSON.parse(nonProccesContainer)['user_id'];
|
||||
const getStoragedToken = JSON.parse(nonProccesContainer)['access_token'];
|
||||
|
||||
var form2 = new FormData();
|
||||
form2.append("server_key", endpoints.server_key);
|
||||
form2.append("fetch", "user_data,email,username,avatar");
|
||||
form2.append("user_id", IdFromLRApi);
|
||||
|
||||
let _this = this;
|
||||
const yCore_GUDEP = endpoints.get_userData_endpoint;
|
||||
let urlOBJ = `${yCore_GUDEP}${getStoragedToken}`;
|
||||
|
||||
var settings2 = {
|
||||
"url": urlOBJ,
|
||||
"method": "POST",
|
||||
"timeout": 0,
|
||||
"processData": false,
|
||||
"mimeType": "multipart/form-data",
|
||||
"contentType": false,
|
||||
"data": form2
|
||||
};
|
||||
$.ajax(settings2)
|
||||
.done(function (response2) {
|
||||
_this.setState({ api_response_ud: response2 }),
|
||||
_this.processSuccess();
|
||||
})
|
||||
}
|
||||
getUserRGData() {
|
||||
const nonProccesContainer = this.state.api_response;
|
||||
const IdFromLRApi = JSON.parse(nonProccesContainer)['user_id'];
|
||||
const getStoragedToken = JSON.parse(nonProccesContainer)['access_token'];
|
||||
|
||||
var form2 = new FormData();
|
||||
form2.append("server_key", endpoints.server_key);
|
||||
form2.append("fetch", "user_data,email,username,avatar");
|
||||
form2.append("user_id", IdFromLRApi);
|
||||
|
||||
let _this = this;
|
||||
const yCore_GUDEP = endpoints.get_userData_endpoint;
|
||||
let urlOBJ = `${yCore_GUDEP}${getStoragedToken}`;
|
||||
|
||||
var settings2 = {
|
||||
"url": urlOBJ,
|
||||
"method": "POST",
|
||||
"timeout": 0,
|
||||
"processData": false,
|
||||
"mimeType": "multipart/form-data",
|
||||
"contentType": false,
|
||||
"data": form2
|
||||
};
|
||||
|
||||
$.ajax(settings2)
|
||||
.done(function (response2) {
|
||||
_this.setState({ api_response_ud: response2 }),
|
||||
_this.processRGSuccess();
|
||||
})
|
||||
|
||||
|
||||
}
|
||||
|
||||
getRegister() {
|
||||
$("#loadingRGspn").css({ opacity: 1, "z-index": 5 });
|
||||
const username = this.state.RGUsername;
|
||||
const password = this.state.RGPassword;
|
||||
const email = this.state.RGEmail;
|
||||
const confirm_password = this.state.RGPassword;
|
||||
const server_key = this.state.server_key;
|
||||
|
||||
var form = new FormData();
|
||||
|
||||
form.append("server_key", server_key);
|
||||
form.append("username", username);
|
||||
form.append("email", email);
|
||||
form.append("password", password);
|
||||
form.append("confirm_password", confirm_password);
|
||||
|
||||
var settings = {
|
||||
"url": endpoints.register_endpoint,
|
||||
"method": "POST",
|
||||
"timeout": 0,
|
||||
"processData": false,
|
||||
"mimeType": "multipart/form-data",
|
||||
"contentType": false,
|
||||
"data": form,
|
||||
};
|
||||
|
||||
let _this = this;
|
||||
$.ajax(settings)
|
||||
.done(function (response) {
|
||||
_this.setState({ api_response: response }),
|
||||
_this.processRGJSON();
|
||||
})
|
||||
.fail(function (response) {
|
||||
|
||||
_this.setState({
|
||||
FailArray: 'Server Failure',
|
||||
ErrorType: '1',
|
||||
api_response: 'Cannot catch response, Error 500',
|
||||
ExceptionID: '500',
|
||||
EXCPMS: 'Cannot catch response, Error 500',
|
||||
|
||||
}),
|
||||
$("#loadingRGspn").css({ opacity: 0, "z-index": -1 }),
|
||||
_this.triggerNOTF();
|
||||
})
|
||||
}
|
||||
|
||||
RecoverPassword(inputIO){
|
||||
const cookies = new Cookies();
|
||||
let _this = this;
|
||||
const tojb1 = endpoints.resetPassword_endpoint;
|
||||
const tobj2 = cookies.get('access_token')
|
||||
let urlOBJ = `${tojb1}${tobj2}`;
|
||||
UIFxPY(UIFxList.notifyWarning)
|
||||
var form = new FormData();
|
||||
form.append("server_key", endpoints.server_key);
|
||||
form.append("email", inputIO);
|
||||
|
||||
var settings = {
|
||||
"url": urlOBJ,
|
||||
"method": "POST",
|
||||
"timeout": 0,
|
||||
"processData": false,
|
||||
"mimeType": "multipart/form-data",
|
||||
"contentType": false,
|
||||
"data": form
|
||||
};
|
||||
$.ajax(settings).done(function (response) {
|
||||
notification.open({
|
||||
placement: 'topLeft',
|
||||
message: 'The instructions to recover your account have been sent to the email',
|
||||
description:
|
||||
'If you cant find the email, try looking for it in the spam folder or try again',
|
||||
icon: <Icon type="mail" style={{ color: '#108ee9' }} />,
|
||||
});
|
||||
console.log(response)
|
||||
});
|
||||
}
|
||||
|
||||
getAuth() {
|
||||
$("#loadingspn").css({ opacity: 1, "z-index": 5 });
|
||||
const username = this.state.username;
|
||||
const password = this.state.password;
|
||||
const server_key = this.state.server_key;
|
||||
|
||||
var form = new FormData();
|
||||
|
||||
form.append("server_key", server_key);
|
||||
form.append("username", username);
|
||||
form.append("password", password);
|
||||
var settings = {
|
||||
"url": endpoints.auth_endpoint,
|
||||
"method": "POST",
|
||||
"timeout": 0,
|
||||
"processData": false,
|
||||
"mimeType": "multipart/form-data",
|
||||
"contentType": false,
|
||||
"data": form,
|
||||
};
|
||||
|
||||
let _this = this;
|
||||
$.ajax(settings)
|
||||
.done(function (response) {
|
||||
_this.setState({ api_response: response }),
|
||||
_this.processJSON();
|
||||
})
|
||||
.fail(function (response) {
|
||||
|
||||
_this.setState({
|
||||
FailArray: 'Server Failure',
|
||||
ErrorType: '1',
|
||||
api_response: 'Cannot catch response, Error 500',
|
||||
ExceptionID: '500',
|
||||
EXCPMS: 'Cannot catch response, Error 500',
|
||||
|
||||
}),
|
||||
notification.open({
|
||||
placement: 'topLeft',
|
||||
message: 'Currently our servers are having operating problems',
|
||||
description: 'Please be patient until the services become available again, try again later. We apologize for the inconveniences',
|
||||
icon: <Icon type="login" style={{ color: '#ff0f2f' }} />
|
||||
}),
|
||||
$("#loadingspn").css({ opacity: 0, "z-index": -1 }),
|
||||
_this.triggerNOTF();
|
||||
})
|
||||
|
||||
|
||||
}
|
||||
|
||||
processError() {
|
||||
const nonProccesContainer = this.state.api_response;
|
||||
const stringParsed = JSON.parse(nonProccesContainer)['api_status'];
|
||||
const ExceptionMensage = JSON.parse(this.state.api_response)['errors'];
|
||||
const ExcepID = ExceptionMensage.error_id;
|
||||
const ExceptionMensagePRC = ExceptionMensage.error_text;
|
||||
|
||||
if (stringParsed == '400') {
|
||||
this.triggerNOTF();
|
||||
this.setState({ FailArray: 'Bad credentials' });
|
||||
this.setState({
|
||||
ErrorType: stringParsed,
|
||||
ExceptionID: ExcepID
|
||||
});
|
||||
$("#loadingspn").css({ opacity: 0, "z-index": -1 });
|
||||
$("#loadingRGspn").css({ opacity: 0, "z-index": -1 });
|
||||
this.setState({ EXCPMS: ExceptionMensagePRC });
|
||||
}
|
||||
if (stringParsed == '404') {
|
||||
this.triggerNOTF();
|
||||
this.setState({ ErrorType: stringParsed });
|
||||
$("#loadingspn").css({ opacity: 0, "z-index": -1 });
|
||||
$("#loadingRGspn").css({ opacity: 0, "z-index": -1 });
|
||||
this.setState({ EXCPMS: ExceptionMensagePRC });
|
||||
}
|
||||
}
|
||||
|
||||
processSuccess() {
|
||||
// CREATE SDCP PACKAGE
|
||||
const nonProccesContainer = this.state.api_response;
|
||||
const accessTokesParsed = JSON.parse(this.state.api_response)['access_token'];
|
||||
const userDataParsed = JSON.parse(this.state.api_response_ud)['user_data'];
|
||||
this.setState({ user_data: userDataParsed });
|
||||
const proccessForParse = JSON.stringify(this.state.user_data);
|
||||
const icryptr = new Cryptr(accessTokesParsed);
|
||||
const encryptedString = icryptr.encrypt(proccessForParse);
|
||||
|
||||
this.setState({ access_token: accessTokesParsed, TSDCP: encryptedString });
|
||||
|
||||
cookies.set('access_token', accessTokesParsed, { path: '/' });
|
||||
cookies.set('last_api_response', nonProccesContainer, { path: '/' });
|
||||
cookies.set('last_api_response_ud', (this.state.TSDCP), { path: '/' });
|
||||
|
||||
localStorage.setItem('UIfx', 0.6);
|
||||
localStorage.setItem('SDCP', (this.state.TSDCP));
|
||||
|
||||
const usernameST = this.state.username;
|
||||
|
||||
this.triggerSOTF();
|
||||
|
||||
const userID = JSON.parse(proccessForParse)['user_id'];
|
||||
let avatar = JSON.parse(proccessForParse)['avatar'];
|
||||
|
||||
const { dispatch } = this.props;
|
||||
let dispatchPayloadValue = { userID, usernameST, avatar, accessTokesParsed };
|
||||
setTimeout(function () { dispatch({ type: 'login/login', payload: dispatchPayloadValue }) }, 1300)
|
||||
UIFxPY(UIFxList.notifySuccess, 0.5);
|
||||
console.log('%c 🎉 Your data has been storaged in SDCP with this values 🎉 =>', 'background: orange; font-size: 16px; color: white; display: block;', dispatchPayloadValue);
|
||||
|
||||
}
|
||||
processRGSuccess() {
|
||||
// CREATE SDCP PACKAGE
|
||||
const nonProccesContainer = this.state.api_response;
|
||||
const accessTokesParsed = JSON.parse(this.state.api_response)['access_token'];
|
||||
const userDataParsed = JSON.parse(this.state.api_response_ud)['user_data'];
|
||||
this.setState({ user_data: userDataParsed });
|
||||
const proccessForParse = JSON.stringify(this.state.user_data);
|
||||
const icryptr = new Cryptr(accessTokesParsed);
|
||||
const encryptedString = icryptr.encrypt(proccessForParse);
|
||||
|
||||
this.setState({ access_token: accessTokesParsed, TSDCP: encryptedString });
|
||||
|
||||
cookies.set('access_token', accessTokesParsed, { path: '/' });
|
||||
cookies.set('last_api_response', nonProccesContainer, { path: '/' });
|
||||
cookies.set('last_api_response_ud', (this.state.TSDCP), { path: '/' });
|
||||
|
||||
localStorage.setItem('UIfx', 0.6);
|
||||
localStorage.setItem('SDCP', (this.state.TSDCP));
|
||||
|
||||
const usernameST = this.state.RGUsername;
|
||||
|
||||
this.triggerRGSOTF();
|
||||
|
||||
const userID = JSON.parse(proccessForParse)['user_id'];
|
||||
const identADMINType = JSON.parse(proccessForParse)['admin'];
|
||||
const identDEVELOPERType = JSON.parse(proccessForParse)['dev'];
|
||||
|
||||
let avatar = JSON.parse(proccessForParse)['avatar'];
|
||||
|
||||
const { dispatch } = this.props;
|
||||
let dispatchPayloadValue = { userID, usernameST, avatar, accessTokesParsed };
|
||||
setTimeout(function () { dispatch({ type: 'login/login', payload: dispatchPayloadValue }) }, 1300)
|
||||
UIFxPY(UIFxList.notifySuccess, 0.3);
|
||||
console.log('%c 🎉 Your data has been storaged in SDCP with this values 🎉 =>', 'background: orange; font-size: 16px; color: white; display: block;', dispatchPayloadValue);
|
||||
|
||||
}
|
||||
|
||||
processJSON() {
|
||||
const nonProccesContainer = this.state.api_response;
|
||||
const stringParsed = JSON.parse(nonProccesContainer);
|
||||
const identStatus = JSON.parse(nonProccesContainer)['api_status'];
|
||||
if (DevOptions.InfiniteLogin == false) {
|
||||
if (identStatus == '400') {
|
||||
this.processError();
|
||||
}
|
||||
|
||||
if (identStatus == '200') {
|
||||
this.getUserData();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
processRGJSON() {
|
||||
const nonProccesContainer = this.state.api_response;
|
||||
const stringParsed = JSON.parse(nonProccesContainer);
|
||||
const identStatus = JSON.parse(nonProccesContainer)['api_status'];
|
||||
if (identStatus == '400') {
|
||||
$("#loadingRGspn").css({ opacity: 0, "z-index": -1 }),
|
||||
this.processError();
|
||||
}
|
||||
|
||||
if (identStatus == '200') {
|
||||
this.getRGUserData();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
handleKeyDown = (e) => {
|
||||
const _this = this;
|
||||
if (e.key === 'Enter') {
|
||||
this.getAuth
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
render() {
|
||||
const { loading, form, i18n, include} = this.props
|
||||
const ErrorType = this.state.ErrorType;
|
||||
const MensageException = this.state.EXCPMS;
|
||||
const ExceptionID = this.state.ExceptionID;
|
||||
const { Panel } = Collapse;
|
||||
|
||||
const { getFieldDecorator } = this.props.form;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div id='ErrorNotification' style={{ display: 'none', marginTop: '15%' }}><Result status="error" title="There are some problems with your operation." /></div>
|
||||
|
||||
|
||||
{/* LOGIN SECTION */}
|
||||
<Drawer width={520} closable={false} visible={this.state.MainLoginVisible}>
|
||||
|
||||
<main className={styles.mainlp}>
|
||||
<section className={styles.forms}>
|
||||
|
||||
<h6 className={styles.h6lp}>YulioID™</h6>
|
||||
<h1 className={styles.h1lp}>Welcome Back !</h1>
|
||||
|
||||
|
||||
<form className={styles.formlogin}>
|
||||
|
||||
<div className={styles.input__wrapper}>
|
||||
|
||||
<label className={styles.labelform}><Icon type="user" style={{ fontSize: '15px' }} /> Username</label>
|
||||
<FormItem hasFeedback>{getFieldDecorator('Username', { rules: [{ required: true }] })(
|
||||
<input className={styles.inputform} type="text" onKeyDown={this.handleKeyDown} placeholder="Username" onChange={(text) => { this.handleUsername(text) }} />
|
||||
)}
|
||||
</FormItem>
|
||||
</div>
|
||||
|
||||
<div className={styles.input__wrapper}>
|
||||
<label className={styles.labelform}><Icon type="unlock" style={{ fontSize: '15px' }} /> Password</label>
|
||||
<FormItem hasFeedback>{getFieldDecorator('Password', { rules: [{ required: true }] })(
|
||||
<input className={styles.inputform} type="password" onKeyDown={this.handleKeyDown} dplaceholder="Password (At least 8 characters)" onChange={(text) => { this.handlePassword(text) }} />
|
||||
)}
|
||||
</FormItem>
|
||||
</div>
|
||||
|
||||
<div style={{ margin: 'auto' }}><a className={styles.buttonlp} id="login" onClick={this.getAuth} >Login</a></div>
|
||||
<h2 style={{ textAlign: 'center', margin: '8px', color: '#666' }}>Or</h2>
|
||||
<div style={{ float: 'left' }}><Button type="dashed" onClick={this.initFPassword} style={{ top: '8px' }}><Icon type="exclamation-circle" /> Forgotten password</Button></div>
|
||||
<div style={{ float: 'right' }}><Button type="dashed" onClick={this.initRegister} style={{ top: '8px' }}><Icon type="user-add" /> Create an account</Button></div><br/><br/>
|
||||
<div style={{ textAlign: 'center', margin: '20px' }}> <RenderInclude data={include} /></div>
|
||||
<div className={styles.spinner__wrapper} id="loadingspn">
|
||||
<div><Icon type="loading" style={{ fontSize: 24, margin: '13px' }} spin /></div>
|
||||
<div>
|
||||
<br /><br /><br />
|
||||
<div style={{ margin: 'auto' }}><h6 className={styles.h6lp} style={{ textAlign: 'center', marginTop: '15%' }}>Wait a sec...</h6></div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
</main>
|
||||
|
||||
</Drawer>
|
||||
|
||||
{/* REGISTER SECTION */}
|
||||
<Drawer width={680} closable={true} onClose={this.cancelRegister} visible={this.state.registerVisible}>
|
||||
<main className={styles.mainlp}>
|
||||
<section className={styles.forms}>
|
||||
<h6 className={styles.h6lp}>YulioID™</h6>
|
||||
<h1 className={styles.h1lp}>Register</h1>
|
||||
<h3>Wow congratulations, very soon you will begin to discover rStudio, but first you will have to start by filling out this form</h3>
|
||||
<form className={styles.formlogin}>
|
||||
<div className={styles.inputRG__wrapper}>
|
||||
<label className={styles.labelform}> Choose your Username</label>
|
||||
<FormItem hasFeedback>{getFieldDecorator('rgUsername', { rules: [{ required: true }] })(
|
||||
<Input type="text" prefix={<Icon type="user" style={{ color: 'rgba(0,0,0,.25)' }} />} placeholder="Username" onChange={(text) => { this.handleRGUsername(text) }} />
|
||||
)}
|
||||
</FormItem>
|
||||
</div>
|
||||
<div className={styles.inputRG__wrapper}>
|
||||
<label className={styles.labelform}> Fill with your email</label>
|
||||
<FormItem hasFeedback>{getFieldDecorator('rgEmail', { rules: [{ required: true }] })(
|
||||
<Input type="text" prefix={<Icon type="link" style={{ color: 'rgba(0,0,0,.25)' }} />} placeholder="Email" onChange={(text) => { this.handleRGEmail(text) }} />
|
||||
)}
|
||||
</FormItem>
|
||||
</div>
|
||||
<div className={styles.inputRG__wrapper}>
|
||||
<label className={styles.labelform}> Fill with your password</label>
|
||||
<FormItem hasFeedback>{getFieldDecorator('rgPassword', { rules: [{ required: true }] })(
|
||||
<Input type="password" prefix={<Icon type="key" style={{ color: 'rgba(0,0,0,.25)' }} />} placeholder="Password" onChange={(text) => { this.handleRGPassword(text) }} />
|
||||
)}
|
||||
</FormItem>
|
||||
</div>
|
||||
<div className={styles.inputRG__wrapper}>
|
||||
</div>
|
||||
<div className={styles.TOSAccept}><span><span style={{ color: 'red', fontSize: '17px' }}>*</span> Clicking the register button you accept our <a href="#">terms and conditions</a></span> </div>
|
||||
<a className={styles.buttonlp} id="register" onClick={this.getRegister}>Register</a>
|
||||
<div className={styles.spinner__wrapper} id="loadingRGspn">
|
||||
<div style={{ position: 'absolute', marginLeft: '86%', marginTop: '-65%' }}><Icon type="loading" style={{ fontSize: 24 }} spin /></div>
|
||||
<div>
|
||||
<div><Icon style={{ fontSize: '160px', margin: '30px', color: '#5B2A86' }} type="smile" /></div>
|
||||
<h6 className={styles.h6lp} style={{ textAlign: 'center' }}>Ok thanks, wait a minute...</h6>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
</main>
|
||||
</Drawer>
|
||||
|
||||
{/* FORGOTTEN PASSWORD SECTION */}
|
||||
<Drawer width={420} closable={true} onClose={this.cancelRecoverPassword} visible={this.state.ForggotPasswordVisible}>
|
||||
<main className={styles.mainlp}>
|
||||
<section className={styles.forms}>
|
||||
<h6 className={styles.h6lp}>YulioID™</h6>
|
||||
<h1 className={styles.h1lp}>Forgotten Password!</h1>
|
||||
<h3>To recover your account enter the email used to register</h3>
|
||||
<form className={styles.formlogin}>
|
||||
<div className={styles.input__wrapper}>
|
||||
<label className={styles.labelform}><Icon type="mail" style={{ fontSize: '15px' }} /> Email</label>
|
||||
<FormItem hasFeedback>{getFieldDecorator('Email', { rules: [{ required: true }] })(
|
||||
<input className={styles.inputform} type="text" placeholder="myaccount@example.com" onChange={(text) => { this.handleFPEmail(text) }} /> )}
|
||||
</FormItem>
|
||||
</div>
|
||||
{/* <div style={{ margin: 'auto' }}><a className={styles.buttonlp} id="login" onClick={this.RecoverPassword(this.state.FGEmail)}>Recover</a></div> */}
|
||||
<div className={styles.spinner__wrapper} id="loadingspn">
|
||||
<div><Icon type="loading" style={{ fontSize: 24, margin: '13px' }} spin /></div>
|
||||
<div>
|
||||
<br /><br /><br />
|
||||
<div style={{ margin: 'auto' }}><h6 className={styles.h6lp} style={{ textAlign: 'center', marginTop: '15%' }}>Wait a sec...</h6></div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
</main>
|
||||
</Drawer>
|
||||
|
||||
{/* NOTF */}
|
||||
<Drawer width={320} closable={false} visible={this.state.NOTFdrawer} >
|
||||
<div style={{ textAlign: 'center', color: 'orange' }} ><Icon type="warning" style={{ fontSize: '230px' }} />
|
||||
<h2 className={styles.h2lp}> {this.state.FailArray} </h2>
|
||||
<h4 className={styles.apierrort}> {MensageException} </h4> <hr />
|
||||
<div id="details-collapse" style={{ textAlign: 'center' }}>
|
||||
<Collapse bordered={false} defaultActiveKey={['0']} expandIcon={({ isActive }) => <Icon type="caret-right" rotate={isActive ? 90 : 0} />}>
|
||||
<Panel header="Details" key="1" style={{ borderRadius: 4, marginBottom: 24, border: 0, overflow: 'hidden', }}>
|
||||
<Icon type="exception" />
|
||||
<h6>STATUS HANDLER => {this.state.ErrorType} </h6>
|
||||
<h6>EXCEPTION => {this.state.api_response} </h6>
|
||||
<h6>EXCEPTION MENSAGE => {MensageException}</h6>
|
||||
<h6><strong>ID {ExceptionID}</strong></h6>
|
||||
</Panel>
|
||||
</Collapse>
|
||||
<hr /><Button type="danger" onClick={this.closeNOTF}>TRY AGAIN</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Drawer>
|
||||
|
||||
|
||||
{/* SOTF */}
|
||||
<Drawer width={320} closable={false} visible={this.state.SOTFdrawer}>
|
||||
<div style={{ textAlign: 'center', color: '#4BB543' }} ><Icon type="check" style={{ fontSize: '200px' }} />
|
||||
<h2 className={styles.h2lp} style={{ color: '#4BB543' }} > Success </h2>
|
||||
<h4>Please wait while process your data ...</h4>
|
||||
</div>
|
||||
</Drawer>
|
||||
{/* RGSOTF */}
|
||||
<Drawer width={320} closable={false} visible={this.state.RGSOTFdrawer}>
|
||||
<div style={{ textAlign: 'center', color: 'green' }} >
|
||||
<Icon type="check" style={{ fontSize: '200px' }} />
|
||||
<h2 className={styles.h2lp} style={{ color: 'green' }} > Registered </h2>
|
||||
<h4 className={styles.apierrort}> Welcome to Dashboard, you will start discovering now</h4>
|
||||
<h4>Please check your new data while we are process you ...</h4>
|
||||
</div>
|
||||
</Drawer>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
YulioID.propTypes = {
|
||||
form: PropTypes.object,
|
||||
dispatch: PropTypes.func,
|
||||
loading: PropTypes.object,
|
||||
include: PropTypes.object,
|
||||
}
|
||||
|
||||
export default YulioID
|
29
src/components/YulioID/legacy/model.js
Normal file
29
src/components/YulioID/legacy/model.js
Normal file
@ -0,0 +1,29 @@
|
||||
import { router, pathMatchRegexp } from 'utils'
|
||||
import api from 'api'
|
||||
|
||||
const { legacyloginUser } = api
|
||||
|
||||
export default {
|
||||
namespace: 'login',
|
||||
|
||||
state: {},
|
||||
|
||||
effects: {
|
||||
*login({ payload }, { put, call, select }) {
|
||||
const data = yield call(legacyloginUser, payload)
|
||||
const { locationQuery } = yield select(_ => _.app)
|
||||
if (data.success) {
|
||||
const { from } = locationQuery
|
||||
yield put({ type: 'app/query' })
|
||||
if (!pathMatchRegexp('/login', from)) {
|
||||
if (from === '/') router.push('/dashboard')
|
||||
else router.push(from)
|
||||
} else {
|
||||
router.push('/dashboard')
|
||||
}
|
||||
} else {
|
||||
throw data
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
431
src/components/YulioID/legacy/ycore_sdcp.js
Normal file
431
src/components/YulioID/legacy/ycore_sdcp.js
Normal file
@ -0,0 +1,431 @@
|
||||
//****************************************|
|
||||
//**** yCore SDCP v1.6 *****|
|
||||
//****************************************|
|
||||
//
|
||||
// @ Licensed by RageStudio(c) 2019
|
||||
// @ Build 03102019EU21700 F/WIAPIS
|
||||
// @ https://api.ragestudio.net/RS-YIBTP
|
||||
//
|
||||
//****************************************|
|
||||
|
||||
import React, { PureComponent } from 'react'
|
||||
import { Form, Icon, message, notification } from 'antd'
|
||||
import { UIFxPY, UIFxList, DevOptions } from 'ycoreLegacy';
|
||||
import { endpoints } from 'ycoreLegacy';
|
||||
import $ from 'jquery';
|
||||
|
||||
import Cookies from 'universal-cookie';
|
||||
import Cryptr from 'cryptr';
|
||||
|
||||
const cookies = new Cookies();
|
||||
|
||||
const FormItem = Form.Item
|
||||
|
||||
export class SDCP extends PureComponent {
|
||||
constructor() {
|
||||
super()
|
||||
this.state = {
|
||||
// Arrays
|
||||
ErrorType: '',
|
||||
FailArray: '',
|
||||
username: '',
|
||||
password: '',
|
||||
server_key: '',
|
||||
access_token: '',
|
||||
user_data: [],
|
||||
ExceptionID: '',
|
||||
EXCPMS: '',
|
||||
CompleteFORM: '',
|
||||
TSDCP: '',
|
||||
user_id: '',
|
||||
api_response: {},
|
||||
api_response_ud: [],
|
||||
RGUsername: '',
|
||||
RGEmail: '',
|
||||
RGPassword: '',
|
||||
RGGender: '',
|
||||
}
|
||||
this.getAuth = this.getAuth.bind(this);
|
||||
this.getRegister = this.getRegister.bind(this);
|
||||
this.getUserData = this.getUserData.bind(this);
|
||||
this.initRegister = this.initRegister.bind(this);
|
||||
this.initFPassword = this.initFPassword.bind(this);
|
||||
this.cancelRegister = this.cancelRegister.bind(this);
|
||||
this.cancelRecoverPassword = this.cancelRecoverPassword.bind(this);
|
||||
this.closeNOTF = this.closeNOTF.bind(this);
|
||||
this.closeSOTF = this.closeSOTF.bind(this);
|
||||
this.closeRGSOTF = this.closeSOTF.bind(this);
|
||||
this.processSuccess = this.processSuccess.bind(this);
|
||||
this.processRGSuccess = this.processSuccess.bind(this);
|
||||
this.processJSON = this.processJSON.bind(this);
|
||||
this.processRGJSON = this.processJSON.bind(this);
|
||||
}
|
||||
|
||||
|
||||
initRegister(inputIO) {
|
||||
var messageListener = message.loading('Initialising YulioID Service..', 2.5)
|
||||
{ messageListener }
|
||||
if (DevOptions.DisableRegister == false) {
|
||||
this.setState({ registerVisible: true })
|
||||
}
|
||||
else {
|
||||
messageListener.then(() => message.error('Error trying to connect to YulioID services', 2.5))
|
||||
}
|
||||
}
|
||||
|
||||
initFPassword(inputIO) {
|
||||
var messageListener = message.loading('Initialising YulioID Service..', 2.5)
|
||||
{ messageListener }
|
||||
if (DevOptions.DisablePasswordRecover == false) {
|
||||
this.setState({ ForggotPasswordVisible: true })
|
||||
}
|
||||
else {
|
||||
messageListener.then(() => message.error('Error trying to connect to YulioID services', 2.5))
|
||||
}
|
||||
}
|
||||
ValidateSession(inputIO) {
|
||||
if (DevOptions.DisableLogin == false) {
|
||||
this.setState({ MainLoginVisible: true })
|
||||
}
|
||||
else {
|
||||
message.error('Error trying to connect to YulioID services', 2.5)
|
||||
$("#ErrorNotification").css({ display: 'block' })
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount(inputIO) {
|
||||
// INIT
|
||||
this.setState({ server_key: endpoints.server_key });
|
||||
this.ValidateSession();
|
||||
|
||||
const istoken = localStorage.getItem('access_token');
|
||||
const isdone = this.state.CompleteFORM;
|
||||
const getSDCP = localStorage.getItem('SDCP');
|
||||
const availableToken = cookies.get('access_token')
|
||||
if (availableToken) {
|
||||
this.resetToken()
|
||||
}
|
||||
|
||||
if (isdone == 'true') {
|
||||
setTimeout(() => { location.reload() }, 3000);
|
||||
}
|
||||
if (!getSDCP) {
|
||||
localStorage.setItem('GetNewData', true);
|
||||
}
|
||||
}
|
||||
|
||||
resetToken(inputIO) {
|
||||
let _this = this;
|
||||
const tojb1 = endpoints.removeToken;
|
||||
const tobj2 = cookies.get('access_token')
|
||||
let urlOBJ = `${tojb1}${tobj2}`;
|
||||
UIFxPY(UIFxList.notifyWarning)
|
||||
var form = new FormData();
|
||||
form.append("server_key", endpoints.server_key);
|
||||
|
||||
|
||||
var settings = {
|
||||
"url": urlOBJ,
|
||||
"method": "POST",
|
||||
"timeout": 0,
|
||||
"processData": false,
|
||||
"mimeType": "multipart/form-data",
|
||||
"contentType": false,
|
||||
"data": form
|
||||
};
|
||||
$.ajax(settings).done(function (response) {
|
||||
notification.open({
|
||||
placement: 'topLeft',
|
||||
message: 'For continue your request, is necessary to login with YulioID™ again',
|
||||
description:
|
||||
'LoginBridge™ report a access token expiration, and is required you for continue login again with security reasons.',
|
||||
icon: <Icon type="login" style={{ color: '#108ee9' }} />,
|
||||
});
|
||||
cookies.remove('access_token', { path: '/' })
|
||||
});
|
||||
}
|
||||
getUserData(inputIO) {
|
||||
const nonProccesContainer = this.state.api_response;
|
||||
const IdFromLRApi = JSON.parse(nonProccesContainer)['user_id'];
|
||||
const getStoragedToken = JSON.parse(nonProccesContainer)['access_token'];
|
||||
|
||||
var form2 = new FormData();
|
||||
form2.append("server_key", endpoints.server_key);
|
||||
form2.append("fetch", "user_data,email,username,avatar");
|
||||
form2.append("user_id", IdFromLRApi);
|
||||
|
||||
let _this = this;
|
||||
const yCore_GUDEP = endpoints.get_userData_endpoint;
|
||||
let urlOBJ = `${yCore_GUDEP}${getStoragedToken}`;
|
||||
|
||||
var settings2 = {
|
||||
"url": urlOBJ,
|
||||
"method": "POST",
|
||||
"timeout": 0,
|
||||
"processData": false,
|
||||
"mimeType": "multipart/form-data",
|
||||
"contentType": false,
|
||||
"data": form2
|
||||
};
|
||||
$.ajax(settings2)
|
||||
.done(function (response2) {
|
||||
_this.setState({ api_response_ud: response2 }),
|
||||
_this.processSuccess();
|
||||
})
|
||||
}
|
||||
getUserRGData(inputIO) {
|
||||
const nonProccesContainer = this.state.api_response;
|
||||
const IdFromLRApi = JSON.parse(nonProccesContainer)['user_id'];
|
||||
const getStoragedToken = JSON.parse(nonProccesContainer)['access_token'];
|
||||
var form2 = new FormData();
|
||||
form2.append("server_key", endpoints.server_key);
|
||||
form2.append("fetch", "user_data,email,username,avatar");
|
||||
form2.append("user_id", IdFromLRApi);
|
||||
let _this = this;
|
||||
const yCore_GUDEP = endpoints.get_userData_endpoint;
|
||||
let urlOBJ = `${yCore_GUDEP}${getStoragedToken}`;
|
||||
var settings2 = {
|
||||
"url": urlOBJ,
|
||||
"method": "POST",
|
||||
"timeout": 0,
|
||||
"processData": false,
|
||||
"mimeType": "multipart/form-data",
|
||||
"contentType": false,
|
||||
"data": form2
|
||||
};
|
||||
$.ajax(settings2)
|
||||
.done(function (response2) {
|
||||
_this.setState({ api_response_ud: response2 }),
|
||||
_this.processRGSuccess();
|
||||
})
|
||||
}
|
||||
|
||||
getRegister(inputIO) {
|
||||
$("#loadingRGspn").css({ opacity: 1, "z-index": 5 });
|
||||
const username = this.state.RGUsername;
|
||||
const password = this.state.RGPassword;
|
||||
const email = this.state.RGEmail;
|
||||
const confirm_password = this.state.RGPassword;
|
||||
const server_key = this.state.server_key;
|
||||
var form = new FormData();
|
||||
form.append("server_key", server_key);
|
||||
form.append("username", username);
|
||||
form.append("email", email);
|
||||
form.append("password", password);
|
||||
form.append("confirm_password", confirm_password);
|
||||
var settings = {
|
||||
"url": endpoints.register_endpoint,
|
||||
"method": "POST",
|
||||
"timeout": 0,
|
||||
"processData": false,
|
||||
"mimeType": "multipart/form-data",
|
||||
"contentType": false,
|
||||
"data": form,
|
||||
};
|
||||
let _this = this;
|
||||
$.ajax(settings)
|
||||
.done(function (response) {
|
||||
_this.setState({ api_response: response }),
|
||||
_this.processRGJSON();
|
||||
})
|
||||
.fail(function (response) {
|
||||
|
||||
_this.setState({
|
||||
FailArray: 'Server Failure',
|
||||
ErrorType: '1',
|
||||
api_response: 'Cannot catch response, Error 500',
|
||||
ExceptionID: '500',
|
||||
EXCPMS: 'Cannot catch response, Error 500',
|
||||
|
||||
}),
|
||||
$("#loadingRGspn").css({ opacity: 0, "z-index": -1 }),
|
||||
_this.triggerNOTF();
|
||||
})
|
||||
}
|
||||
|
||||
RecoverPassword(inputIO){
|
||||
const cookies = new Cookies();
|
||||
let _this = this;
|
||||
const tojb1 = endpoints.resetPassword_endpoint;
|
||||
const tobj2 = cookies.get('access_token')
|
||||
let urlOBJ = `${tojb1}${tobj2}`;
|
||||
UIFxPY(UIFxList.notifyWarning)
|
||||
var form = new FormData();
|
||||
form.append("server_key", endpoints.server_key);
|
||||
form.append("email", inputIO);
|
||||
|
||||
var settings = {
|
||||
"url": urlOBJ,
|
||||
"method": "POST",
|
||||
"timeout": 0,
|
||||
"processData": false,
|
||||
"mimeType": "multipart/form-data",
|
||||
"contentType": false,
|
||||
"data": form
|
||||
};
|
||||
$.ajax(settings).done(function (response) {
|
||||
notification.open({
|
||||
placement: 'topLeft',
|
||||
message: 'The instructions to recover your account have been sent to the email',
|
||||
description:
|
||||
'If you cant find the email, try looking for it in the spam folder or try again',
|
||||
icon: <Icon type="mail" style={{ color: '#108ee9' }} />,
|
||||
});
|
||||
console.log(response)
|
||||
});
|
||||
}
|
||||
|
||||
getAuth(inputIO) {
|
||||
$("#loadingspn").css({ opacity: 1, "z-index": 5 });
|
||||
const username = this.state.username;
|
||||
const password = this.state.password;
|
||||
const server_key = this.state.server_key;
|
||||
|
||||
var form = new FormData();
|
||||
|
||||
form.append("server_key", server_key);
|
||||
form.append("username", username);
|
||||
form.append("password", password);
|
||||
var settings = {
|
||||
"url": endpoints.auth_endpoint,
|
||||
"method": "POST",
|
||||
"timeout": 0,
|
||||
"processData": false,
|
||||
"mimeType": "multipart/form-data",
|
||||
"contentType": false,
|
||||
"data": form,
|
||||
};
|
||||
let _this = this;
|
||||
$.ajax(settings)
|
||||
.done(function (response) {
|
||||
_this.setState({ api_response: response }),
|
||||
_this.processJSON();
|
||||
})
|
||||
.fail(function (response) {
|
||||
_this.setState({
|
||||
FailArray: 'Server Failure',
|
||||
ErrorType: '1',
|
||||
api_response: 'Cannot catch response, Error 500',
|
||||
ExceptionID: '500',
|
||||
EXCPMS: 'Cannot catch response, Error 500',
|
||||
|
||||
}),
|
||||
notification.open({
|
||||
placement: 'topLeft',
|
||||
message: 'Currently our servers are having operating problems',
|
||||
description: 'Please be patient until the services become available again, try again later. We apologize for the inconveniences',
|
||||
icon: <Icon type="login" style={{ color: '#ff0f2f' }} />
|
||||
}),
|
||||
$("#loadingspn").css({ opacity: 0, "z-index": -1 }),
|
||||
_this.triggerNOTF();
|
||||
})
|
||||
}
|
||||
|
||||
processError(inputIO) {
|
||||
const nonProccesContainer = this.state.api_response;
|
||||
const stringParsed = JSON.parse(nonProccesContainer)['api_status'];
|
||||
const ExceptionMensage = JSON.parse(this.state.api_response)['errors'];
|
||||
const ExcepID = ExceptionMensage.error_id;
|
||||
const ExceptionMensagePRC = ExceptionMensage.error_text;
|
||||
if (stringParsed == '400') {
|
||||
this.triggerNOTF();
|
||||
this.setState({ FailArray: 'Bad credentials' });
|
||||
this.setState({
|
||||
ErrorType: stringParsed,
|
||||
ExceptionID: ExcepID
|
||||
});
|
||||
$("#loadingspn").css({ opacity: 0, "z-index": -1 });
|
||||
$("#loadingRGspn").css({ opacity: 0, "z-index": -1 });
|
||||
this.setState({ EXCPMS: ExceptionMensagePRC });
|
||||
}
|
||||
if (stringParsed == '404') {
|
||||
this.triggerNOTF();
|
||||
this.setState({ ErrorType: stringParsed });
|
||||
$("#loadingspn").css({ opacity: 0, "z-index": -1 });
|
||||
$("#loadingRGspn").css({ opacity: 0, "z-index": -1 });
|
||||
this.setState({ EXCPMS: ExceptionMensagePRC });
|
||||
}
|
||||
}
|
||||
|
||||
processSuccess(inputIO) {
|
||||
// CREATE SDCP PACKAGE
|
||||
const nonProccesContainer = this.state.api_response;
|
||||
const accessTokesParsed = JSON.parse(this.state.api_response)['access_token'];
|
||||
const userDataParsed = JSON.parse(this.state.api_response_ud)['user_data'];
|
||||
this.setState({ user_data: userDataParsed });
|
||||
const proccessForParse = JSON.stringify(this.state.user_data);
|
||||
const icryptr = new Cryptr(accessTokesParsed);
|
||||
const encryptedString = icryptr.encrypt(proccessForParse);
|
||||
this.setState({ access_token: accessTokesParsed, TSDCP: encryptedString });
|
||||
cookies.set('access_token', accessTokesParsed, { path: '/' });
|
||||
cookies.set('last_api_response', nonProccesContainer, { path: '/' });
|
||||
cookies.set('last_api_response_ud', (this.state.TSDCP), { path: '/' });
|
||||
localStorage.setItem('UIfx', 0.6);
|
||||
localStorage.setItem('SDCP', (this.state.TSDCP));
|
||||
const usernameST = this.state.username;
|
||||
const password = this.state.password;
|
||||
this.triggerSOTF();
|
||||
const userID = JSON.parse(proccessForParse)['user_id'];
|
||||
let avatar = JSON.parse(proccessForParse)['avatar'];
|
||||
const { dispatch } = this.props;
|
||||
let dispatchPayloadValue = { userID, usernameST, avatar, accessTokesParsed };
|
||||
setTimeout(function () { dispatch({ type: 'login/login', payload: dispatchPayloadValue }) }, 1300)
|
||||
UIFxPY(UIFxList.notifySuccess, 0.5);
|
||||
console.log('%c 🎉 Your data has been storaged in SDCP with this values 🎉 =>', 'background: orange; font-size: 16px; color: white; display: block;', dispatchPayloadValue);
|
||||
|
||||
}
|
||||
processRGSuccess(inputIO) {
|
||||
// CREATE SDCP PACKAGE
|
||||
const nonProccesContainer = this.state.api_response;
|
||||
const accessTokesParsed = JSON.parse(this.state.api_response)['access_token'];
|
||||
const userDataParsed = JSON.parse(this.state.api_response_ud)['user_data'];
|
||||
this.setState({ user_data: userDataParsed });
|
||||
const proccessForParse = JSON.stringify(this.state.user_data);
|
||||
const icryptr = new Cryptr(accessTokesParsed);
|
||||
const encryptedString = icryptr.encrypt(proccessForParse);
|
||||
this.setState({ access_token: accessTokesParsed, TSDCP: encryptedString });
|
||||
cookies.set('access_token', accessTokesParsed, { path: '/' });
|
||||
cookies.set('last_api_response', nonProccesContainer, { path: '/' });
|
||||
cookies.set('last_api_response_ud', (this.state.TSDCP), { path: '/' });
|
||||
localStorage.setItem('UIfx', 0.6);
|
||||
localStorage.setItem('SDCP', (this.state.TSDCP));
|
||||
const usernameST = this.state.RGUsername;
|
||||
this.triggerRGSOTF();
|
||||
const userID = JSON.parse(proccessForParse)['user_id'];
|
||||
const identADMINType = JSON.parse(proccessForParse)['admin'];
|
||||
const identDEVELOPERType = JSON.parse(proccessForParse)['dev'];
|
||||
let avatar = JSON.parse(proccessForParse)['avatar'];
|
||||
const { dispatch } = this.props;
|
||||
let dispatchPayloadValue = { userID, usernameST, avatar, accessTokesParsed };
|
||||
setTimeout(function () { dispatch({ type: 'login/login', payload: dispatchPayloadValue }) }, 1300)
|
||||
UIFxPY(UIFxList.notifySuccess, 0.3);
|
||||
console.log('%c 🎉 Your data has been storaged in SDCP with this values 🎉 =>', 'background: orange; font-size: 16px; color: white; display: block;', dispatchPayloadValue);
|
||||
}
|
||||
|
||||
processJSON(inputIO) {
|
||||
const nonProccesContainer = this.state.api_response;
|
||||
const stringParsed = JSON.parse(nonProccesContainer);
|
||||
const identStatus = JSON.parse(nonProccesContainer)['api_status'];
|
||||
if (DevOptions.InfiniteLogin == false) {
|
||||
if (identStatus == '400') {
|
||||
this.processError();
|
||||
}
|
||||
if (identStatus == '200') {
|
||||
this.getUserData();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
processRGJSON(inputIO) {
|
||||
const nonProccesContainer = this.state.api_response;
|
||||
const stringParsed = JSON.parse(nonProccesContainer);
|
||||
const identStatus = JSON.parse(nonProccesContainer)['api_status'];
|
||||
if (identStatus == '400') {
|
||||
$("#loadingRGspn").css({ opacity: 0, "z-index": -1 }),
|
||||
this.processError();
|
||||
}
|
||||
if (identStatus == '200') {
|
||||
this.getRGUserData();
|
||||
}
|
||||
}
|
||||
}
|
1285
src/components/YulioID/legacy/yid.scss
Normal file
1285
src/components/YulioID/legacy/yid.scss
Normal file
File diff suppressed because it is too large
Load Diff
13
src/components/index.js
Normal file
13
src/components/index.js
Normal file
@ -0,0 +1,13 @@
|
||||
import Editor from './Editor'
|
||||
import FilterItem from './FilterItem'
|
||||
import DropOption from './DropOption'
|
||||
import Loader from './Loader/Loader.js'
|
||||
import ScrollBar from './ScrollBar'
|
||||
import * as MyLayout from './Layout/index.js'
|
||||
import Page from './Page'
|
||||
import Debugger from './Debugger'
|
||||
import YulioID from './YulioID/experimental/index.js'
|
||||
import YulioAuth from './YulioAuth/index.js'
|
||||
import CoreLoader from './CoreLoader'
|
||||
|
||||
export { MyLayout, Editor, FilterItem, DropOption, Loader, Page, ScrollBar, YulioID, YulioAuth, Debugger, CoreLoader }
|
59
src/layouts/BaseLayout.js
Normal file
59
src/layouts/BaseLayout.js
Normal file
@ -0,0 +1,59 @@
|
||||
import React, { PureComponent, Fragment } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { connect } from 'dva'
|
||||
import { Helmet } from 'react-helmet'
|
||||
import { Loader } from 'components'
|
||||
import { queryLayout } from 'utils'
|
||||
import NProgress from 'nprogress'
|
||||
import config from 'config'
|
||||
import withRouter from 'umi/withRouter'
|
||||
|
||||
import PublicLayout from './PublicLayout'
|
||||
import PrimaryLayout from './PrimaryLayout'
|
||||
import SocketLayout from './SocketLayout'
|
||||
import PublicViewLayout from './PublicViewLayout'
|
||||
import './BaseLayout.less'
|
||||
|
||||
const LayoutMap = {
|
||||
socket: SocketLayout,
|
||||
primary: PrimaryLayout,
|
||||
public: PublicLayout,
|
||||
publicview: PublicViewLayout,
|
||||
}
|
||||
|
||||
@withRouter
|
||||
@connect(({ loading }) => ({ loading }))
|
||||
class BaseLayout extends PureComponent {
|
||||
previousPath = ''
|
||||
|
||||
render() {
|
||||
const { loading, children, location } = this.props
|
||||
const Container = LayoutMap[queryLayout(config.layouts, location.pathname)]
|
||||
|
||||
const currentPath = location.pathname + location.search
|
||||
if (currentPath !== this.previousPath) {
|
||||
NProgress.start()
|
||||
}
|
||||
|
||||
if (!loading.global) {
|
||||
NProgress.done()
|
||||
this.previousPath = currentPath
|
||||
}
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<Helmet>
|
||||
<title>{config.siteName}</title>
|
||||
</Helmet>
|
||||
<Loader fullScreen spinning={loading.effects['app/query']} />
|
||||
<Container>{children}</Container>
|
||||
</Fragment>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
BaseLayout.propTypes = {
|
||||
loading: PropTypes.object,
|
||||
}
|
||||
|
||||
export default BaseLayout
|
75
src/layouts/BaseLayout.less
Normal file
75
src/layouts/BaseLayout.less
Normal file
@ -0,0 +1,75 @@
|
||||
@import '~themes/vars.less';
|
||||
@import '~themes/index.less';
|
||||
|
||||
:global {
|
||||
|
||||
#nprogress {
|
||||
pointer-events: none;
|
||||
|
||||
.bar {
|
||||
background: @primary-color;
|
||||
position: fixed;
|
||||
z-index: 2048;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
width: 100%;
|
||||
height: 2px;
|
||||
}
|
||||
|
||||
.peg {
|
||||
display: block;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
width: 100px;
|
||||
height: 100%;
|
||||
box-shadow: 0 0 10px @primary-color, 0 0 5px @primary-color;
|
||||
opacity: 1;
|
||||
transform: rotate(3deg) translate(0, -4px);
|
||||
}
|
||||
|
||||
.spinner {
|
||||
display: block;
|
||||
position: fixed;
|
||||
z-index: 1031;
|
||||
top: 15px;
|
||||
right: 15px;
|
||||
}
|
||||
|
||||
.spinner-icon {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
box-sizing: border-box;
|
||||
border: solid 2px transparent;
|
||||
border-top-color: @primary-color;
|
||||
border-left-color: @primary-color;
|
||||
border-radius: 50%;
|
||||
|
||||
:local {
|
||||
animation: nprogress-spinner 400ms linear infinite;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.nprogress-custom-parent {
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
|
||||
#nprogress {
|
||||
.bar,
|
||||
.spinner {
|
||||
position: absolute;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes nprogress-spinner {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
188
src/layouts/PrimaryLayout.js
Normal file
188
src/layouts/PrimaryLayout.js
Normal file
@ -0,0 +1,188 @@
|
||||
/* global window */
|
||||
/* global document */
|
||||
import React, { PureComponent, Fragment } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { RefreshONCE, LogoutCall, SDCP } from 'ycore'
|
||||
import withRouter from 'umi/withRouter'
|
||||
import { connect } from 'dva'
|
||||
import { MyLayout } from 'components'
|
||||
import { Layout, Drawer, Result, Button, Checkbox } from 'antd'
|
||||
import { enquireScreen, unenquireScreen } from 'enquire-js'
|
||||
import { config, pathMatchRegexp, langFromPath } from 'utils'
|
||||
import store from 'store';
|
||||
import classNames from 'classnames'
|
||||
import Error from '../pages/404'
|
||||
import styles from './PrimaryLayout.less'
|
||||
|
||||
const { Content } = Layout
|
||||
const { Header, L_Sider, R_Sider, Control } = MyLayout
|
||||
|
||||
@withRouter
|
||||
@connect(({ app, loading }) => ({ app, loading }))
|
||||
class PrimaryLayout extends PureComponent {
|
||||
constructor(props){
|
||||
super(props)
|
||||
this.state = {
|
||||
isMobile: false,
|
||||
resbypass: store.get('resbypass') || false,
|
||||
RemByPass: false,
|
||||
BarControls: [],
|
||||
}
|
||||
this.ResByPassHandler = this.ResByPassHandler.bind(this);
|
||||
}
|
||||
setControls(e){
|
||||
this.setState({BarControls: e})
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.enquireHandler = enquireScreen(mobile => {
|
||||
const { isMobile } = this.state
|
||||
if (isMobile !== mobile) {
|
||||
this.setState({
|
||||
isMobile: mobile,
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
unenquireScreen(this.enquireHandler)
|
||||
}
|
||||
|
||||
onCollapseChange = collapsed => {
|
||||
this.props.dispatch({
|
||||
type: 'app/handleCollapseChange',
|
||||
payload: collapsed,
|
||||
})
|
||||
}
|
||||
|
||||
ResByPassHandler() {
|
||||
const {RemByPass} = this.state;
|
||||
if (RemByPass == true){
|
||||
this.setState({resbypass: true})
|
||||
store.set('resbypass', true)
|
||||
return
|
||||
}
|
||||
this.setState({resbypass: true})
|
||||
}
|
||||
|
||||
isDarkMode = () => {
|
||||
const {app} = this.props
|
||||
const { theme } = app
|
||||
if (theme == "light") {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
render() {
|
||||
const { app, location, dispatch, children } = this.props
|
||||
const { theme, routeList, collapsed, notifications } = app
|
||||
const { isMobile, resbypass, rememberbypass } = this.state
|
||||
const { onCollapseChange } = this
|
||||
// Localized route name.
|
||||
const lang = langFromPath(location.pathname)
|
||||
const newRouteList =
|
||||
lang !== 'en'
|
||||
? routeList.map(item => {
|
||||
const { name, ...other } = item
|
||||
return {
|
||||
...other,
|
||||
name: (item[lang] || {}).name || name,
|
||||
}
|
||||
})
|
||||
: routeList
|
||||
|
||||
// Find a route that matches the pathname.
|
||||
const currentRoute = newRouteList.find(
|
||||
_ => _.route && pathMatchRegexp(_.route, location.pathname)
|
||||
)
|
||||
|
||||
// MenuParentId is equal to -1 is not a available menu.
|
||||
const menus = newRouteList.filter(_ => _.menuParentId !== '-1')
|
||||
|
||||
const headerProps = {
|
||||
menus,
|
||||
theme,
|
||||
collapsed,
|
||||
newRouteList,
|
||||
notifications,
|
||||
onCollapseChange,
|
||||
onThemeChange(theme) {
|
||||
dispatch({
|
||||
type: 'app/handleThemeChange',
|
||||
payload: theme,
|
||||
})
|
||||
},
|
||||
fixed: config.fixedHeader,
|
||||
onAllNotificationsRead() {
|
||||
dispatch({ type: 'app/allNotificationsRead' })
|
||||
},
|
||||
|
||||
}
|
||||
|
||||
const LeftSiderProps = {
|
||||
theme,
|
||||
menus,
|
||||
isMobile,
|
||||
collapsed,
|
||||
onCollapseChange,
|
||||
}
|
||||
const RightSiderProps = {
|
||||
theme,
|
||||
collapsed,
|
||||
onCollapseChange,
|
||||
onThemeChange(theme) {
|
||||
dispatch({
|
||||
type: 'app/handleThemeChange',
|
||||
payload: theme,
|
||||
})
|
||||
},
|
||||
}
|
||||
|
||||
const MobileWarning = () =>{
|
||||
if (resbypass == false) {
|
||||
if (isMobile == true) {
|
||||
return(
|
||||
<div className={styles.mobilewarning}>
|
||||
<Result status="warning" title="Low resolution warning"
|
||||
extra={ <div style={{ color: "white" }}><h3 style={{ color: "white" }}>This version of the application is not fully compatible with the resolution of this screen, a higher resolution is recommended for an optimal experience</h3><span>Please choose an option to continue</span><br /><br /><br /><Checkbox onChange={this.setState({ RemByPass: true })}>Don't Show this again</Checkbox><br /><br /><br /><Button type="dashed" onClick={this.ResByPassHandler}>Continue</Button></div> }/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<MobileWarning />
|
||||
<div className={styles.BarControlWrapper}><Control /></div>
|
||||
<Layout className={this.isDarkMode()? styles.container_dark : styles.container_light}>
|
||||
<L_Sider {...LeftSiderProps} />
|
||||
<div className={styles.container}>
|
||||
<div style={{ paddingTop: config.fixedHeader ? 72 : 0 }} id="primaryLayout" >
|
||||
<Header {...headerProps} />
|
||||
<Content className={styles.content}>
|
||||
{children}
|
||||
</Content>
|
||||
</div>
|
||||
</div>
|
||||
<R_Sider {...RightSiderProps}/>
|
||||
</Layout>
|
||||
</Fragment>
|
||||
)
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
PrimaryLayout.propTypes = {
|
||||
children: PropTypes.element.isRequired,
|
||||
location: PropTypes.object,
|
||||
dispatch: PropTypes.func,
|
||||
app: PropTypes.object,
|
||||
loading: PropTypes.object,
|
||||
}
|
||||
|
||||
export default PrimaryLayout
|
129
src/layouts/PrimaryLayout.less
Normal file
129
src/layouts/PrimaryLayout.less
Normal file
@ -0,0 +1,129 @@
|
||||
@import '~themes/vars.less';
|
||||
|
||||
.mobilewarning{
|
||||
background-color: rgba(0, 0, 0, 0.975);
|
||||
color: white;
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
z-index: 100000;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
:global {
|
||||
.ant-result-title {
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 24px;
|
||||
height: 100vh;
|
||||
width: 100%;
|
||||
|
||||
}
|
||||
.container_light {
|
||||
background-color: #fff;
|
||||
transition: background-color 200ms linear;
|
||||
}
|
||||
// TODO: Complete full dark theme
|
||||
.container_dark {
|
||||
background-color: @DarkMode-backgroud_container;
|
||||
color: @DarkMode-color_container;
|
||||
transition: background-color 200ms linear;
|
||||
:global {
|
||||
h1{
|
||||
color: @DarkMode-color_container;
|
||||
}
|
||||
h2{
|
||||
color: @DarkMode-color_container;
|
||||
}
|
||||
h3{
|
||||
color: @DarkMode-color_container;
|
||||
}
|
||||
h4{
|
||||
color: @DarkMode-color_container;
|
||||
}
|
||||
h5{
|
||||
color: @DarkMode-color_container;
|
||||
}
|
||||
h6{
|
||||
color: @DarkMode-color_container;
|
||||
}
|
||||
p{
|
||||
color: @DarkMode-color_container;
|
||||
}
|
||||
span{
|
||||
color: @DarkMode-color_container;
|
||||
}
|
||||
pre{
|
||||
color: @DarkMode-color_container;
|
||||
}
|
||||
.ant-pro-page-header-wrap-page-header-warp {
|
||||
color: @DarkMode-color_container;
|
||||
background-color: @DarkMode-backgroud_container;
|
||||
transition: background-color 200ms linear;
|
||||
}
|
||||
transition: background-color 200ms linear;
|
||||
}
|
||||
}
|
||||
|
||||
.sider {
|
||||
:global {
|
||||
.ant-layout-sider{
|
||||
background: #2d2d2d;
|
||||
}
|
||||
.ant-layout-sider-dark {
|
||||
background-color: #2d2d2d;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.ant-menu-dark {
|
||||
background-color: #2d2d2d;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.ant-layout-sider-dark .ant-layout-sider-children {
|
||||
background-color: #2d2d2d;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.ant-layout-sider-children {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
}
|
||||
}
|
||||
}
|
||||
.container{
|
||||
width: 100vh;
|
||||
flex: 1;
|
||||
overflow-x: hidden;
|
||||
height: 100vh;
|
||||
bottom: 0;
|
||||
}
|
||||
.BarControlWrapper{
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
z-index: 30;
|
||||
}
|
||||
@media (max-width: 767px) {
|
||||
.content {
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.container_light {
|
||||
height: 100vh;
|
||||
flex: 1;
|
||||
|
||||
}
|
||||
.container_dark {
|
||||
height: 100vh;
|
||||
flex: 1;
|
||||
|
||||
}
|
||||
}
|
3
src/layouts/PublicLayout.js
Normal file
3
src/layouts/PublicLayout.js
Normal file
@ -0,0 +1,3 @@
|
||||
export default ({ children }) => {
|
||||
return children
|
||||
}
|
72
src/layouts/index.js
Normal file
72
src/layouts/index.js
Normal file
@ -0,0 +1,72 @@
|
||||
import React, { Component } from 'react'
|
||||
import withRouter from 'umi/withRouter'
|
||||
import { ConfigProvider } from 'antd'
|
||||
import { I18nProvider } from '@lingui/react'
|
||||
import { langFromPath, defaultLanguage } from 'utils'
|
||||
import en_US from 'antd/lib/locale-provider/en_US'
|
||||
import BaseLayout from './BaseLayout'
|
||||
|
||||
const languages = {
|
||||
en: en_US,
|
||||
}
|
||||
|
||||
@withRouter
|
||||
class Layout extends Component {
|
||||
state = {
|
||||
catalogs: {},
|
||||
}
|
||||
|
||||
language = defaultLanguage
|
||||
|
||||
componentDidMount() {
|
||||
const language = langFromPath(this.props.location.pathname)
|
||||
this.language = language
|
||||
this.loadCatalog(language)
|
||||
}
|
||||
|
||||
shouldComponentUpdate(nextProps, nextState) {
|
||||
const language = langFromPath(nextProps.location.pathname)
|
||||
const preLanguage = this.language
|
||||
const { catalogs } = nextState
|
||||
|
||||
if (preLanguage !== language && !catalogs[language]) {
|
||||
this.loadCatalog(language)
|
||||
this.language = language
|
||||
return false
|
||||
}
|
||||
this.language = language
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
loadCatalog = async language => {
|
||||
const catalog = await import(/* webpackMode: "lazy", webpackChunkName: "i18n-[index]" */
|
||||
`@lingui/loader!../locales/${language}/messages.json`)
|
||||
|
||||
this.setState(state => ({
|
||||
catalogs: {
|
||||
...state.catalogs,
|
||||
[language]: catalog,
|
||||
},
|
||||
}))
|
||||
}
|
||||
|
||||
render() {
|
||||
const { location, children } = this.props
|
||||
const { catalogs } = this.state
|
||||
|
||||
let language = langFromPath(location.pathname)
|
||||
// If the language pack is not loaded or is loading, use the default language
|
||||
if (!catalogs[language]) language = defaultLanguage
|
||||
|
||||
return (
|
||||
<ConfigProvider locale={languages[language]}>
|
||||
<I18nProvider language={language} catalogs={catalogs}>
|
||||
<BaseLayout>{children}</BaseLayout>
|
||||
</I18nProvider>
|
||||
</ConfigProvider>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default Layout
|
132
src/models/app.js
Normal file
132
src/models/app.js
Normal file
@ -0,0 +1,132 @@
|
||||
|
||||
/* global window */
|
||||
import { router } from 'utils'
|
||||
import { stringify } from 'qs'
|
||||
import store from 'store'
|
||||
import { queryLayout, pathMatchRegexp } from 'utils'
|
||||
import { CANCEL_REQUEST_MESSAGE } from 'utils/constant'
|
||||
import api from 'api'
|
||||
import config from 'config'
|
||||
import Cookies from 'js-cookie'
|
||||
import * as ycore from 'ycore'
|
||||
import jwt from 'jsonwebtoken'
|
||||
const { queryRouteList, logoutUser, queryUserInfo } = api
|
||||
|
||||
export default {
|
||||
namespace: 'app',
|
||||
state: {
|
||||
routeList: [
|
||||
{
|
||||
id: '1',
|
||||
icon: 'home',
|
||||
name: 'Main',
|
||||
router: '/Main',
|
||||
},
|
||||
],
|
||||
locationPathname: '',
|
||||
AppSettings: store.get('app_settings') || config.defaultSettings,
|
||||
locationQuery: {},
|
||||
theme: store.get('theme') || 'light',
|
||||
collapsed: store.get('collapsed') || true,
|
||||
notifications: [
|
||||
{
|
||||
title: 'Hey! Test notification',
|
||||
date: new Date(Date.now() - 50000000),
|
||||
},
|
||||
],
|
||||
},
|
||||
subscriptions: {
|
||||
setupHistory({ dispatch, history }) {
|
||||
history.listen(location => {
|
||||
dispatch({
|
||||
type: 'updateState',
|
||||
payload: {
|
||||
locationPathname: location.pathname,
|
||||
locationQuery: location.query,
|
||||
},
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
setupRequestCancel({ history }) {
|
||||
history.listen(() => {
|
||||
const { cancelRequest = new Map() } = window
|
||||
cancelRequest.forEach((value, key) => {
|
||||
if (value.pathname !== window.location.pathname) {
|
||||
value.cancel(CANCEL_REQUEST_MESSAGE)
|
||||
cancelRequest.delete(key)
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
setup({ dispatch }) {
|
||||
dispatch({ type: 'query' })
|
||||
},
|
||||
},
|
||||
effects: {
|
||||
*query({payload}, { call, put, select }) {
|
||||
const { locationPathname } = yield select(_ => _.app)
|
||||
const { list } = yield call(queryRouteList)
|
||||
let routeList = list
|
||||
yield put({type: 'updateState', payload: { routeList: list }, })
|
||||
|
||||
const valid = ycore.ValidLoginSession();
|
||||
const validBackup = ycore.ValidBackup();
|
||||
if ( valid == true) {
|
||||
if (pathMatchRegexp(['/', '/login'], window.location.pathname)) {
|
||||
router.push({pathname: '/main',})
|
||||
ycore.RefreshONCE()
|
||||
}else{
|
||||
ycore.MakeBackup()
|
||||
ycore.UpdateSDCP()
|
||||
}
|
||||
} else if (queryLayout(config.layouts, locationPathname) !== 'public') {
|
||||
if (validBackup == true) {
|
||||
ycore.LogoutCall()
|
||||
return
|
||||
}else if (ycore.GetUserToken == false){
|
||||
notification.open({
|
||||
placement: 'topLeft',
|
||||
message: 'Unexpectedly failed logout in YulioID™ ',
|
||||
description: 'It seems that your token has been removed unexpectedly and could not log out from YulioID ',
|
||||
icon: <Icon type="warning" style={{ color: 'orange' }} />
|
||||
})
|
||||
return
|
||||
}
|
||||
router.push({pathname: '/login',})
|
||||
}
|
||||
},
|
||||
|
||||
*signOut({ payload }, { call, put }) {
|
||||
const data = yield call(logoutUser)
|
||||
if (data.success) {
|
||||
sessionStorage.clear()
|
||||
yield put({ type: 'query' })
|
||||
} else {
|
||||
throw data
|
||||
}
|
||||
},
|
||||
},
|
||||
reducers: {
|
||||
updateState(state, { payload }) {
|
||||
return {
|
||||
...state,
|
||||
...payload,
|
||||
}
|
||||
},
|
||||
|
||||
handleThemeChange(state, { payload }) {
|
||||
store.set('theme', payload)
|
||||
state.theme = payload
|
||||
},
|
||||
|
||||
handleCollapseChange(state, { payload }) {
|
||||
store.set('collapsed', payload)
|
||||
state.collapsed = payload
|
||||
},
|
||||
|
||||
allNotificationsRead(state) {
|
||||
state.notifications = []
|
||||
},
|
||||
},
|
||||
}
|
16
src/pages/404.js
Normal file
16
src/pages/404.js
Normal file
@ -0,0 +1,16 @@
|
||||
import React from 'react'
|
||||
import { Icon } from 'antd'
|
||||
import { Page } from 'components'
|
||||
import styles from './404.less'
|
||||
|
||||
const Error = () => (
|
||||
<Page inner>
|
||||
<div className={styles.error}>
|
||||
<Icon type="api" />
|
||||
<h1>OBA BLYAT</h1>
|
||||
<p><strong>ERROR 404</strong></p>
|
||||
</div>
|
||||
</Page>
|
||||
)
|
||||
|
||||
export default Error
|
50
src/pages/404.less
Normal file
50
src/pages/404.less
Normal file
@ -0,0 +1,50 @@
|
||||
/* devanagari */
|
||||
@font-face {
|
||||
font-family: 'Poppins';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: local('Poppins Regular'), local('Poppins-Regular'), url(https://fonts.gstatic.com/s/poppins/v6/pxiEyp8kv8JHgFVrJJbecmNE.woff2) format('woff2');
|
||||
unicode-range: U+0900-097F, U+1CD0-1CF6, U+1CF8-1CF9, U+200C-200D, U+20A8, U+20B9, U+25CC, U+A830-A839, U+A8E0-A8FB;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'Poppins';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: local('Poppins Regular'), local('Poppins-Regular'), url(https://fonts.gstatic.com/s/poppins/v6/pxiEyp8kv8JHgFVrJJnecmNE.woff2) format('woff2');
|
||||
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Poppins';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: local('Poppins Regular'), local('Poppins-Regular'), url(https://fonts.gstatic.com/s/poppins/v6/pxiEyp8kv8JHgFVrJJfecg.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
.error {
|
||||
color: black;
|
||||
text-align: center;
|
||||
position: absolute;
|
||||
top: 30%;
|
||||
margin-top: -50px;
|
||||
left: 50%;
|
||||
margin-left: -100px;
|
||||
width: 200px;
|
||||
|
||||
:global .anticon {
|
||||
font-size: 48px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-family: 'Poppins', sans-serif;
|
||||
|
||||
}
|
||||
p {
|
||||
font-family: 'Poppins', sans-serif;
|
||||
}
|
||||
}
|
13
src/pages/index.js
Normal file
13
src/pages/index.js
Normal file
@ -0,0 +1,13 @@
|
||||
import React, { PureComponent } from 'react'
|
||||
import Redirect from 'umi/redirect'
|
||||
import { withI18n } from '@lingui/react'
|
||||
|
||||
@withI18n()
|
||||
class Index extends PureComponent {
|
||||
render() {
|
||||
const { i18n } = this.props
|
||||
return <Redirect to={i18n.t`/dashboard`} />
|
||||
}
|
||||
}
|
||||
|
||||
export default Index
|
40
src/pages/login/index.js
Normal file
40
src/pages/login/index.js
Normal file
@ -0,0 +1,40 @@
|
||||
import React, { Component } from 'react';
|
||||
import { getRandomBG } from 'ycore';
|
||||
import { YulioID } from 'components';
|
||||
let imgRend;
|
||||
|
||||
class Login extends Component {
|
||||
constructor(props){
|
||||
super(props)
|
||||
this.state = {
|
||||
// Setting default method
|
||||
type: 'stable'
|
||||
}
|
||||
this.changeMethod = this.changeMethod.bind(this);
|
||||
}
|
||||
|
||||
componentDidMount(){
|
||||
// INIT
|
||||
var arrayBg = new Array();
|
||||
arrayBg[0] = "bg-1-an";
|
||||
arrayBg[1] = "bg-2-an";
|
||||
arrayBg[2] = "bg-3-an";
|
||||
arrayBg[3] = "bg-4-an";
|
||||
arrayBg[4] = "bg-5-an";
|
||||
arrayBg[5] = "bg-6-an";
|
||||
arrayBg[6] = "bg-1-an";
|
||||
imgRend = getRandomBG(arrayBg)
|
||||
}
|
||||
|
||||
changeMethod() {
|
||||
this.setState({type: 'stable'})
|
||||
}
|
||||
render() {
|
||||
const { type } = this.state;
|
||||
return (
|
||||
<YulioID include={<div>Using stable</div>} />
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default Login
|
27
src/pages/login/model.js
Normal file
27
src/pages/login/model.js
Normal file
@ -0,0 +1,27 @@
|
||||
import { router, pathMatchRegexp } from 'utils'
|
||||
import api from 'api'
|
||||
|
||||
const { loginUser } = api
|
||||
|
||||
export default {
|
||||
namespace: 'login',
|
||||
state: {},
|
||||
effects: {
|
||||
*login({ payload }, { put, call, select }) {
|
||||
const data = yield call(loginUser, payload)
|
||||
const { locationQuery } = yield select(_ => _.app)
|
||||
if (data.success == true) {
|
||||
const { from } = locationQuery
|
||||
yield put({ type: 'app/query' })
|
||||
if (!pathMatchRegexp('/login', from)) {
|
||||
if (from === '/') router.push('/dashboard')
|
||||
else router.push(from)
|
||||
} else {
|
||||
router.push('/dashboard')
|
||||
}
|
||||
} else {
|
||||
throw data
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
18
src/pages/main/index.tsx
Normal file
18
src/pages/main/index.tsx
Normal file
@ -0,0 +1,18 @@
|
||||
import React from 'react'
|
||||
import * as ycore from 'ycore'
|
||||
import * as antd from 'antd'
|
||||
|
||||
|
||||
|
||||
class Main extends React.Component{
|
||||
render(){
|
||||
return (
|
||||
<div>
|
||||
<h1>
|
||||
Sigueme pe
|
||||
</h1>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
export default Main;
|
6
src/services/api.js
Normal file
6
src/services/api.js
Normal file
@ -0,0 +1,6 @@
|
||||
export default {
|
||||
queryRouteList: '/routes',
|
||||
|
||||
loginUser: 'POST /user/login',
|
||||
logoutUser: '/user/logout',
|
||||
}
|
38
src/services/index.js
Normal file
38
src/services/index.js
Normal file
@ -0,0 +1,38 @@
|
||||
import request from 'utils/request';
|
||||
import { apiPrefix } from 'config';
|
||||
|
||||
import api from './api';
|
||||
|
||||
const gen = params => {
|
||||
let url = apiPrefix + params
|
||||
let method = 'GET'
|
||||
|
||||
const paramsArray = params.split(' ')
|
||||
if (paramsArray.length === 2) {
|
||||
method = paramsArray[0];
|
||||
url = apiPrefix + paramsArray[1];
|
||||
}
|
||||
|
||||
return function(data) {
|
||||
return request({
|
||||
url,
|
||||
data,
|
||||
method,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const APIFunction = {}
|
||||
for (const key in api) {
|
||||
APIFunction[key] = gen(api[key]);
|
||||
}
|
||||
|
||||
APIFunction.queryWeather = params => {
|
||||
params.key = 'i7sau1babuzwhycn'
|
||||
return request({
|
||||
url: `${apiPrefix}/weather/now.json`,
|
||||
data: params,
|
||||
})
|
||||
}
|
||||
|
||||
export default APIFunction;
|
848
src/themes/default.less
Normal file
848
src/themes/default.less
Normal file
@ -0,0 +1,848 @@
|
||||
// 本文件是对 ant-design:
|
||||
// https://github.com/ant-design/ant-design/blob/master/components/style/themes/default.less
|
||||
// 相应变量值的覆盖
|
||||
// 注意:只需写出要覆盖的变量即可(不需要覆盖的变量不要写)
|
||||
|
||||
|
||||
/* stylelint-disable at-rule-empty-line-before,at-rule-name-space-after,at-rule-no-unknown */
|
||||
@import '../../node_modules/antd/lib/style/themes/default.less';
|
||||
|
||||
|
||||
// -------- Colors -----------
|
||||
@primary-color: @blue-6;
|
||||
@info-color: @blue-6;
|
||||
@success-color: @green-6;
|
||||
@processing-color: @blue-6;
|
||||
@error-color: @red-6;
|
||||
@highlight-color: @red-6;
|
||||
@warning-color: @gold-6;
|
||||
@normal-color: #d9d9d9;
|
||||
@white: #fff;
|
||||
@black: #000;
|
||||
|
||||
// Color used by default to control hover and active backgrounds and for
|
||||
// alert info backgrounds.
|
||||
@primary-1: color(~`colorPalette('@{primary-color}', 1) `); // replace tint(@primary-color, 90%)
|
||||
@primary-2: color(~`colorPalette('@{primary-color}', 2) `); // replace tint(@primary-color, 80%)
|
||||
@primary-3: color(~`colorPalette('@{primary-color}', 3) `); // unused
|
||||
@primary-4: color(~`colorPalette('@{primary-color}', 4) `); // unused
|
||||
@primary-5: color(
|
||||
~`colorPalette('@{primary-color}', 5) `
|
||||
); // color used to control the text color in many active and hover states, replace tint(@primary-color, 20%)
|
||||
@primary-6: @primary-color; // color used to control the text color of active buttons, don't use, use @primary-color
|
||||
@primary-7: color(~`colorPalette('@{primary-color}', 7) `); // replace shade(@primary-color, 5%)
|
||||
@primary-8: color(~`colorPalette('@{primary-color}', 8) `); // unused
|
||||
@primary-9: color(~`colorPalette('@{primary-color}', 9) `); // unused
|
||||
@primary-10: color(~`colorPalette('@{primary-color}', 10) `); // unused
|
||||
|
||||
// Base Scaffolding Variables
|
||||
// ---
|
||||
|
||||
// Background color for `<body>`
|
||||
@body-background: #fff;
|
||||
// Base background color for most components
|
||||
@component-background: #fff;
|
||||
@font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB',
|
||||
'Microsoft YaHei', 'Helvetica Neue', Helvetica, Arial, sans-serif, 'Apple Color Emoji',
|
||||
'Segoe UI Emoji', 'Segoe UI Symbol';
|
||||
@code-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace;
|
||||
@text-color: fade(@black, 65%);
|
||||
@text-color-secondary: fade(@black, 45%);
|
||||
@text-color-inverse: @white;
|
||||
@icon-color: inherit;
|
||||
@icon-color-hover: fade(@black, 75%);
|
||||
@heading-color: fade(#000, 85%);
|
||||
@heading-color-dark: fade(@white, 100%);
|
||||
@text-color-dark: fade(@white, 85%);
|
||||
@text-color-secondary-dark: fade(@white, 65%);
|
||||
@text-selection-bg: @primary-color;
|
||||
@font-variant-base: tabular-nums;
|
||||
@font-feature-settings-base: 'tnum';
|
||||
@font-size-base: 14px;
|
||||
@font-size-lg: @font-size-base + 2px;
|
||||
@font-size-sm: 12px;
|
||||
@heading-1-size: ceil(@font-size-base * 2.71);
|
||||
@heading-2-size: ceil(@font-size-base * 2.14);
|
||||
@heading-3-size: ceil(@font-size-base * 1.71);
|
||||
@heading-4-size: ceil(@font-size-base * 1.42);
|
||||
@line-height-base: 1.5;
|
||||
@border-radius-base: 4px;
|
||||
@border-radius-sm: 2px;
|
||||
|
||||
// vertical paddings
|
||||
@padding-lg: 24px; // containers
|
||||
@padding-md: 16px; // small containers and buttons
|
||||
@padding-sm: 12px; // Form controls and items
|
||||
@padding-xs: 8px; // small items
|
||||
|
||||
// vertical padding for all form controls
|
||||
@control-padding-horizontal: @padding-sm;
|
||||
@control-padding-horizontal-sm: @padding-xs;
|
||||
|
||||
// The background colors for active and hover states for things like
|
||||
// list items or table cells.
|
||||
@item-active-bg: @primary-1;
|
||||
@item-hover-bg: @primary-1;
|
||||
|
||||
// ICONFONT
|
||||
@iconfont-css-prefix: anticon;
|
||||
|
||||
// LINK
|
||||
@link-color: @primary-color;
|
||||
@link-hover-color: color(~`colorPalette('@{link-color}', 5) `);
|
||||
@link-active-color: color(~`colorPalette('@{link-color}', 7) `);
|
||||
@link-decoration: none;
|
||||
@link-hover-decoration: none;
|
||||
|
||||
// Animation
|
||||
@ease-base-out: cubic-bezier(0.7, 0.3, 0.1, 1);
|
||||
@ease-base-in: cubic-bezier(0.9, 0, 0.3, 0.7);
|
||||
@ease-out: cubic-bezier(0.215, 0.61, 0.355, 1);
|
||||
@ease-in: cubic-bezier(0.55, 0.055, 0.675, 0.19);
|
||||
@ease-in-out: cubic-bezier(0.645, 0.045, 0.355, 1);
|
||||
@ease-out-back: cubic-bezier(0.12, 0.4, 0.29, 1.46);
|
||||
@ease-in-back: cubic-bezier(0.71, -0.46, 0.88, 0.6);
|
||||
@ease-in-out-back: cubic-bezier(0.71, -0.46, 0.29, 1.46);
|
||||
@ease-out-circ: cubic-bezier(0.08, 0.82, 0.17, 1);
|
||||
@ease-in-circ: cubic-bezier(0.6, 0.04, 0.98, 0.34);
|
||||
@ease-in-out-circ: cubic-bezier(0.78, 0.14, 0.15, 0.86);
|
||||
@ease-out-quint: cubic-bezier(0.23, 1, 0.32, 1);
|
||||
@ease-in-quint: cubic-bezier(0.755, 0.05, 0.855, 0.06);
|
||||
@ease-in-out-quint: cubic-bezier(0.86, 0, 0.07, 1);
|
||||
|
||||
// Border color
|
||||
@border-color-base: hsv(0, 0, 85%); // base border outline a component
|
||||
@border-color-split: hsv(0, 0, 91%); // split border inside a component
|
||||
@border-color-inverse: @white;
|
||||
@border-width-base: 1px; // width of the border for a component
|
||||
@border-style-base: solid; // style of a components border
|
||||
|
||||
// Outline
|
||||
@outline-blur-size: 0;
|
||||
@outline-width: 2px;
|
||||
@outline-color: @primary-color;
|
||||
|
||||
@background-color-light: hsv(0, 0, 98%); // background of header and selected item
|
||||
@background-color-base: hsv(0, 0, 96%); // Default grey background color
|
||||
|
||||
// Disabled states
|
||||
@disabled-color: fade(#000, 25%);
|
||||
@disabled-bg: @background-color-base;
|
||||
@disabled-color-dark: fade(#fff, 35%);
|
||||
|
||||
// Shadow
|
||||
@shadow-color: rgba(0, 0, 0, 0.15);
|
||||
@shadow-color-inverse: @component-background;
|
||||
@box-shadow-base: @shadow-1-down;
|
||||
@shadow-1-up: 0 -2px 8px @shadow-color;
|
||||
@shadow-1-down: 0 2px 8px @shadow-color;
|
||||
@shadow-1-left: -2px 0 8px @shadow-color;
|
||||
@shadow-1-right: 2px 0 8px @shadow-color;
|
||||
@shadow-2: 0 4px 12px @shadow-color;
|
||||
|
||||
// Buttons
|
||||
@btn-font-weight: 400;
|
||||
@btn-border-radius-base: @border-radius-base;
|
||||
@btn-border-radius-sm: @border-radius-base;
|
||||
@btn-border-width: @border-width-base;
|
||||
@btn-border-style: @border-style-base;
|
||||
@btn-shadow: 0 2px 0 rgba(0, 0, 0, 0.015);
|
||||
@btn-primary-shadow: 0 2px 0 rgba(0, 0, 0, 0.045);
|
||||
@btn-text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.12);
|
||||
|
||||
@btn-primary-color: #fff;
|
||||
@btn-primary-bg: @primary-color;
|
||||
|
||||
@btn-default-color: @text-color;
|
||||
@btn-default-bg: @component-background;
|
||||
@btn-default-border: @border-color-base;
|
||||
|
||||
@btn-danger-color: #fff;
|
||||
@btn-danger-bg: color(~`colorPalette('@{error-color}', 5) `);
|
||||
@btn-danger-border: color(~`colorPalette('@{error-color}', 5) `);
|
||||
|
||||
@btn-disable-color: @disabled-color;
|
||||
@btn-disable-bg: @disabled-bg;
|
||||
@btn-disable-border: @border-color-base;
|
||||
|
||||
@btn-padding-base: 0 @padding-md - 1px;
|
||||
@btn-font-size-lg: @font-size-lg;
|
||||
@btn-font-size-sm: @font-size-base;
|
||||
@btn-padding-lg: @btn-padding-base;
|
||||
@btn-padding-sm: 0 @padding-xs - 1px;
|
||||
|
||||
@btn-height-base: 32px;
|
||||
@btn-height-lg: 40px;
|
||||
@btn-height-sm: 24px;
|
||||
|
||||
@btn-circle-size: @btn-height-base;
|
||||
@btn-circle-size-lg: @btn-height-lg;
|
||||
@btn-circle-size-sm: @btn-height-sm;
|
||||
|
||||
@btn-square-size: @btn-height-base;
|
||||
@btn-square-size-lg: @btn-height-lg;
|
||||
@btn-square-size-sm: @btn-height-sm;
|
||||
|
||||
@btn-group-border: @primary-5;
|
||||
|
||||
// Checkbox
|
||||
@checkbox-size: 16px;
|
||||
@checkbox-color: @primary-color;
|
||||
@checkbox-check-color: #fff;
|
||||
@checkbox-border-width: @border-width-base;
|
||||
|
||||
// Descriptions
|
||||
@descriptions-bg: #fafafa;
|
||||
|
||||
// Dropdown
|
||||
@dropdown-selected-color: @primary-color;
|
||||
|
||||
// Empty
|
||||
@empty-font-size: @font-size-base;
|
||||
|
||||
// Radio
|
||||
@radio-size: 16px;
|
||||
@radio-dot-color: @primary-color;
|
||||
|
||||
// Radio buttons
|
||||
@radio-button-bg: @btn-default-bg;
|
||||
@radio-button-checked-bg: @btn-default-bg;
|
||||
@radio-button-color: @btn-default-color;
|
||||
@radio-button-hover-color: @primary-5;
|
||||
@radio-button-active-color: @primary-7;
|
||||
|
||||
// Media queries breakpoints
|
||||
// Extra small screen / phone
|
||||
@screen-xs: 480px;
|
||||
@screen-xs-min: @screen-xs;
|
||||
|
||||
// Small screen / tablet
|
||||
@screen-sm: 576px;
|
||||
@screen-sm-min: @screen-sm;
|
||||
|
||||
// Medium screen / desktop
|
||||
@screen-md: 768px;
|
||||
@screen-md-min: @screen-md;
|
||||
|
||||
// Large screen / wide desktop
|
||||
@screen-lg: 992px;
|
||||
@screen-lg-min: @screen-lg;
|
||||
|
||||
// Extra large screen / full hd
|
||||
@screen-xl: 1200px;
|
||||
@screen-xl-min: @screen-xl;
|
||||
|
||||
// Extra extra large screen / large desktop
|
||||
@screen-xxl: 1600px;
|
||||
@screen-xxl-min: @screen-xxl;
|
||||
|
||||
// provide a maximum
|
||||
@screen-xs-max: (@screen-sm-min - 1px);
|
||||
@screen-sm-max: (@screen-md-min - 1px);
|
||||
@screen-md-max: (@screen-lg-min - 1px);
|
||||
@screen-lg-max: (@screen-xl-min - 1px);
|
||||
@screen-xl-max: (@screen-xxl-min - 1px);
|
||||
|
||||
// Grid system
|
||||
@grid-columns: 24;
|
||||
@grid-gutter-width: 0;
|
||||
|
||||
// Layout
|
||||
@layout-body-background: #f0f2f5;
|
||||
@layout-header-background: #424242;
|
||||
@layout-footer-background: @layout-body-background;
|
||||
@layout-header-height: 64px;
|
||||
@layout-header-padding: 0 50px;
|
||||
@layout-footer-padding: 24px 50px;
|
||||
@layout-sider-background: @layout-header-background;
|
||||
@layout-trigger-height: 48px;
|
||||
@layout-trigger-background: #2d2d2d;
|
||||
@layout-trigger-color: #fff;
|
||||
@layout-zero-trigger-width: 36px;
|
||||
@layout-zero-trigger-height: 42px;
|
||||
// Layout light theme
|
||||
@layout-sider-background-light: #fff;
|
||||
@layout-trigger-background-light: #fff;
|
||||
@layout-trigger-color-light: @text-color;
|
||||
|
||||
// z-index list, order by `z-index`
|
||||
@zindex-table-fixed: auto;
|
||||
@zindex-affix: 10;
|
||||
@zindex-back-top: 10;
|
||||
@zindex-badge: 10;
|
||||
@zindex-picker-panel: 10;
|
||||
@zindex-popup-close: 10;
|
||||
@zindex-modal: 1000;
|
||||
@zindex-modal-mask: 1000;
|
||||
@zindex-message: 1010;
|
||||
@zindex-notification: 1010;
|
||||
@zindex-popover: 1030;
|
||||
@zindex-dropdown: 1050;
|
||||
@zindex-picker: 1050;
|
||||
@zindex-tooltip: 1060;
|
||||
|
||||
// Animation
|
||||
@animation-duration-slow: 0.3s; // Modal
|
||||
@animation-duration-base: 0.2s;
|
||||
@animation-duration-fast: 0.1s; // Tooltip
|
||||
|
||||
//CollapsePanel
|
||||
@collapse-panel-border-radius: @border-radius-base;
|
||||
|
||||
//Dropdown
|
||||
@dropdown-vertical-padding: 5px;
|
||||
@dropdown-font-size: @font-size-base;
|
||||
@dropdown-line-height: 22px;
|
||||
|
||||
// Form
|
||||
// ---
|
||||
@label-required-color: @highlight-color;
|
||||
@label-color: @heading-color;
|
||||
@form-warning-input-bg: @input-bg;
|
||||
@form-item-margin-bottom: 24px;
|
||||
@form-item-trailing-colon: true;
|
||||
@form-vertical-label-padding: 0 0 8px;
|
||||
@form-vertical-label-margin: 0;
|
||||
@form-item-label-colon-margin-right: 8px;
|
||||
@form-item-label-colon-margin-left: 2px;
|
||||
@form-error-input-bg: @input-bg;
|
||||
|
||||
// Input
|
||||
// ---
|
||||
@input-height-base: 32px;
|
||||
@input-height-lg: 40px;
|
||||
@input-height-sm: 24px;
|
||||
@input-padding-horizontal: @control-padding-horizontal - 1px;
|
||||
@input-padding-horizontal-base: @input-padding-horizontal;
|
||||
@input-padding-horizontal-sm: @control-padding-horizontal-sm - 1px;
|
||||
@input-padding-horizontal-lg: @input-padding-horizontal;
|
||||
@input-padding-vertical-base: 4px;
|
||||
@input-padding-vertical-sm: 1px;
|
||||
@input-padding-vertical-lg: 6px;
|
||||
@input-placeholder-color: hsv(0, 0, 75%);
|
||||
@input-color: @text-color;
|
||||
@input-border-color: @border-color-base;
|
||||
@input-bg: @component-background;
|
||||
@input-number-handler-active-bg: #f4f4f4;
|
||||
@input-number-handler-hover-bg: @primary-5;
|
||||
@input-number-handler-bg: @component-background;
|
||||
@input-number-handler-border-color: @border-color-base;
|
||||
@input-addon-bg: @background-color-light;
|
||||
@input-hover-border-color: @primary-5;
|
||||
@input-disabled-bg: @disabled-bg;
|
||||
@input-outline-offset: 0 0;
|
||||
|
||||
// Select
|
||||
// ---
|
||||
@select-border-color: @border-color-base;
|
||||
@select-item-selected-font-weight: 600;
|
||||
@select-dropdown-bg: @component-background;
|
||||
@select-item-selected-bg: @background-color-light;
|
||||
@select-item-active-bg: @item-active-bg;
|
||||
|
||||
// Anchor
|
||||
// ---
|
||||
@anchor-border-color: @border-color-split;
|
||||
|
||||
// Tooltip
|
||||
// ---
|
||||
// Tooltip max width
|
||||
@tooltip-max-width: 250px;
|
||||
// Tooltip text color
|
||||
@tooltip-color: #fff;
|
||||
// Tooltip background color
|
||||
@tooltip-bg: rgba(0, 0, 0, 0.75);
|
||||
// Tooltip arrow width
|
||||
@tooltip-arrow-width: 5px;
|
||||
// Tooltip distance with trigger
|
||||
@tooltip-distance: @tooltip-arrow-width - 1px + 4px;
|
||||
// Tooltip arrow color
|
||||
@tooltip-arrow-color: @tooltip-bg;
|
||||
|
||||
// Popover
|
||||
// ---
|
||||
// Popover body background color
|
||||
@popover-bg: @component-background;
|
||||
// Popover text color
|
||||
@popover-color: @text-color;
|
||||
// Popover maximum width
|
||||
@popover-min-width: 177px;
|
||||
// Popover arrow width
|
||||
@popover-arrow-width: 6px;
|
||||
// Popover arrow color
|
||||
@popover-arrow-color: @popover-bg;
|
||||
// Popover outer arrow width
|
||||
// Popover outer arrow color
|
||||
@popover-arrow-outer-color: @popover-bg;
|
||||
// Popover distance with trigger
|
||||
@popover-distance: @popover-arrow-width + 4px;
|
||||
|
||||
// Modal
|
||||
// --
|
||||
@modal-body-padding: 24px;
|
||||
@modal-header-bg: @component-background;
|
||||
@modal-footer-bg: transparent;
|
||||
@modal-footer-border-color-split: @border-color-split;
|
||||
@modal-mask-bg: fade(@black, 45%);
|
||||
|
||||
// Progress
|
||||
// --
|
||||
@progress-default-color: @processing-color;
|
||||
@progress-remaining-color: @background-color-base;
|
||||
@progress-text-color: @text-color;
|
||||
@progress-radius: 100px;
|
||||
|
||||
// Menu
|
||||
// ---
|
||||
@menu-inline-toplevel-item-height: 40px;
|
||||
@menu-item-height: 40px;
|
||||
@menu-collapsed-width: 80px;
|
||||
@menu-bg: @component-background;
|
||||
@menu-popup-bg: @component-background;
|
||||
@menu-item-color: @text-color;
|
||||
@menu-highlight-color: @primary-color;
|
||||
@menu-item-active-bg: @item-active-bg;
|
||||
@menu-item-active-border-width: 3px;
|
||||
@menu-item-group-title-color: @text-color-secondary;
|
||||
@menu-icon-size: @font-size-base;
|
||||
@menu-icon-size-lg: @font-size-lg;
|
||||
|
||||
@menu-item-vertical-margin: 4px;
|
||||
@menu-item-font-size: @font-size-base;
|
||||
@menu-item-boundary-margin: 8px;
|
||||
@menu-icon-size: @font-size-base;
|
||||
@menu-icon-size-lg: @font-size-lg;
|
||||
@menu-dark-selected-item-icon-color: @white;
|
||||
@menu-dark-selected-item-text-color: @white;
|
||||
@dark-menu-item-hover-bg: transparent;
|
||||
|
||||
// dark theme
|
||||
@menu-dark-color: @text-color-secondary-dark;
|
||||
@menu-dark-bg: #2d2d2d;
|
||||
@menu-dark-arrow-color: #fff;
|
||||
@menu-dark-submenu-bg: #2d2d2d;
|
||||
@menu-dark-highlight-color: #fff;
|
||||
@menu-dark-item-active-bg: @primary-color;
|
||||
@menu-dark-selected-item-icon-color: @white;
|
||||
@menu-dark-selected-item-text-color: @white;
|
||||
@menu-dark-item-hover-bg: transparent;
|
||||
// Spin
|
||||
// ---
|
||||
@spin-dot-size-sm: 14px;
|
||||
@spin-dot-size: 20px;
|
||||
@spin-dot-size-lg: 32px;
|
||||
|
||||
// Table
|
||||
// --
|
||||
@table-header-bg: @background-color-light;
|
||||
@table-header-color: @heading-color;
|
||||
@table-header-sort-bg: @background-color-base;
|
||||
@table-body-sort-bg: rgba(0, 0, 0, 0.01);
|
||||
@table-row-hover-bg: @primary-1;
|
||||
@table-selected-row-color: inherit;
|
||||
@table-selected-row-bg: #fafafa;
|
||||
@table-body-selected-sort-bg: @table-selected-row-bg;
|
||||
@table-selected-row-hover-bg: @table-selected-row-bg;
|
||||
@table-expanded-row-bg: #fbfbfb;
|
||||
@table-padding-vertical: 16px;
|
||||
@table-padding-horizontal: 16px;
|
||||
@table-border-radius-base: @border-radius-base;
|
||||
@table-footer-bg: @background-color-light;
|
||||
@table-footer-color: @heading-color;
|
||||
|
||||
// Tag
|
||||
// --
|
||||
@tag-default-bg: @background-color-light;
|
||||
@tag-default-color: @text-color;
|
||||
@tag-font-size: @font-size-sm;
|
||||
|
||||
// TimePicker
|
||||
// ---
|
||||
@time-picker-panel-column-width: 56px;
|
||||
@time-picker-panel-width: @time-picker-panel-column-width * 3;
|
||||
@time-picker-selected-bg: @background-color-base;
|
||||
|
||||
// Carousel
|
||||
// ---
|
||||
@carousel-dot-width: 16px;
|
||||
@carousel-dot-height: 3px;
|
||||
@carousel-dot-active-width: 24px;
|
||||
|
||||
// Badge
|
||||
// ---
|
||||
@badge-height: 20px;
|
||||
@badge-dot-size: 6px;
|
||||
@badge-font-size: @font-size-sm;
|
||||
@badge-font-weight: normal;
|
||||
@badge-status-size: 6px;
|
||||
@badge-text-color: @component-background;
|
||||
|
||||
// Rate
|
||||
// ---
|
||||
@rate-star-color: @yellow-6;
|
||||
@rate-star-bg: @border-color-split;
|
||||
|
||||
// Card
|
||||
// ---
|
||||
@card-head-color: @heading-color;
|
||||
@card-head-background: transparent;
|
||||
@card-head-padding: 16px;
|
||||
@card-inner-head-padding: 12px;
|
||||
@card-padding-base: 24px;
|
||||
@card-actions-background: @background-color-light;
|
||||
@card-skeleton-bg: #cfd8dc;
|
||||
@card-background: @component-background;
|
||||
@card-shadow: 0 2px 8px rgba(0, 0, 0, 0.09);
|
||||
@card-radius: @border-radius-sm;
|
||||
|
||||
// Comment
|
||||
// ---
|
||||
@comment-padding-base: 16px 0;
|
||||
@comment-nest-indent: 44px;
|
||||
@comment-font-size-base: @font-size-base;
|
||||
@comment-font-size-sm: @font-size-sm;
|
||||
@comment-author-name-color: @text-color-secondary;
|
||||
@comment-author-time-color: #ccc;
|
||||
@comment-action-color: @text-color-secondary;
|
||||
@comment-action-hover-color: #595959;
|
||||
|
||||
// Tabs
|
||||
// ---
|
||||
@tabs-card-head-background: @background-color-light;
|
||||
@tabs-card-height: 40px;
|
||||
@tabs-card-active-color: @primary-color;
|
||||
@tabs-title-font-size: @font-size-base;
|
||||
@tabs-title-font-size-lg: @font-size-lg;
|
||||
@tabs-title-font-size-sm: @font-size-base;
|
||||
@tabs-ink-bar-color: @primary-color;
|
||||
@tabs-bar-margin: 0 0 16px 0;
|
||||
@tabs-horizontal-margin: 0 32px 0 0;
|
||||
@tabs-horizontal-padding: 12px 16px;
|
||||
@tabs-horizontal-padding-lg: 16px;
|
||||
@tabs-horizontal-padding-sm: 8px 16px;
|
||||
@tabs-vertical-padding: 8px 24px;
|
||||
@tabs-vertical-margin: 0 0 16px 0;
|
||||
@tabs-scrolling-size: 32px;
|
||||
@tabs-highlight-color: @primary-color;
|
||||
@tabs-hover-color: @primary-5;
|
||||
@tabs-active-color: @primary-7;
|
||||
@tabs-card-gutter: 2px;
|
||||
@tabs-card-tab-active-border-top: 2px solid transparent;
|
||||
|
||||
// BackTop
|
||||
// ---
|
||||
@back-top-color: #fff;
|
||||
@back-top-bg: @text-color-secondary;
|
||||
@back-top-hover-bg: @text-color;
|
||||
|
||||
// Avatar
|
||||
// ---
|
||||
@avatar-size-base: 32px;
|
||||
@avatar-size-lg: 40px;
|
||||
@avatar-size-sm: 24px;
|
||||
@avatar-font-size-base: 18px;
|
||||
@avatar-font-size-lg: 24px;
|
||||
@avatar-font-size-sm: 14px;
|
||||
@avatar-bg: #ccc;
|
||||
@avatar-color: #fff;
|
||||
@avatar-border-radius: @border-radius-base;
|
||||
|
||||
// Switch
|
||||
// ---
|
||||
@switch-height: 22px;
|
||||
@switch-sm-height: 16px;
|
||||
@switch-sm-checked-margin-left: -(@switch-sm-height - 3px);
|
||||
@switch-disabled-opacity: 0.4;
|
||||
@switch-color: @primary-color;
|
||||
@switch-shadow-color: fade(#00230b, 20%);
|
||||
|
||||
// Pagination
|
||||
// ---
|
||||
@pagination-item-size: 32px;
|
||||
@pagination-item-size-sm: 24px;
|
||||
@pagination-font-family: Arial;
|
||||
@pagination-font-weight-active: 500;
|
||||
@pagination-item-bg-active: @component-background;
|
||||
|
||||
// PageHeader
|
||||
// ---
|
||||
@page-header-padding: 24px;
|
||||
@page-header-padding-vertical: 16px;
|
||||
@page-header-padding-breadcrumb: 12px;
|
||||
@page-header-back-color: #000;
|
||||
|
||||
// Breadcrumb
|
||||
// ---
|
||||
@breadcrumb-base-color: @text-color-secondary;
|
||||
@breadcrumb-last-item-color: @text-color;
|
||||
@breadcrumb-font-size: @font-size-base;
|
||||
@breadcrumb-icon-font-size: @font-size-base;
|
||||
@breadcrumb-link-color: @text-color-secondary;
|
||||
@breadcrumb-link-color-hover: @primary-5;
|
||||
@breadcrumb-separator-color: @text-color-secondary;
|
||||
@breadcrumb-separator-margin: 0 @padding-xs;
|
||||
|
||||
// Slider
|
||||
// ---
|
||||
@slider-margin: 14px 6px 10px;
|
||||
@slider-rail-background-color: @background-color-base;
|
||||
@slider-rail-background-color-hover: #e1e1e1;
|
||||
@slider-track-background-color: @primary-3;
|
||||
@slider-track-background-color-hover: @primary-4;
|
||||
@slider-handle-border-width: 2px;
|
||||
@slider-handle-background-color: @component-background;
|
||||
@slider-handle-color: @primary-3;
|
||||
@slider-handle-color-hover: @primary-4;
|
||||
@slider-handle-color-focus: tint(@primary-color, 20%);
|
||||
@slider-handle-color-focus-shadow: fade(@primary-color, 20%);
|
||||
@slider-handle-color-tooltip-open: @primary-color;
|
||||
@slider-handle-shadow: 0;
|
||||
@slider-dot-border-color: @border-color-split;
|
||||
@slider-dot-border-color-active: tint(@primary-color, 50%);
|
||||
@slider-disabled-color: @disabled-color;
|
||||
@slider-disabled-background-color: @component-background;
|
||||
|
||||
// Tree
|
||||
// ---
|
||||
@tree-title-height: 24px;
|
||||
@tree-child-padding: 18px;
|
||||
@tree-directory-selected-color: #fff;
|
||||
@tree-directory-selected-bg: @primary-color;
|
||||
@tree-node-hover-bg: @item-hover-bg;
|
||||
@tree-node-selected-bg: @primary-2;
|
||||
|
||||
// Collapse
|
||||
// ---
|
||||
@collapse-header-padding: 12px 16px;
|
||||
@collapse-header-padding-extra: 40px;
|
||||
@collapse-header-bg: @background-color-light;
|
||||
@collapse-content-padding: @padding-md;
|
||||
@collapse-content-bg: @component-background;
|
||||
|
||||
// Skeleton
|
||||
// ---
|
||||
@skeleton-color: #f2f2f2;
|
||||
|
||||
// Transfer
|
||||
// ---
|
||||
@transfer-header-height: 40px;
|
||||
@transfer-disabled-bg: @disabled-bg;
|
||||
@transfer-list-height: 200px;
|
||||
|
||||
// Message
|
||||
// ---
|
||||
@message-notice-content-padding: 10px 16px;
|
||||
|
||||
// Motion
|
||||
// ---
|
||||
@wave-animation-width: 6px;
|
||||
|
||||
// Alert
|
||||
// ---
|
||||
@alert-success-border-color: ~`colorPalette('@{success-color}', 3) `;
|
||||
@alert-success-bg-color: ~`colorPalette('@{success-color}', 1) `;
|
||||
@alert-success-icon-color: @success-color;
|
||||
@alert-info-border-color: ~`colorPalette('@{info-color}', 3) `;
|
||||
@alert-info-bg-color: ~`colorPalette('@{info-color}', 1) `;
|
||||
@alert-info-icon-color: @info-color;
|
||||
@alert-warning-border-color: ~`colorPalette('@{warning-color}', 3) `;
|
||||
@alert-warning-bg-color: ~`colorPalette('@{warning-color}', 1) `;
|
||||
@alert-warning-icon-color: @warning-color;
|
||||
@alert-error-border-color: ~`colorPalette('@{error-color}', 3) `;
|
||||
@alert-error-bg-color: ~`colorPalette('@{error-color}', 1) `;
|
||||
@alert-error-icon-color: @error-color;
|
||||
|
||||
// List
|
||||
// ---
|
||||
@list-header-background: transparent;
|
||||
@list-footer-background: transparent;
|
||||
@list-empty-text-padding: @padding-md;
|
||||
@list-item-padding: @padding-sm 0;
|
||||
@list-item-meta-margin-bottom: @padding-md;
|
||||
@list-item-meta-avatar-margin-right: @padding-md;
|
||||
@list-item-meta-title-margin-bottom: @padding-sm;
|
||||
|
||||
// Statistic
|
||||
// ---
|
||||
@statistic-title-font-size: @font-size-base;
|
||||
@statistic-content-font-size: 24px;
|
||||
@statistic-unit-font-size: 16px;
|
||||
@statistic-font-family: @font-family;
|
||||
|
||||
// Drawer
|
||||
// ---
|
||||
@drawer-header-padding: 16px 24px;
|
||||
@drawer-body-padding: 24px;
|
||||
|
||||
// Timeline
|
||||
// ---
|
||||
@timeline-width: 2px;
|
||||
@timeline-color: @border-color-split;
|
||||
@timeline-dot-border-width: 2px;
|
||||
@timeline-dot-color: @primary-color;
|
||||
@timeline-dot-bg: @component-background;
|
||||
|
||||
// Typography
|
||||
// ---
|
||||
@typography-title-font-weight: 600;
|
||||
@typography-title-margin-top: 1.2em;
|
||||
@typography-title-margin-bottom: 0.5em;
|
||||
|
||||
// color palettes
|
||||
@blue-1: color(~`colorPalette('@{blue-6}', 1) `);
|
||||
@blue-2: color(~`colorPalette('@{blue-6}', 2) `);
|
||||
@blue-3: color(~`colorPalette('@{blue-6}', 3) `);
|
||||
@blue-4: color(~`colorPalette('@{blue-6}', 4) `);
|
||||
@blue-5: color(~`colorPalette('@{blue-6}', 5) `);
|
||||
@blue-6: #1890ff;
|
||||
@blue-7: color(~`colorPalette('@{blue-6}', 7) `);
|
||||
@blue-8: color(~`colorPalette('@{blue-6}', 8) `);
|
||||
@blue-9: color(~`colorPalette('@{blue-6}', 9) `);
|
||||
@blue-10: color(~`colorPalette('@{blue-6}', 10) `);
|
||||
|
||||
@purple-1: color(~`colorPalette('@{purple-6}', 1) `);
|
||||
@purple-2: color(~`colorPalette('@{purple-6}', 2) `);
|
||||
@purple-3: color(~`colorPalette('@{purple-6}', 3) `);
|
||||
@purple-4: color(~`colorPalette('@{purple-6}', 4) `);
|
||||
@purple-5: color(~`colorPalette('@{purple-6}', 5) `);
|
||||
@purple-6: #722ed1;
|
||||
@purple-7: color(~`colorPalette('@{purple-6}', 7) `);
|
||||
@purple-8: color(~`colorPalette('@{purple-6}', 8) `);
|
||||
@purple-9: color(~`colorPalette('@{purple-6}', 9) `);
|
||||
@purple-10: color(~`colorPalette('@{purple-6}', 10) `);
|
||||
|
||||
@cyan-1: color(~`colorPalette('@{cyan-6}', 1) `);
|
||||
@cyan-2: color(~`colorPalette('@{cyan-6}', 2) `);
|
||||
@cyan-3: color(~`colorPalette('@{cyan-6}', 3) `);
|
||||
@cyan-4: color(~`colorPalette('@{cyan-6}', 4) `);
|
||||
@cyan-5: color(~`colorPalette('@{cyan-6}', 5) `);
|
||||
@cyan-6: #13c2c2;
|
||||
@cyan-7: color(~`colorPalette('@{cyan-6}', 7) `);
|
||||
@cyan-8: color(~`colorPalette('@{cyan-6}', 8) `);
|
||||
@cyan-9: color(~`colorPalette('@{cyan-6}', 9) `);
|
||||
@cyan-10: color(~`colorPalette('@{cyan-6}', 10) `);
|
||||
|
||||
@green-1: color(~`colorPalette('@{green-6}', 1) `);
|
||||
@green-2: color(~`colorPalette('@{green-6}', 2) `);
|
||||
@green-3: color(~`colorPalette('@{green-6}', 3) `);
|
||||
@green-4: color(~`colorPalette('@{green-6}', 4) `);
|
||||
@green-5: color(~`colorPalette('@{green-6}', 5) `);
|
||||
@green-6: #52c41a;
|
||||
@green-7: color(~`colorPalette('@{green-6}', 7) `);
|
||||
@green-8: color(~`colorPalette('@{green-6}', 8) `);
|
||||
@green-9: color(~`colorPalette('@{green-6}', 9) `);
|
||||
@green-10: color(~`colorPalette('@{green-6}', 10) `);
|
||||
|
||||
@magenta-1: color(~`colorPalette('@{magenta-6}', 1) `);
|
||||
@magenta-2: color(~`colorPalette('@{magenta-6}', 2) `);
|
||||
@magenta-3: color(~`colorPalette('@{magenta-6}', 3) `);
|
||||
@magenta-4: color(~`colorPalette('@{magenta-6}', 4) `);
|
||||
@magenta-5: color(~`colorPalette('@{magenta-6}', 5) `);
|
||||
@magenta-6: #eb2f96;
|
||||
@magenta-7: color(~`colorPalette('@{magenta-6}', 7) `);
|
||||
@magenta-8: color(~`colorPalette('@{magenta-6}', 8) `);
|
||||
@magenta-9: color(~`colorPalette('@{magenta-6}', 9) `);
|
||||
@magenta-10: color(~`colorPalette('@{magenta-6}', 10) `);
|
||||
|
||||
// alias of magenta
|
||||
@pink-1: color(~`colorPalette('@{pink-6}', 1) `);
|
||||
@pink-2: color(~`colorPalette('@{pink-6}', 2) `);
|
||||
@pink-3: color(~`colorPalette('@{pink-6}', 3) `);
|
||||
@pink-4: color(~`colorPalette('@{pink-6}', 4) `);
|
||||
@pink-5: color(~`colorPalette('@{pink-6}', 5) `);
|
||||
@pink-6: #eb2f96;
|
||||
@pink-7: color(~`colorPalette('@{pink-6}', 7) `);
|
||||
@pink-8: color(~`colorPalette('@{pink-6}', 8) `);
|
||||
@pink-9: color(~`colorPalette('@{pink-6}', 9) `);
|
||||
@pink-10: color(~`colorPalette('@{pink-6}', 10) `);
|
||||
|
||||
@red-1: color(~`colorPalette('@{red-6}', 1) `);
|
||||
@red-2: color(~`colorPalette('@{red-6}', 2) `);
|
||||
@red-3: color(~`colorPalette('@{red-6}', 3) `);
|
||||
@red-4: color(~`colorPalette('@{red-6}', 4) `);
|
||||
@red-5: color(~`colorPalette('@{red-6}', 5) `);
|
||||
@red-6: #f5222d;
|
||||
@red-7: color(~`colorPalette('@{red-6}', 7) `);
|
||||
@red-8: color(~`colorPalette('@{red-6}', 8) `);
|
||||
@red-9: color(~`colorPalette('@{red-6}', 9) `);
|
||||
@red-10: color(~`colorPalette('@{red-6}', 10) `);
|
||||
|
||||
@orange-1: color(~`colorPalette('@{orange-6}', 1) `);
|
||||
@orange-2: color(~`colorPalette('@{orange-6}', 2) `);
|
||||
@orange-3: color(~`colorPalette('@{orange-6}', 3) `);
|
||||
@orange-4: color(~`colorPalette('@{orange-6}', 4) `);
|
||||
@orange-5: color(~`colorPalette('@{orange-6}', 5) `);
|
||||
@orange-6: #fa8c16;
|
||||
@orange-7: color(~`colorPalette('@{orange-6}', 7) `);
|
||||
@orange-8: color(~`colorPalette('@{orange-6}', 8) `);
|
||||
@orange-9: color(~`colorPalette('@{orange-6}', 9) `);
|
||||
@orange-10: color(~`colorPalette('@{orange-6}', 10) `);
|
||||
|
||||
@yellow-1: color(~`colorPalette('@{yellow-6}', 1) `);
|
||||
@yellow-2: color(~`colorPalette('@{yellow-6}', 2) `);
|
||||
@yellow-3: color(~`colorPalette('@{yellow-6}', 3) `);
|
||||
@yellow-4: color(~`colorPalette('@{yellow-6}', 4) `);
|
||||
@yellow-5: color(~`colorPalette('@{yellow-6}', 5) `);
|
||||
@yellow-6: #fadb14;
|
||||
@yellow-7: color(~`colorPalette('@{yellow-6}', 7) `);
|
||||
@yellow-8: color(~`colorPalette('@{yellow-6}', 8) `);
|
||||
@yellow-9: color(~`colorPalette('@{yellow-6}', 9) `);
|
||||
@yellow-10: color(~`colorPalette('@{yellow-6}', 10) `);
|
||||
|
||||
@volcano-1: color(~`colorPalette('@{volcano-6}', 1) `);
|
||||
@volcano-2: color(~`colorPalette('@{volcano-6}', 2) `);
|
||||
@volcano-3: color(~`colorPalette('@{volcano-6}', 3) `);
|
||||
@volcano-4: color(~`colorPalette('@{volcano-6}', 4) `);
|
||||
@volcano-5: color(~`colorPalette('@{volcano-6}', 5) `);
|
||||
@volcano-6: #fa541c;
|
||||
@volcano-7: color(~`colorPalette('@{volcano-6}', 7) `);
|
||||
@volcano-8: color(~`colorPalette('@{volcano-6}', 8) `);
|
||||
@volcano-9: color(~`colorPalette('@{volcano-6}', 9) `);
|
||||
@volcano-10: color(~`colorPalette('@{volcano-6}', 10) `);
|
||||
|
||||
@geekblue-1: color(~`colorPalette('@{geekblue-6}', 1) `);
|
||||
@geekblue-2: color(~`colorPalette('@{geekblue-6}', 2) `);
|
||||
@geekblue-3: color(~`colorPalette('@{geekblue-6}', 3) `);
|
||||
@geekblue-4: color(~`colorPalette('@{geekblue-6}', 4) `);
|
||||
@geekblue-5: color(~`colorPalette('@{geekblue-6}', 5) `);
|
||||
@geekblue-6: #2f54eb;
|
||||
@geekblue-7: color(~`colorPalette('@{geekblue-6}', 7) `);
|
||||
@geekblue-8: color(~`colorPalette('@{geekblue-6}', 8) `);
|
||||
@geekblue-9: color(~`colorPalette('@{geekblue-6}', 9) `);
|
||||
@geekblue-10: color(~`colorPalette('@{geekblue-6}', 10) `);
|
||||
|
||||
@lime-1: color(~`colorPalette('@{lime-6}', 1) `);
|
||||
@lime-2: color(~`colorPalette('@{lime-6}', 2) `);
|
||||
@lime-3: color(~`colorPalette('@{lime-6}', 3) `);
|
||||
@lime-4: color(~`colorPalette('@{lime-6}', 4) `);
|
||||
@lime-5: color(~`colorPalette('@{lime-6}', 5) `);
|
||||
@lime-6: #a0d911;
|
||||
@lime-7: color(~`colorPalette('@{lime-6}', 7) `);
|
||||
@lime-8: color(~`colorPalette('@{lime-6}', 8) `);
|
||||
@lime-9: color(~`colorPalette('@{lime-6}', 9) `);
|
||||
@lime-10: color(~`colorPalette('@{lime-6}', 10) `);
|
||||
|
||||
@gold-1: color(~`colorPalette('@{gold-6}', 1) `);
|
||||
@gold-2: color(~`colorPalette('@{gold-6}', 2) `);
|
||||
@gold-3: color(~`colorPalette('@{gold-6}', 3) `);
|
||||
@gold-4: color(~`colorPalette('@{gold-6}', 4) `);
|
||||
@gold-5: color(~`colorPalette('@{gold-6}', 5) `);
|
||||
@gold-6: #faad14;
|
||||
@gold-7: color(~`colorPalette('@{gold-6}', 7) `);
|
||||
@gold-8: color(~`colorPalette('@{gold-6}', 8) `);
|
||||
@gold-9: color(~`colorPalette('@{gold-6}', 9) `);
|
||||
@gold-10: color(~`colorPalette('@{gold-6}', 10) `);
|
||||
|
||||
@preset-colors: pink, magenta, red, volcano, orange, yellow, gold, cyan, lime, green, blue, geekblue,
|
||||
purple;
|
||||
|
||||
|
||||
@border-radius-base: 3px;
|
||||
@border-radius-sm: 2px;
|
||||
@shadow-color: rgba(0, 0, 0, 0.05);
|
||||
@shadow-1-down: 4px 4px 40px @shadow-color;
|
||||
@border-color-split: #f4f4f4;
|
||||
@border-color-base: #e5e5e5;
|
||||
@font-size-base: 13px;
|
||||
@text-color: #666;
|
||||
@hover-color: #f9f9fc;
|
127
src/themes/index.less
Normal file
127
src/themes/index.less
Normal file
@ -0,0 +1,127 @@
|
||||
@import '~themes/vars.less';
|
||||
|
||||
body {
|
||||
height: 100%;
|
||||
overflow-y: hidden;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
|
||||
::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
}
|
||||
|
||||
:global {
|
||||
|
||||
.ant-breadcrumb {
|
||||
& > span {
|
||||
&:last-child {
|
||||
color: #999;
|
||||
font-weight: normal;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ant-breadcrumb-link {
|
||||
.anticon + span {
|
||||
margin-left: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.ant-table {
|
||||
.ant-table-thead > tr > th {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.ant-table-tbody > tr > td {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
&.ant-table-small {
|
||||
.ant-table-thead > tr > th {
|
||||
background: #f7f7f7;
|
||||
}
|
||||
|
||||
.ant-table-body > table {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.ant-table-pagination {
|
||||
float: none !important;
|
||||
display: table;
|
||||
margin: 16px auto !important;
|
||||
}
|
||||
|
||||
.ant-popover-inner {
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
box-shadow: 0 0 20px rgba(100, 100, 100, 0.2);
|
||||
}
|
||||
|
||||
.ant-form-item-control {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.ant-modal-mask {
|
||||
background-color: rgba(55, 55, 55, 0.2);
|
||||
}
|
||||
|
||||
.ant-modal-content {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.ant-select-dropdown-menu-item {
|
||||
padding: 12px 16px !important;
|
||||
}
|
||||
|
||||
.margin-right {
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
a:focus {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.ant-table-layout-fixed table {
|
||||
table-layout: auto;
|
||||
}
|
||||
}
|
||||
@media (min-width: 1600px) {
|
||||
:global {
|
||||
.ant-col-xl-48 {
|
||||
width: 20%;
|
||||
}
|
||||
|
||||
.ant-col-xl-96 {
|
||||
width: 40%;
|
||||
}
|
||||
}
|
||||
}
|
||||
@media (max-width: 767px) {
|
||||
:global {
|
||||
.ant-pagination-item,
|
||||
.ant-pagination-next,
|
||||
.ant-pagination-options,
|
||||
.ant-pagination-prev {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.ant-card {
|
||||
.ant-card-head {
|
||||
padding: 0 12px;
|
||||
}
|
||||
|
||||
.ant-card-body {
|
||||
padding: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
35
src/themes/mixin.less
Normal file
35
src/themes/mixin.less
Normal file
@ -0,0 +1,35 @@
|
||||
@import '~themes/default';
|
||||
|
||||
@dark-half: #494949;
|
||||
@purple: #d897eb;
|
||||
@shadow-1: 4px 4px 20px 0 rgba(0, 0, 0, 0.01);
|
||||
@shadow-2: 4px 4px 40px 0 rgba(0, 0, 0, 0.05);
|
||||
@transition-ease-in: all 0.3s ease-out;
|
||||
@transition-ease-out: all 0.3s ease-out;
|
||||
@ease-in: ease-in;
|
||||
|
||||
.text-overflow {
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.text-gradient {
|
||||
background-image: -webkit-gradient(
|
||||
linear,
|
||||
37.219838% 34.532506%,
|
||||
36.425669% 93.178216%,
|
||||
from(#29cdff),
|
||||
to(#0a60ff),
|
||||
color-stop(0.37, #148eff)
|
||||
);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
}
|
||||
|
||||
.background-hover {
|
||||
transition: @transition-ease-in;
|
||||
&:hover {
|
||||
background-color: @hover-color;
|
||||
}
|
||||
}
|
14
src/themes/vars.less
Normal file
14
src/themes/vars.less
Normal file
@ -0,0 +1,14 @@
|
||||
@import '~themes/default.less';
|
||||
@import '~themes/mixin.less';
|
||||
|
||||
@DarkMode-backgroud_container: rgb(24, 26, 27);
|
||||
@DarkMode-backgroud: #2F2E30;
|
||||
@LightMode-backgroud: #fff;
|
||||
|
||||
@DarkMode-color_container: rgb(195, 191, 182);
|
||||
@DarkMode-color: #fff;
|
||||
@LightMode-color: #2F2E30;
|
||||
|
||||
|
||||
|
||||
|
8
src/utils/constant.js
Normal file
8
src/utils/constant.js
Normal file
@ -0,0 +1,8 @@
|
||||
// ** Deprecated Roles ** //
|
||||
// export const ROLE_TYPE = {
|
||||
// ADMIN: 'admin',
|
||||
// DEFAULT: 'guest',
|
||||
// DEVELOPER: 'developer',
|
||||
// }
|
||||
|
||||
export const CANCEL_REQUEST_MESSAGE = 'cancel request';
|
253
src/utils/index.js
Normal file
253
src/utils/index.js
Normal file
@ -0,0 +1,253 @@
|
||||
import { cloneDeep, isString, flow, curry } from 'lodash';
|
||||
import umiRouter from 'umi/router';
|
||||
import pathToRegexp from 'path-to-regexp';
|
||||
import { i18n } from 'config';
|
||||
|
||||
export classnames from 'classnames';
|
||||
export config from 'config';
|
||||
export request from './request';
|
||||
export { Color } from './theme';
|
||||
|
||||
export const { defaultLanguage } = i18n
|
||||
export const languages = i18n.languages.map(item => item.key)
|
||||
|
||||
/**
|
||||
* Query objects that specify keys and values in an array where all values are objects.
|
||||
* @param {array} array An array where all values are objects, like [{key:1},{key:2}].
|
||||
* @param {string} key The key of the object that needs to be queried.
|
||||
* @param {string} value The value of the object that needs to be queried.
|
||||
* @return {object|undefined} Return frist object when query success.
|
||||
*/
|
||||
export function queryArray(array, key, value) {
|
||||
if (!Array.isArray(array)) {
|
||||
return;
|
||||
}
|
||||
return array.find(_ => _[key] === value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an array to a tree-structured array.
|
||||
* @param {array} array The Array need to Converted.
|
||||
* @param {string} id The alias of the unique ID of the object in the array.
|
||||
* @param {string} parentId The alias of the parent ID of the object in the array.
|
||||
* @param {string} children The alias of children of the object in the array.
|
||||
* @return {array} Return a tree-structured array.
|
||||
*/
|
||||
export function arrayToTree(
|
||||
array,
|
||||
id = 'id',
|
||||
parentId = 'pid',
|
||||
children = 'children'
|
||||
) {
|
||||
const result = [];
|
||||
const hash = {};
|
||||
const data = cloneDeep(array);
|
||||
|
||||
data.forEach((item, index) => {
|
||||
hash[data[index][id]] = data[index]
|
||||
})
|
||||
|
||||
data.forEach(item => {
|
||||
const hashParent = hash[item[parentId]]
|
||||
if (hashParent) {
|
||||
!hashParent[children] && (hashParent[children] = [])
|
||||
hashParent[children].push(item)
|
||||
} else {
|
||||
result.push(item);
|
||||
}
|
||||
})
|
||||
return result;
|
||||
}
|
||||
|
||||
export const langFromPath = curry(
|
||||
/**
|
||||
* Query language from pathname.
|
||||
* @param {array} languages Specify which languages are currently available.
|
||||
* @param {string} defaultLanguage Specify the default language.
|
||||
* @param {string} pathname Pathname to be queried.
|
||||
* @return {string} Return the queryed language.
|
||||
*/
|
||||
(languages, defaultLanguage, pathname) => {
|
||||
for (const item of languages) {
|
||||
if (pathname.startsWith(`/${item}/`)) {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
return defaultLanguage;
|
||||
}
|
||||
)(languages)(defaultLanguage)
|
||||
|
||||
export const deLangPrefix = curry(
|
||||
/**
|
||||
* Remove the language prefix in pathname.
|
||||
* @param {array} languages Specify which languages are currently available.
|
||||
* @param {string} pathname Remove the language prefix in the pathname.
|
||||
* @return {string} Return the pathname after removing the language prefix.
|
||||
*/
|
||||
(languages, pathname) => {
|
||||
if (!pathname) {
|
||||
return;
|
||||
}
|
||||
for (const item of languages) {
|
||||
if (pathname.startsWith(`/${item}/`)) {
|
||||
return pathname.replace(`/${item}/`, '/')
|
||||
}
|
||||
}
|
||||
|
||||
return pathname;
|
||||
}
|
||||
)(languages)
|
||||
|
||||
/**
|
||||
* Add the language prefix in pathname.
|
||||
* @param {string} pathname Add the language prefix in the pathname.
|
||||
* @return {string} Return the pathname after adding the language prefix.
|
||||
*/
|
||||
export function addLangPrefix(pathname) {
|
||||
const prefix = langFromPath(window.location.pathname)
|
||||
return `/${prefix}${deLangPrefix(pathname)}`;
|
||||
}
|
||||
|
||||
const routerAddLangPrefix = params => {
|
||||
if (isString(params)) {
|
||||
params = addLangPrefix(params)
|
||||
} else {
|
||||
params.pathname = addLangPrefix(params.pathname)
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjust the router to automatically add the current language prefix before the pathname in push and replace.
|
||||
*/
|
||||
const myRouter = { ...umiRouter }
|
||||
|
||||
myRouter.push = flow(
|
||||
routerAddLangPrefix,
|
||||
umiRouter.push
|
||||
)
|
||||
|
||||
myRouter.replace = flow(
|
||||
routerAddLangPrefix,
|
||||
myRouter.replace
|
||||
)
|
||||
|
||||
export const router = myRouter
|
||||
|
||||
/**
|
||||
* Whether the path matches the regexp if the language prefix is ignored, https://github.com/pillarjs/path-to-regexp.
|
||||
* @param {string|regexp|array} regexp Specify a string, array of strings, or a regular expression.
|
||||
* @param {string} pathname Specify the pathname to match.
|
||||
* @return {array|null} Return the result of the match or null.
|
||||
*/
|
||||
export function pathMatchRegexp(regexp, pathname) {
|
||||
return pathToRegexp(regexp).exec(deLangPrefix(pathname))
|
||||
}
|
||||
|
||||
/**
|
||||
* In an array object, traverse all parent IDs based on the value of an object.
|
||||
* @param {array} array The Array need to Converted.
|
||||
* @param {string} current Specify the value of the object that needs to be queried.
|
||||
* @param {string} parentId The alias of the parent ID of the object in the array.
|
||||
* @param {string} id The alias of the unique ID of the object in the array.
|
||||
* @return {array} Return a key array.
|
||||
*/
|
||||
export function queryPathKeys(array, current, parentId, id = 'id') {
|
||||
const result = [current]
|
||||
const hashMap = new Map()
|
||||
array.forEach(item => hashMap.set(item[id], item))
|
||||
|
||||
const getPath = current => {
|
||||
const currentParentId = hashMap.get(current)[parentId]
|
||||
if (currentParentId) {
|
||||
result.push(currentParentId)
|
||||
getPath(currentParentId)
|
||||
}
|
||||
}
|
||||
|
||||
getPath(current)
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* In an array of objects, specify an object that traverses the objects whose parent ID matches.
|
||||
* @param {array} array The Array need to Converted.
|
||||
* @param {string} current Specify the object that needs to be queried.
|
||||
* @param {string} parentId The alias of the parent ID of the object in the array.
|
||||
* @param {string} id The alias of the unique ID of the object in the array.
|
||||
* @return {array} Return a key array.
|
||||
*/
|
||||
export function queryAncestors(array, current, parentId, id = 'id') {
|
||||
const result = [current]
|
||||
const hashMap = new Map()
|
||||
array.forEach(item => hashMap.set(item[id], item))
|
||||
|
||||
const getPath = current => {
|
||||
const currentParentId = hashMap.get(current[id])[parentId]
|
||||
if (currentParentId) {
|
||||
result.push(hashMap.get(currentParentId))
|
||||
getPath(hashMap.get(currentParentId))
|
||||
}
|
||||
}
|
||||
|
||||
getPath(current)
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Query which layout should be used for the current path based on the configuration.
|
||||
* @param {layouts} layouts Layout configuration.
|
||||
* @param {pathname} pathname Path name to be queried.
|
||||
* @return {string} Return frist object when query success.
|
||||
*/
|
||||
export function queryLayout(layouts, pathname) {
|
||||
let result = 'public';
|
||||
|
||||
const isMatch = regepx => {
|
||||
return regepx instanceof RegExp
|
||||
? regepx.test(pathname)
|
||||
: pathMatchRegexp(regepx, pathname)
|
||||
}
|
||||
|
||||
for (const item of layouts) {
|
||||
let include = false
|
||||
let exclude = false
|
||||
if (item.include) {
|
||||
for (const regepx of item.include) {
|
||||
if (isMatch(regepx)) {
|
||||
include = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (include && item.exclude) {
|
||||
for (const regepx of item.exclude) {
|
||||
if (isMatch(regepx)) {
|
||||
exclude = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (include && !exclude) {
|
||||
result = item.name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
export function getLocale() {
|
||||
return langFromPath(window.location.pathname);
|
||||
}
|
||||
|
||||
export function setLocale(language) {
|
||||
if (getLocale() !== language) {
|
||||
umiRouter.push({
|
||||
pathname: `/${language}${deLangPrefix(window.location.pathname)}`,
|
||||
search: window.location.search,
|
||||
});
|
||||
}
|
||||
}
|
20
src/utils/index.test.js
Normal file
20
src/utils/index.test.js
Normal file
@ -0,0 +1,20 @@
|
||||
import { pathMatchRegexp } from './index'
|
||||
import pathToRegexp from 'path-to-regexp'
|
||||
|
||||
describe('test pathMatchRegexp', () => {
|
||||
it('get right', () => {
|
||||
expect(pathMatchRegexp('/user', '/zh/user')).toEqual(
|
||||
pathToRegexp('/user').exec('/user')
|
||||
)
|
||||
expect(pathMatchRegexp('/user', '/user')).toEqual(
|
||||
pathToRegexp('/user').exec('/user')
|
||||
)
|
||||
|
||||
expect(pathMatchRegexp('/user/:id', '/zh/user/1')).toEqual(
|
||||
pathToRegexp('/user/:id').exec('/user/1')
|
||||
)
|
||||
expect(pathMatchRegexp('/user/:id', '/user/1')).toEqual(
|
||||
pathToRegexp('/user/:id').exec('/user/1')
|
||||
)
|
||||
})
|
||||
})
|
39
src/utils/model.js
Normal file
39
src/utils/model.js
Normal file
@ -0,0 +1,39 @@
|
||||
import modelExtend from 'dva-model-extend'
|
||||
|
||||
export const model = {
|
||||
reducers: {
|
||||
updateState(state, { payload }) {
|
||||
return {
|
||||
...state,
|
||||
...payload,
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
export const pageModel = modelExtend(model, {
|
||||
state: {
|
||||
list: [],
|
||||
pagination: {
|
||||
showSizeChanger: true,
|
||||
showQuickJumper: true,
|
||||
current: 1,
|
||||
total: 0,
|
||||
pageSize: 10,
|
||||
},
|
||||
},
|
||||
|
||||
reducers: {
|
||||
querySuccess(state, { payload }) {
|
||||
const { list, pagination } = payload
|
||||
return {
|
||||
...state,
|
||||
list,
|
||||
pagination: {
|
||||
...state.pagination,
|
||||
...pagination,
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
})
|
97
src/utils/request.js
Normal file
97
src/utils/request.js
Normal file
@ -0,0 +1,97 @@
|
||||
import axios from 'axios'
|
||||
import { cloneDeep, isEmpty } from 'lodash'
|
||||
import pathToRegexp from 'path-to-regexp'
|
||||
import { message } from 'antd'
|
||||
import { CANCEL_REQUEST_MESSAGE } from 'utils/constant'
|
||||
import qs from 'qs'
|
||||
|
||||
const { CancelToken } = axios
|
||||
window.cancelRequest = new Map()
|
||||
|
||||
export default function request(options) {
|
||||
let { data, url, method = 'get' } = options;
|
||||
const cloneData = cloneDeep(data);
|
||||
|
||||
try {
|
||||
let domain = ''
|
||||
const urlMatch = url.match(/[a-zA-z]+:\/\/[^/]*/)
|
||||
if (urlMatch) {
|
||||
;[domain] = urlMatch
|
||||
url = url.slice(domain.length);
|
||||
}
|
||||
|
||||
const match = pathToRegexp.parse(url);
|
||||
url = pathToRegexp.compile(url)(data);
|
||||
|
||||
for (const item of match) {
|
||||
if (item instanceof Object && item.name in cloneData) {
|
||||
delete cloneData[item.name];
|
||||
}
|
||||
}
|
||||
url = domain + url;
|
||||
} catch (e) {
|
||||
message.error(e.message);
|
||||
}
|
||||
|
||||
options.url =
|
||||
method.toLocaleLowerCase() === 'get'
|
||||
? `${url}${isEmpty(cloneData) ? '' : '?'}${qs.stringify(cloneData)}`
|
||||
: url
|
||||
|
||||
options.cancelToken = new CancelToken(cancel => {
|
||||
window.cancelRequest.set(Symbol(Date.now()), {
|
||||
pathname: window.location.pathname,
|
||||
cancel,
|
||||
})
|
||||
})
|
||||
|
||||
return axios(options)
|
||||
.then(response => {
|
||||
const { statusText, status, data } = response
|
||||
|
||||
let result = {}
|
||||
if (typeof data === 'object') {
|
||||
result = data;
|
||||
if (Array.isArray(data)) {
|
||||
result.list = data;
|
||||
}
|
||||
} else {
|
||||
result.data = data;
|
||||
}
|
||||
|
||||
return Promise.resolve({
|
||||
success: true,
|
||||
message: statusText,
|
||||
statusCode: status,
|
||||
...result,
|
||||
})
|
||||
})
|
||||
.catch(error => {
|
||||
const { response, message } = error
|
||||
|
||||
if (String(message) === CANCEL_REQUEST_MESSAGE) {
|
||||
return {
|
||||
success: false,
|
||||
}
|
||||
}
|
||||
|
||||
let msg;
|
||||
let statusCode;
|
||||
|
||||
if (response && response instanceof Object) {
|
||||
const { data, statusText } = response
|
||||
statusCode = response.status
|
||||
msg = data.message || statusText
|
||||
} else {
|
||||
statusCode = 600
|
||||
msg = error.message || 'Network Error'
|
||||
}
|
||||
|
||||
/* eslint-disable */
|
||||
return Promise.reject({
|
||||
success: false,
|
||||
statusCode,
|
||||
message: msg,
|
||||
});
|
||||
})
|
||||
}
|
14
src/utils/theme.js
Normal file
14
src/utils/theme.js
Normal file
@ -0,0 +1,14 @@
|
||||
module.exports = {
|
||||
Color: {
|
||||
green: '#64ea91',
|
||||
blue: '#8fc9fb',
|
||||
purple: '#d897eb',
|
||||
red: '#f69899',
|
||||
yellow: '#f8c82e',
|
||||
peach: '#f797d6',
|
||||
borderBase: '#e5e5e5',
|
||||
borderSplit: '#f4f4f4',
|
||||
grass: '#d6fbb5',
|
||||
sky: '#c1e0fc',
|
||||
},
|
||||
}
|
1488
src/ycore_style.scss
Normal file
1488
src/ycore_style.scss
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user