mirror of
https://gitlab.com/psono/psono-admin-client
synced 2025-04-19 03:22:17 +03:00
library upgrades
Signed-off-by: Sascha Pfeiffer <sascha.pfeiffer@esaqa.com>
This commit is contained in:
parent
7e8793a806
commit
e7b2b71ca7
12
.eslintrc
12
.eslintrc
@ -1,6 +1,6 @@
|
||||
{
|
||||
"extends": "react-app",
|
||||
"rules": {
|
||||
"indent": ["error", 2]
|
||||
}
|
||||
}
|
||||
{
|
||||
"extends": "react-app",
|
||||
"rules": {
|
||||
"indent": "off"
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ test-unittests:
|
||||
except:
|
||||
- schedules
|
||||
stage: test
|
||||
image: psono-docker.jfrog.io/ubuntu:18.04
|
||||
image: psono-docker.jfrog.io/ubuntu:22.04
|
||||
script:
|
||||
- sh ./var/build-ubuntu.sh
|
||||
- npm test -- --coverage
|
||||
@ -37,7 +37,7 @@ test-vulnerability-scan:
|
||||
# except:
|
||||
# - schedules
|
||||
# stage: test
|
||||
# image: psono-docker.jfrog.io/ubuntu:18.04
|
||||
# image: psono-docker.jfrog.io/ubuntu:22.04
|
||||
# script:
|
||||
# - sh ./var/build-ubuntu.sh
|
||||
# - cat ./build/firefox/manifest.json
|
||||
@ -59,7 +59,7 @@ build-docker-image:
|
||||
except:
|
||||
- schedules
|
||||
stage: build
|
||||
image: psono-docker.jfrog.io/ubuntu:18.04
|
||||
image: psono-docker.jfrog.io/ubuntu:22.04
|
||||
services:
|
||||
- docker:18-dind
|
||||
variables:
|
||||
@ -86,7 +86,7 @@ build-webclient:
|
||||
except:
|
||||
- schedules
|
||||
stage: build
|
||||
image: psono-docker.jfrog.io/ubuntu:18.04
|
||||
image: psono-docker.jfrog.io/ubuntu:22.04
|
||||
script:
|
||||
- sh ./var/download_translations_from_artifactory.sh
|
||||
- sh ./var/build-ubuntu.sh
|
||||
@ -111,7 +111,7 @@ release-artifacts:
|
||||
except:
|
||||
- schedules
|
||||
stage: release
|
||||
image: psono-docker.jfrog.io/ubuntu:18.04
|
||||
image: psono-docker.jfrog.io/ubuntu:22.04
|
||||
script:
|
||||
- apt-get update
|
||||
- apt-get install -y curl
|
||||
@ -128,9 +128,15 @@ release-docker:
|
||||
except:
|
||||
- schedules
|
||||
stage: release
|
||||
image: psono-docker.jfrog.io/docker:19.03.8-git
|
||||
image: psono-docker-enterprise.jfrog.io/docker:20.10.17-git
|
||||
services:
|
||||
- docker:18-dind
|
||||
- name: docker:20-dind
|
||||
alias: docker
|
||||
command: ["--tls=false"]
|
||||
variables:
|
||||
DOCKER_DRIVER: overlay2
|
||||
DOCKER_HOST: tcp://docker:2375/
|
||||
DOCKER_TLS_CERTDIR: ""
|
||||
script:
|
||||
- docker info
|
||||
- echo $CI_JOB_TOKEN | docker login --username=gitlab-ci-token --password-stdin registry.gitlab.com
|
||||
@ -146,9 +152,15 @@ release-docker:
|
||||
# except:
|
||||
# - schedules
|
||||
# stage: deploy
|
||||
# image: psono-docker.jfrog.io/docker:19.03.8-git
|
||||
# image: psono-docker-enterprise.jfrog.io/docker:20.10.17-git
|
||||
# services:
|
||||
# - docker:18-dind
|
||||
# - name: docker:20-dind
|
||||
# alias: docker
|
||||
# command: ["--tls=false"]
|
||||
# variables:
|
||||
# DOCKER_DRIVER: overlay2
|
||||
# DOCKER_HOST: tcp://docker:2375/
|
||||
# DOCKER_TLS_CERTDIR: ""
|
||||
# script:
|
||||
# - docker info
|
||||
# - echo $artifactory_credentials | docker login --username=gitlab --password-stdin psono-docker.jfrog.io
|
||||
@ -162,9 +174,15 @@ deploy-docker:
|
||||
except:
|
||||
- schedules
|
||||
stage: deploy
|
||||
image: psono-docker.jfrog.io/docker:19.03.8-git
|
||||
image: psono-docker-enterprise.jfrog.io/docker:20.10.17-git
|
||||
services:
|
||||
- docker:18-dind
|
||||
- name: docker:20-dind
|
||||
alias: docker
|
||||
command: ["--tls=false"]
|
||||
variables:
|
||||
DOCKER_DRIVER: overlay2
|
||||
DOCKER_HOST: tcp://docker:2375/
|
||||
DOCKER_TLS_CERTDIR: ""
|
||||
script:
|
||||
- echo $artifactory_credentials | docker login --username=gitlab --password-stdin psono-docker.jfrog.io
|
||||
- echo $docker_hub_credentials | docker login --username=psonogitlab --password-stdin
|
||||
@ -177,9 +195,15 @@ deploy-github:
|
||||
except:
|
||||
- schedules
|
||||
stage: deploy
|
||||
image: psono-docker.jfrog.io/docker:19.03.8-git
|
||||
image: psono-docker-enterprise.jfrog.io/docker:20.10.17-git
|
||||
services:
|
||||
- docker:18-dind
|
||||
- name: docker:20-dind
|
||||
alias: docker
|
||||
command: ["--tls=false"]
|
||||
variables:
|
||||
DOCKER_DRIVER: overlay2
|
||||
DOCKER_HOST: tcp://docker:2375/
|
||||
DOCKER_TLS_CERTDIR: ""
|
||||
script:
|
||||
- sh ./var/deploy-github.sh
|
||||
environment:
|
||||
@ -193,7 +217,7 @@ deploy-github:
|
||||
# except:
|
||||
# - schedules
|
||||
# stage: deploy
|
||||
# image: psono-docker.jfrog.io/ubuntu:18.04
|
||||
# image: psono-docker.jfrog.io/ubuntu:22.04
|
||||
# script:
|
||||
# - sh ./var/build-ubuntu.sh
|
||||
# - sh ./var/deploy-chrome-extension.sh
|
||||
@ -208,7 +232,7 @@ deploy-github:
|
||||
# except:
|
||||
# - schedules
|
||||
# stage: deploy
|
||||
# image: psono-docker.jfrog.io/ubuntu:18.04
|
||||
# image: psono-docker.jfrog.io/ubuntu:22.04
|
||||
# script:
|
||||
# - sh ./var/build-ubuntu.sh
|
||||
# - sh ./var/deploy-firefox-extension.sh
|
||||
|
44793
package-lock.json
generated
44793
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
58
package.json
58
package.json
@ -10,46 +10,42 @@
|
||||
"homepage": "/portal",
|
||||
"dependencies": {
|
||||
"@date-io/date-fns": "^2.4.0",
|
||||
"@material-ui/core": "^4.9.2",
|
||||
"@material-ui/icons": "^4.9.1",
|
||||
"axios": "^0.21.1",
|
||||
"@material-ui/core": "^4.11.4",
|
||||
"@material-ui/icons": "^4.11.2",
|
||||
"@material-ui/lab": "^4.0.0-alpha.60",
|
||||
"@material-ui/pickers": "^3.3.10",
|
||||
"axios": "^0.24.0",
|
||||
"chartist": "^0.10.1",
|
||||
"chartist-plugin-axistitle": "^0.0.4",
|
||||
"classnames": "^2.2.6",
|
||||
"clientjs": "^0.1.11",
|
||||
"ecma-nacl": "^2.4.2",
|
||||
"enzyme": "^3.11.0",
|
||||
"enzyme-adapter-react-16": "^1.15.2",
|
||||
"font-awesome": "^4.7.0",
|
||||
"husky": "^0.14.3",
|
||||
"i18next": "^15.1.0",
|
||||
"i18next-browser-languagedetector": "^3.0.1",
|
||||
"i18next-xhr-backend": "^2.0.1",
|
||||
"i18next": "^21.4.0",
|
||||
"i18next-browser-languagedetector": "^6.1.2",
|
||||
"i18next-http-backend": "^1.3.2",
|
||||
"js-sha256": "^0.9.0",
|
||||
"js-sha512": "^0.7.1",
|
||||
"js-sha512": "^0.8.0",
|
||||
"lint-staged": "^7.3.0",
|
||||
"material-table": "^1.57.2",
|
||||
"moment": "^2.24.0",
|
||||
"moment-timezone": "^0.5.25",
|
||||
"material-table": "^1.69.3",
|
||||
"moment": "^2.29.4",
|
||||
"moment-timezone": "^0.5.34",
|
||||
"npm-run-all": "^4.1.1",
|
||||
"perfect-scrollbar": "^1.3.0",
|
||||
"prettier": "^1.11.0",
|
||||
"react": "^16.12.0",
|
||||
"react-chartist": "^0.13.1",
|
||||
"react-dom": "^16.12.0",
|
||||
"react": "^17.0.2",
|
||||
"react-chartist": "^0.14.4",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-fontawesome": "^1.6.1",
|
||||
"react-google-maps": "^9.4.5",
|
||||
"react-i18next": "^10.9.0",
|
||||
"react-moment": "^0.9.2",
|
||||
"react-popper": "^0.10.4",
|
||||
"react-redux": "^7.1.3",
|
||||
"react-router-dom": "^5.1.2",
|
||||
"react-scripts": "^3.4.1",
|
||||
"react-spinners": "^0.8.0",
|
||||
"react-swipeable-views": "^0.12.13",
|
||||
"react-test-renderer": "^16.12.0",
|
||||
"react-i18next": "^11.13.0",
|
||||
"react-moment": "^1.1.2",
|
||||
"react-redux": "^7.2.6",
|
||||
"react-router-dom": "^5.3.0",
|
||||
"react-scripts": "^5.0.1",
|
||||
"react-spinners": "^0.13.3",
|
||||
"react-swipeable-views": "^0.14.0",
|
||||
"react-timeout": "^1.0.1",
|
||||
"redux": "^4.0.5",
|
||||
"redux": "^4.1.2",
|
||||
"redux-logger": "^3.0.6",
|
||||
"redux-persist": "^6.0.0",
|
||||
"redux-thunk": "^2.3.0",
|
||||
@ -84,5 +80,11 @@
|
||||
"not ie <= 11",
|
||||
"not op_mini all"
|
||||
],
|
||||
"devDependencies": {}
|
||||
"devDependencies": {
|
||||
"prettier": "^2.6.2",
|
||||
"react-test-renderer": "^17.0.2"
|
||||
},
|
||||
"browser": {
|
||||
"crypto": false
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
{
|
||||
"SIGNED_IN_AS": "Angemeldet als",
|
||||
"PASSWORDS_DONT_MATCH": "Passwörter nicht identisch.",
|
||||
"LDAP_GATEWAY_CONNECTION_ISSUE": "LDAP Gateway Verbindungsprobleme",
|
||||
"LDAP_SERVER_CONNECTION_ISSUE": "LDAP Server Verbindungsprobleme",
|
||||
|
@ -1,4 +1,5 @@
|
||||
{
|
||||
"SIGNED_IN_AS": "Signed in as",
|
||||
"PASSWORDS_DONT_MATCH": "Passwords don't match.",
|
||||
"LDAP_GATEWAY_CONNECTION_ISSUE": "LDAP gateway connection issue",
|
||||
"LDAP_SERVER_CONNECTION_ISSUE": "LDAP server connection issue",
|
||||
|
@ -1,119 +1,113 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
Person //, Notifications, Dashboard, Search,
|
||||
} from '@material-ui/icons';
|
||||
import classNames from 'classnames';
|
||||
import {
|
||||
withStyles,
|
||||
MenuItem,
|
||||
MenuList,
|
||||
Grow,
|
||||
Paper,
|
||||
ClickAwayListener,
|
||||
Hidden
|
||||
} from '@material-ui/core';
|
||||
import Button from '../CustomButtons/Button.jsx';
|
||||
|
||||
import headerLinksStyle from '../../assets/jss/material-dashboard-react/headerLinksStyle';
|
||||
import Poppers from '@material-ui/core/Popper';
|
||||
import { compose } from 'redux';
|
||||
import { withTranslation } from 'react-i18next';
|
||||
import { makeStyles } from '@material-ui/core/styles';
|
||||
import { withStyles, MenuItem, ListItemIcon, Hidden } from '@material-ui/core';
|
||||
import Typography from '@material-ui/core/Typography';
|
||||
import IconButton from '@material-ui/core/IconButton';
|
||||
import AccountCircleIcon from '@material-ui/icons/AccountCircle';
|
||||
import Menu from '@material-ui/core/Menu';
|
||||
import ExitToAppIcon from '@material-ui/icons/ExitToApp';
|
||||
import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
|
||||
|
||||
class HeaderLinks extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
openProfile: null
|
||||
};
|
||||
}
|
||||
import Button from '../CustomButtons/Button.jsx';
|
||||
import headerLinksStyle from '../../assets/jss/material-dashboard-react/headerLinksStyle';
|
||||
import store from '../../services/store';
|
||||
|
||||
render() {
|
||||
const { classes, t } = this.props;
|
||||
const { openProfile } = this.state;
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
listItemIcon: {
|
||||
minWidth: theme.spacing(4),
|
||||
},
|
||||
flex: {
|
||||
flex: 1,
|
||||
},
|
||||
icon: {
|
||||
fontSize: '18px',
|
||||
},
|
||||
topMenuButton: {
|
||||
textTransform: 'none',
|
||||
padding: '8px',
|
||||
},
|
||||
signInText: {
|
||||
marginRight: '10px',
|
||||
display: 'inline',
|
||||
},
|
||||
}));
|
||||
|
||||
const handleClickProfile = event => {
|
||||
if (openProfile && openProfile.contains(event.target)) {
|
||||
this.setState({ openProfile: null });
|
||||
} else {
|
||||
this.setState({ openProfile: event.currentTarget });
|
||||
}
|
||||
};
|
||||
const handleCloseProfile = () => {
|
||||
this.setState({ openProfile: null });
|
||||
};
|
||||
const HeaderLinks = (props) => {
|
||||
const { t } = props;
|
||||
const classes = useStyles();
|
||||
const [anchorTopMenuEl, setAnchorTopMenuEl] = React.useState(null);
|
||||
|
||||
const logout = () => {
|
||||
this.props.logout();
|
||||
this.setState({ openProfile: null });
|
||||
};
|
||||
return (
|
||||
<div>
|
||||
<div className={classes.manager}>
|
||||
const openTopMenu = (event) => {
|
||||
setAnchorTopMenuEl(event.currentTarget);
|
||||
};
|
||||
const closeTopMenu = () => {
|
||||
setAnchorTopMenuEl(null);
|
||||
};
|
||||
|
||||
const logout = () => {
|
||||
props.logout();
|
||||
this.setState({ openProfile: null });
|
||||
};
|
||||
return (
|
||||
<div className={classes.flex}>
|
||||
<div style={{ float: 'right' }}>
|
||||
<Hidden mdUp>
|
||||
<IconButton
|
||||
variant="contained"
|
||||
onClick={openTopMenu}
|
||||
color="primary"
|
||||
className={classes.topMenuButton}
|
||||
>
|
||||
<AccountCircleIcon />
|
||||
</IconButton>
|
||||
</Hidden>
|
||||
<Hidden smDown>
|
||||
<div className={classes.signInText}>
|
||||
{t('SIGNED_IN_AS')}
|
||||
</div>
|
||||
<Button
|
||||
color={
|
||||
window.innerWidth > 959 ? 'transparent' : 'white'
|
||||
}
|
||||
justIcon={window.innerWidth > 959}
|
||||
simple={!(window.innerWidth > 959)}
|
||||
aria-owns={
|
||||
openProfile ? 'profile-menu-list-grow' : null
|
||||
}
|
||||
variant="contained"
|
||||
aria-controls="top-menu"
|
||||
aria-haspopup="true"
|
||||
onClick={handleClickProfile}
|
||||
className={classes.buttonLink}
|
||||
onClick={openTopMenu}
|
||||
color="primary"
|
||||
disableElevation
|
||||
className={classes.topMenuButton}
|
||||
endIcon={<ExpandMoreIcon />}
|
||||
>
|
||||
<Person className={classes.icons} />
|
||||
<Hidden mdUp implementation="css">
|
||||
<p className={classes.linkText}>{t('PROFILE')}</p>
|
||||
</Hidden>
|
||||
{store.getState().user.username}
|
||||
</Button>
|
||||
<Poppers
|
||||
open={Boolean(openProfile)}
|
||||
anchorEl={openProfile}
|
||||
transition
|
||||
disablePortal
|
||||
className={
|
||||
classNames({
|
||||
[classes.popperClose]: !openProfile
|
||||
}) +
|
||||
' ' +
|
||||
classes.popperNav
|
||||
}
|
||||
>
|
||||
{({ TransitionProps, placement }) => (
|
||||
<Grow
|
||||
{...TransitionProps}
|
||||
id="profile-menu-list-grow"
|
||||
style={{
|
||||
transformOrigin:
|
||||
placement === 'bottom'
|
||||
? 'center top'
|
||||
: 'center bottom'
|
||||
}}
|
||||
>
|
||||
<Paper>
|
||||
<ClickAwayListener
|
||||
onClickAway={handleCloseProfile}
|
||||
>
|
||||
<MenuList role="menu">
|
||||
<MenuItem
|
||||
onClick={logout}
|
||||
className={classes.dropdownItem}
|
||||
>
|
||||
{t('LOGOUT')}
|
||||
</MenuItem>
|
||||
</MenuList>
|
||||
</ClickAwayListener>
|
||||
</Paper>
|
||||
</Grow>
|
||||
)}
|
||||
</Poppers>
|
||||
</div>
|
||||
</Hidden>
|
||||
<Menu
|
||||
id="top-menu"
|
||||
anchorEl={anchorTopMenuEl}
|
||||
keepMounted
|
||||
open={Boolean(anchorTopMenuEl)}
|
||||
onClose={closeTopMenu}
|
||||
anchorOrigin={{
|
||||
vertical: 'top',
|
||||
horizontal: 'right',
|
||||
}}
|
||||
transformOrigin={{
|
||||
vertical: 'bottom',
|
||||
horizontal: 'right',
|
||||
}}
|
||||
>
|
||||
<MenuItem onClick={logout}>
|
||||
<ListItemIcon className={classes.listItemIcon}>
|
||||
<ExitToAppIcon className={classes.icon} />
|
||||
</ListItemIcon>
|
||||
<Typography variant="body2">{t('LOGOUT')}</Typography>
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default compose(withTranslation(), withStyles(headerLinksStyle))(
|
||||
HeaderLinks
|
||||
);
|
||||
export default compose(
|
||||
withTranslation(),
|
||||
withStyles(headerLinksStyle)
|
||||
)(HeaderLinks);
|
||||
|
@ -1,7 +0,0 @@
|
||||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
import App from './App';
|
||||
|
||||
it('renders without crashing', () => {
|
||||
shallow(<App />);
|
||||
});
|
145
src/i18n.js
145
src/i18n.js
@ -1,10 +1,145 @@
|
||||
import i18n from 'i18next';
|
||||
import Backend from 'i18next-xhr-backend';
|
||||
import Backend from 'i18next-http-backend';
|
||||
import LanguageDetector from 'i18next-browser-languagedetector';
|
||||
import { initReactI18next } from 'react-i18next';
|
||||
// import i18next from 'i18next';
|
||||
// import moment from 'moment'
|
||||
|
||||
const languages = {
|
||||
ca: {
|
||||
code: 'ca',
|
||||
lng_code: 'LANG_CA',
|
||||
lng_title_native: 'Català',
|
||||
active: true,
|
||||
},
|
||||
cs: {
|
||||
code: 'cs',
|
||||
lng_code: 'LANG_CS',
|
||||
lng_title_native: 'Česky',
|
||||
active: true,
|
||||
},
|
||||
de: {
|
||||
code: 'de',
|
||||
lng_code: 'LANG_DE',
|
||||
lng_title_native: 'Deutsch',
|
||||
active: true,
|
||||
},
|
||||
en: {
|
||||
code: 'en',
|
||||
lng_code: 'LANG_EN',
|
||||
lng_title_native: 'English',
|
||||
active: true,
|
||||
default: true,
|
||||
},
|
||||
es: {
|
||||
code: 'es',
|
||||
lng_code: 'LANG_ES',
|
||||
lng_title_native: 'Español',
|
||||
active: true,
|
||||
},
|
||||
fi: {
|
||||
code: 'fi',
|
||||
lng_code: 'LANG_FI',
|
||||
lng_title_native: 'Suomi',
|
||||
active: true,
|
||||
},
|
||||
fr: {
|
||||
code: 'fr',
|
||||
lng_code: 'LANG_FR',
|
||||
lng_title_native: 'Français',
|
||||
active: true,
|
||||
},
|
||||
hr: { code: 'hr', lng_code: 'LANG_HR', lng_title_native: 'Hrvatski' },
|
||||
hu: {
|
||||
code: 'hu',
|
||||
lng_code: 'LANG_HU',
|
||||
lng_title_native: 'Magyar',
|
||||
active: true,
|
||||
},
|
||||
it: {
|
||||
code: 'it',
|
||||
lng_code: 'LANG_IT',
|
||||
lng_title_native: 'Italiano',
|
||||
active: true,
|
||||
},
|
||||
ja: { code: 'ja', lng_code: 'LANG_JA', lng_title_native: '日本語' },
|
||||
ko: { code: 'ko', lng_code: 'LANG_KO', lng_title_native: '한국어' },
|
||||
nl: {
|
||||
code: 'nl',
|
||||
lng_code: 'LANG_NL',
|
||||
lng_title_native: 'Nederlands',
|
||||
active: true,
|
||||
},
|
||||
pl: {
|
||||
code: 'pl',
|
||||
lng_code: 'LANG_PL',
|
||||
lng_title_native: 'Polskie',
|
||||
active: true,
|
||||
},
|
||||
pt: {
|
||||
code: 'pt',
|
||||
lng_code: 'LANG_PT_PT',
|
||||
lng_title_native: 'Portuguese',
|
||||
active: true,
|
||||
},
|
||||
'pt-br': {
|
||||
code: 'pt-br',
|
||||
lng_code: 'LANG_PT_BR',
|
||||
lng_title_native: 'Portuguese (BR)',
|
||||
active: true,
|
||||
},
|
||||
ru: {
|
||||
code: 'ru',
|
||||
lng_code: 'LANG_RU',
|
||||
lng_title_native: 'Русский',
|
||||
active: true,
|
||||
},
|
||||
vi: { code: 'vi', lng_code: 'LANG_VI', lng_title_native: '' }, // lng_title_native incorrect
|
||||
da: { code: 'da', lng_code: 'LANG_DA', lng_title_native: '' }, // lng_title_native incorrect
|
||||
sv: {
|
||||
code: 'sv',
|
||||
lng_code: 'LANG_SV',
|
||||
lng_title_native: 'Svenska',
|
||||
active: true,
|
||||
},
|
||||
sk: {
|
||||
code: 'sk',
|
||||
lng_code: 'LANG_SK',
|
||||
lng_title_native: 'Slovák',
|
||||
active: true,
|
||||
},
|
||||
uk: {
|
||||
code: 'uk',
|
||||
lng_code: 'LANG_UK',
|
||||
lng_title_native: 'Український',
|
||||
active: true,
|
||||
},
|
||||
no: {
|
||||
code: 'no',
|
||||
lng_code: 'LANG_NO',
|
||||
lng_title_native: 'Norsk',
|
||||
active: true,
|
||||
},
|
||||
he: { code: 'he', lng_code: 'LANG_HE', lng_title_native: '' }, // lng_title_native incorrect
|
||||
ar: { code: 'ar', lng_code: 'LANG_AR', lng_title_native: '' }, // lng_title_native incorrect
|
||||
hi: { code: 'hi', lng_code: 'LANG_HI', lng_title_native: '' }, // lng_title_native incorrect
|
||||
bn: {
|
||||
code: 'bn',
|
||||
lng_code: 'LANG_BN',
|
||||
lng_title_native: 'বাংলা',
|
||||
active: true,
|
||||
},
|
||||
zh_CN: { code: 'zh_CN', lng_code: 'LANG_ZH_CN', lng_title_native: '漢語' },
|
||||
};
|
||||
|
||||
const supportedLngs = [];
|
||||
|
||||
Object.entries(languages).forEach(([key, value]) => {
|
||||
if (value.active) {
|
||||
supportedLngs.push(value.code);
|
||||
}
|
||||
});
|
||||
|
||||
i18n
|
||||
// load translation using xhr -> see /public/locales
|
||||
// learn more: https://github.com/i18next/i18next-xhr-backend
|
||||
@ -18,15 +153,17 @@ i18n
|
||||
// for all options read: https://www.i18next.com/overview/configuration-options
|
||||
.init({
|
||||
fallbackLng: 'en',
|
||||
supportedLngs: supportedLngs,
|
||||
load: 'languageOnly',
|
||||
debug: process.env.NODE_ENV === 'development',
|
||||
backend: {
|
||||
// for all available options read the backend's repository readme file
|
||||
loadPath: process.env.PUBLIC_URL + '/locales/{{lng}}/{{ns}}.json'
|
||||
loadPath: process.env.PUBLIC_URL + '/locales/{{lng}}/{{ns}}.json',
|
||||
},
|
||||
|
||||
interpolation: {
|
||||
escapeValue: false // not needed for react as it escapes by default
|
||||
}
|
||||
escapeValue: false, // not needed for react as it escapes by default
|
||||
},
|
||||
});
|
||||
|
||||
export default i18n;
|
||||
|
@ -2,6 +2,7 @@ import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { I18nextProvider } from 'react-i18next';
|
||||
import { Provider } from 'react-redux';
|
||||
import CssBaseline from '@material-ui/core/CssBaseline';
|
||||
import 'moment-timezone';
|
||||
|
||||
import i18n from './i18n';
|
||||
@ -54,6 +55,7 @@ import './assets/css/material-dashboard-react.css';
|
||||
ReactDOM.render(
|
||||
<Provider store={store}>
|
||||
<I18nextProvider i18n={i18n}>
|
||||
<CssBaseline />
|
||||
<App />
|
||||
</I18nextProvider>
|
||||
</Provider>,
|
||||
|
@ -5,13 +5,12 @@ import SecurityReports from '../views/SecurityReports/Index';
|
||||
// import TableList from '../views/TableList/TableList.jsx';
|
||||
// import Typography from '../views/Typography/Typography.jsx';
|
||||
// import Icons from '../views/Icons/Icons.jsx';
|
||||
// import Maps from '../views/Maps/Maps.jsx';
|
||||
// import NotificationsPage from '../views/Notifications/Notifications.jsx';
|
||||
|
||||
import {
|
||||
Dashboard,
|
||||
Person,
|
||||
Timeline
|
||||
Timeline,
|
||||
// ContentPaste,
|
||||
// LibraryBooks,
|
||||
// BubbleChart,
|
||||
@ -25,22 +24,22 @@ let routes = [
|
||||
sidebarName: 'DASHBOARD',
|
||||
navbarName: 'DASHBOARD',
|
||||
icon: Dashboard,
|
||||
component: DashboardPage
|
||||
component: DashboardPage,
|
||||
},
|
||||
{
|
||||
path: '/users',
|
||||
sidebarName: 'USERS',
|
||||
navbarName: 'USERS',
|
||||
icon: Person,
|
||||
component: Users
|
||||
component: Users,
|
||||
},
|
||||
{
|
||||
path: '/security-reports',
|
||||
sidebarName: 'SECURITY_REPORTS',
|
||||
navbarName: 'SECURITY_REPORTS',
|
||||
icon: Timeline,
|
||||
component: SecurityReports
|
||||
}
|
||||
component: SecurityReports,
|
||||
},
|
||||
];
|
||||
|
||||
if (!process.env.NODE_ENV || process.env.NODE_ENV === 'development') {
|
||||
@ -95,7 +94,7 @@ if (!process.env.NODE_ENV || process.env.NODE_ENV === 'development') {
|
||||
}
|
||||
|
||||
routes = routes.concat([
|
||||
{ redirect: true, path: '/', to: '/dashboard', navbarName: 'Redirect' }
|
||||
{ redirect: true, path: '/', to: '/dashboard', navbarName: 'Redirect' },
|
||||
]);
|
||||
|
||||
export default routes;
|
||||
|
@ -1,357 +0,0 @@
|
||||
import React from 'react';
|
||||
import cryptoLibrary from './cryptoLibrary';
|
||||
import converter from './converter';
|
||||
import helper from './helper';
|
||||
|
||||
describe('Service: cryptoLibrary test suite #1', function() {
|
||||
it('cryptoLibrary exists', function() {
|
||||
expect(cryptoLibrary).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Service: cryptoLibrary test suite #2', function() {
|
||||
it('cryptoLibrary exists', function() {
|
||||
expect(cryptoLibrary).toBeDefined();
|
||||
});
|
||||
|
||||
it('cryptoLibrary randomBytes', function() {
|
||||
expect(cryptoLibrary.randomBytes(16).length).toBe(16);
|
||||
expect(cryptoLibrary.randomBytes(32).length).toBe(32);
|
||||
expect(cryptoLibrary.randomBytes(64).length).toBe(64);
|
||||
});
|
||||
|
||||
/*
|
||||
it("randomBytes doesn't return the the same in 1000 repetitions", function () {
|
||||
var num, numbers, random_numbers;
|
||||
numbers = 1000;
|
||||
random_numbers = (function () {
|
||||
var i, ref, results;
|
||||
results = [];
|
||||
for (num = i = 1, ref = numbers; 1 <= ref ? i <= ref : i >= ref; num = 1 <= ref ? ++i : --i) {
|
||||
results.push(cryptoLibrary.randomBytes(32));
|
||||
}
|
||||
return results;
|
||||
})();
|
||||
return expect((new Set(random_numbers)).size).toBe(numbers);
|
||||
});
|
||||
*/
|
||||
|
||||
it('generate_authkey works', function() {
|
||||
expect(
|
||||
cryptoLibrary.generate_authkey('test@example.com', '123456')
|
||||
).toBe(
|
||||
'1ad635d464917db74a127b3de19c5bec9df932472c3e31ca8b18e872c641e8c828e9da35543ef36c0b013ab6c549a7ddbfe7b52b08e9e8704aca69f4c2fd68ea'
|
||||
);
|
||||
return expect(
|
||||
cryptoLibrary.generate_authkey('test2@example.com', '1234567')
|
||||
).toBe(
|
||||
'3d97a9354e99760d543761c168b655ccc7e565ddd6ef1d6b83df66d8b50bc62708dfe2c2dc56a628fa24b71bf75fc49db85ce11fd64fadb0e458f3780dde1899'
|
||||
);
|
||||
});
|
||||
|
||||
it('generate_authkey works', function() {
|
||||
expect(
|
||||
cryptoLibrary.generate_authkey('test@example.com', '123456')
|
||||
).toBe(
|
||||
'1ad635d464917db74a127b3de19c5bec9df932472c3e31ca8b18e872c641e8c828e9da35543ef36c0b013ab6c549a7ddbfe7b52b08e9e8704aca69f4c2fd68ea'
|
||||
);
|
||||
return expect(
|
||||
cryptoLibrary.generate_authkey('test2@example.com', '1234567')
|
||||
).toBe(
|
||||
'3d97a9354e99760d543761c168b655ccc7e565ddd6ef1d6b83df66d8b50bc62708dfe2c2dc56a628fa24b71bf75fc49db85ce11fd64fadb0e458f3780dde1899'
|
||||
);
|
||||
});
|
||||
|
||||
it('generate_secret_key returns a 32 bytes long key', function() {
|
||||
let bytes;
|
||||
bytes = 32;
|
||||
return expect(
|
||||
converter.from_hex(cryptoLibrary.generate_secret_key()).length
|
||||
).toBe(bytes);
|
||||
});
|
||||
|
||||
it('generate_public_private_keypair returns a pair of 32 bytes long keys', function() {
|
||||
let bytes, pair;
|
||||
bytes = 32;
|
||||
pair = cryptoLibrary.generate_public_private_keypair();
|
||||
expect(converter.from_hex(pair.private_key).length).toBe(bytes);
|
||||
return expect(converter.from_hex(pair.public_key).length).toBe(bytes);
|
||||
});
|
||||
|
||||
it('generate_public_private_keypair returned pairs are different', function() {
|
||||
let pair1, pair2;
|
||||
pair1 = cryptoLibrary.generate_public_private_keypair();
|
||||
pair2 = cryptoLibrary.generate_public_private_keypair();
|
||||
expect(pair1.private_key).toBe(pair1.private_key);
|
||||
expect(pair1.private_key).not.toBe(pair2.private_key);
|
||||
return expect(pair1.public_key).not.toBe(pair2.public_key);
|
||||
});
|
||||
|
||||
it('generate_user_sauce', function() {
|
||||
let bytes, user_sauce1, user_sauce2;
|
||||
bytes = 32;
|
||||
user_sauce1 = cryptoLibrary.generate_user_sauce();
|
||||
user_sauce2 = cryptoLibrary.generate_user_sauce();
|
||||
expect(converter.from_hex(user_sauce1).length).toBe(bytes);
|
||||
return expect(user_sauce1).not.toBe(user_sauce2);
|
||||
});
|
||||
|
||||
it('get_checksum', function() {
|
||||
return expect(cryptoLibrary.get_checksum('RBLbEDsvgnU', 2)).toBe('4A');
|
||||
});
|
||||
|
||||
it('generate_recovery_code', function() {
|
||||
const recovery_code = cryptoLibrary.generate_recovery_code();
|
||||
|
||||
expect(recovery_code.bytes.length).toBe(16);
|
||||
expect(recovery_code.hex).toBe(converter.to_hex(recovery_code.bytes));
|
||||
expect(recovery_code.hex).toBe(
|
||||
converter.words_to_hex(recovery_code.words)
|
||||
);
|
||||
expect(recovery_code.hex).toBe(
|
||||
converter.base58_to_hex(recovery_code.base58)
|
||||
);
|
||||
|
||||
const chunks = helper.split_string_in_chunks(recovery_code.base58, 11);
|
||||
|
||||
for (let i = 0; i < chunks.length; i++) {
|
||||
chunks[i] += cryptoLibrary.get_checksum(chunks[i], 2);
|
||||
}
|
||||
|
||||
return expect(recovery_code.base58_checksums).toBe(chunks.join(''));
|
||||
});
|
||||
|
||||
it('recovery_code_strip_checksums', function() {
|
||||
const stripped = cryptoLibrary.recovery_code_strip_checksums(
|
||||
'UaKSKNNixJY2ARqGDKXduo4c2N'
|
||||
);
|
||||
return expect(stripped).toBe('UaKSKNNixJYRqGDKXduo4c');
|
||||
});
|
||||
|
||||
it('recovery_code_strip_checksums chunk < 2', function() {
|
||||
try {
|
||||
cryptoLibrary.recovery_code_strip_checksums('A');
|
||||
} catch (err) {
|
||||
return expect(err.name).toBe('InvalidRecoveryCodeException');
|
||||
}
|
||||
return expect('This line').toBe('should never be reached');
|
||||
});
|
||||
|
||||
it('recovery_password_chunk_pass_checksum positive', function() {
|
||||
return expect(
|
||||
cryptoLibrary.recovery_password_chunk_pass_checksum('UaKSKNNixJY2A')
|
||||
).toBeTruthy();
|
||||
});
|
||||
|
||||
it('recovery_password_chunk_pass_checksum negative', function() {
|
||||
return expect(
|
||||
cryptoLibrary.recovery_password_chunk_pass_checksum('UaKSKNNixJY2B')
|
||||
).toBeFalsy();
|
||||
});
|
||||
|
||||
it('decrypt_secret', function() {
|
||||
let data, nonce, password, text, user_sauce;
|
||||
data = '12345';
|
||||
password = 'myPassword';
|
||||
user_sauce =
|
||||
'6168de45af90c335967a8f9eae76f8f19bcb42fb8c3f602fee35f7617acdc489';
|
||||
nonce = 'ff786149d8242bb7802379bc5fd2f9ccc744a2e1f18bb0a8';
|
||||
text = 'a92528f78ca1f0812a4fb2ee5de4d16eb75d434318';
|
||||
return expect(
|
||||
cryptoLibrary.decrypt_secret(text, nonce, password, user_sauce)
|
||||
).toBe(data);
|
||||
});
|
||||
|
||||
it('encrypt_secret', function() {
|
||||
let bytes_nonce,
|
||||
data,
|
||||
encrypted_data,
|
||||
encrypted_data2,
|
||||
password,
|
||||
user_sauce;
|
||||
bytes_nonce = 24;
|
||||
data = '12345';
|
||||
password = 'myPassword';
|
||||
user_sauce =
|
||||
'6168de45af90c335967a8f9eae76f8f19bcb42fb8c3f602fee35f7617acdc489';
|
||||
encrypted_data = cryptoLibrary.encrypt_secret(
|
||||
data,
|
||||
password,
|
||||
user_sauce
|
||||
);
|
||||
expect(encrypted_data.text).not.toBe(void 0);
|
||||
expect(encrypted_data.nonce).not.toBe(void 0);
|
||||
expect(converter.from_hex(encrypted_data.text).length).toBeGreaterThan(
|
||||
0
|
||||
);
|
||||
expect(converter.from_hex(encrypted_data.nonce).length).toBe(
|
||||
bytes_nonce
|
||||
);
|
||||
expect(
|
||||
cryptoLibrary.decrypt_secret(
|
||||
encrypted_data.text,
|
||||
encrypted_data.nonce,
|
||||
password,
|
||||
user_sauce
|
||||
)
|
||||
).toBe(data);
|
||||
encrypted_data2 = cryptoLibrary.encrypt_secret(
|
||||
data,
|
||||
password,
|
||||
user_sauce
|
||||
);
|
||||
return expect(encrypted_data.nonce).not.toBe(encrypted_data2.nonce);
|
||||
});
|
||||
|
||||
it('decrypt_data works', function() {
|
||||
let data, nonce, secret_key, text;
|
||||
data = '12345';
|
||||
secret_key =
|
||||
'9f3edbf7760d8ec1e8fd4a9c623b4fe569f324bf42c78770ef0a40a56495f92d';
|
||||
nonce = 'd65673e9abcf379493bba61a576535a82bcf8d735a915390';
|
||||
text = '9429f56f028a82ec44651bb7ea6b9f8baab3cd137e';
|
||||
return expect(cryptoLibrary.decrypt_data(text, nonce, secret_key)).toBe(
|
||||
data
|
||||
);
|
||||
});
|
||||
|
||||
it('encrypt_data works', function() {
|
||||
let bytes_nonce, data, encrypted_data, encrypted_data2, secret_key;
|
||||
bytes_nonce = 24;
|
||||
data = '12345';
|
||||
secret_key =
|
||||
'9f3edbf7760d8ec1e8fd4a9c623b4fe569f324bf42c78770ef0a40a56495f92d';
|
||||
encrypted_data = cryptoLibrary.encrypt_data(data, secret_key);
|
||||
expect(encrypted_data.text).not.toBe(void 0);
|
||||
expect(encrypted_data.nonce).not.toBe(void 0);
|
||||
expect(converter.from_hex(encrypted_data.text).length).toBeGreaterThan(
|
||||
0
|
||||
);
|
||||
expect(converter.from_hex(encrypted_data.nonce).length).toBe(
|
||||
bytes_nonce
|
||||
);
|
||||
expect(
|
||||
cryptoLibrary.decrypt_data(
|
||||
encrypted_data.text,
|
||||
encrypted_data.nonce,
|
||||
secret_key
|
||||
)
|
||||
).toBe(data);
|
||||
encrypted_data2 = cryptoLibrary.encrypt_data(data, secret_key);
|
||||
return expect(encrypted_data.nonce).not.toBe(encrypted_data2.nonce);
|
||||
});
|
||||
|
||||
it('decrypt_data_public_key works', function() {
|
||||
let data, nonce, pair, pair2, text;
|
||||
data = '12345';
|
||||
pair = {
|
||||
public_key:
|
||||
'ed7293c239164855aca4c2e6edb19e09bba41e3451603ec427782d45f2d57b39',
|
||||
private_key:
|
||||
'035f8aa4c86658a36d995df47c8e3d1e9a7a2a2f3efdcbdc1451ed4354350660'
|
||||
};
|
||||
pair2 = {
|
||||
public_key:
|
||||
'57531faba711e6e9bdea25229e63db4ce6eb79f0872d97cbfec74df0382dbf3a',
|
||||
private_key:
|
||||
'a04c3fbcb4dcf5df44bc433668bb686aac8991f83e993b971e73a0b37ace362c'
|
||||
};
|
||||
nonce = '538a2fc024e1ff7a791da88874099709bdb60ad62653529b';
|
||||
text = '0eedec49906748988b011741c8df4214e4dbeeda76';
|
||||
return expect(
|
||||
cryptoLibrary.decrypt_data_public_key(
|
||||
text,
|
||||
nonce,
|
||||
pair2.public_key,
|
||||
pair.private_key
|
||||
)
|
||||
).toBe(data);
|
||||
});
|
||||
|
||||
it('encrypt_data_public_key works', function() {
|
||||
let bytes_nonce, data, encrypted_data, encrypted_data2, pair, pair2;
|
||||
bytes_nonce = 24;
|
||||
data = '12345';
|
||||
pair = {
|
||||
public_key:
|
||||
'ed7293c239164855aca4c2e6edb19e09bba41e3451603ec427782d45f2d57b39',
|
||||
private_key:
|
||||
'035f8aa4c86658a36d995df47c8e3d1e9a7a2a2f3efdcbdc1451ed4354350660'
|
||||
};
|
||||
pair2 = {
|
||||
public_key:
|
||||
'57531faba711e6e9bdea25229e63db4ce6eb79f0872d97cbfec74df0382dbf3a',
|
||||
private_key:
|
||||
'a04c3fbcb4dcf5df44bc433668bb686aac8991f83e993b971e73a0b37ace362c'
|
||||
};
|
||||
encrypted_data = cryptoLibrary.encrypt_data_public_key(
|
||||
data,
|
||||
pair.public_key,
|
||||
pair2.private_key
|
||||
);
|
||||
expect(encrypted_data.text).not.toBe(void 0);
|
||||
expect(encrypted_data.nonce).not.toBe(void 0);
|
||||
expect(converter.from_hex(encrypted_data.text).length).toBeGreaterThan(
|
||||
0
|
||||
);
|
||||
expect(converter.from_hex(encrypted_data.nonce).length).toBe(
|
||||
bytes_nonce
|
||||
);
|
||||
expect(
|
||||
cryptoLibrary.decrypt_data_public_key(
|
||||
encrypted_data.text,
|
||||
encrypted_data.nonce,
|
||||
pair2.public_key,
|
||||
pair.private_key
|
||||
)
|
||||
).toBe(data);
|
||||
encrypted_data2 = cryptoLibrary.encrypt_data_public_key(
|
||||
data,
|
||||
pair.public_key,
|
||||
pair2.private_key
|
||||
);
|
||||
return expect(encrypted_data.nonce).not.toBe(encrypted_data2.nonce);
|
||||
});
|
||||
|
||||
it('generate_uuid', function() {
|
||||
const regex = /^[0-9A-F]{8}-[0-9A-F]{4}-[4][0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i;
|
||||
expect(regex.test(cryptoLibrary.generate_uuid())).toBe(true);
|
||||
});
|
||||
|
||||
it("nacl's signing.verify works", function() {
|
||||
const nacl = require('ecma-nacl');
|
||||
// signing key pair can be generated from some seed array, which can
|
||||
// either be random itself, or be generated from a password
|
||||
const pair = nacl.signing.generate_keypair(
|
||||
cryptoLibrary.randomBytes(32)
|
||||
);
|
||||
|
||||
// make signature bytes, for msg
|
||||
const msgSig = nacl.signing.signature(
|
||||
converter.encode_utf8(
|
||||
'test message that is some nice text or whatever that needs to be encrypted'
|
||||
),
|
||||
pair.skey
|
||||
);
|
||||
|
||||
// verify signature
|
||||
const sigIsOK = nacl.signing.verify(
|
||||
msgSig,
|
||||
converter.encode_utf8(
|
||||
'test message that is some nice text or whatever that needs to be encrypted'
|
||||
),
|
||||
pair.pkey
|
||||
);
|
||||
expect(sigIsOK).toBe(true);
|
||||
});
|
||||
|
||||
it('validate_signature', function() {
|
||||
expect(
|
||||
cryptoLibrary.validate_signature(
|
||||
'test message that is some nice text or whatever that needs to be encrypted',
|
||||
'6e3302a696092fe3893d971391f94f2cb850d19fbbae9978122f0f465593bc06e65440e0ec929805b58e63fe719983201754a2a578c906c18b8ffa71e3234502',
|
||||
'967fd5c3c8386609c1ac57209a6f68a147a56518a7ed5df3285beea58d671f62'
|
||||
)
|
||||
).toBe(true);
|
||||
});
|
||||
});
|
@ -1,19 +1,14 @@
|
||||
import { configure } from 'enzyme';
|
||||
import Adapter from 'enzyme-adapter-react-16';
|
||||
|
||||
const localStorageMock = {
|
||||
getItem: jest.fn(),
|
||||
setItem: jest.fn(),
|
||||
clear: jest.fn()
|
||||
};
|
||||
global.localStorage = localStorageMock;
|
||||
|
||||
jest.mock('./services/clientjs', () => {
|
||||
return {
|
||||
getFingerprint: () => {
|
||||
return 'dummy_fingerprint';
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
configure({ adapter: new Adapter() });
|
||||
const localStorageMock = {
|
||||
getItem: jest.fn(),
|
||||
setItem: jest.fn(),
|
||||
clear: jest.fn(),
|
||||
};
|
||||
global.localStorage = localStorageMock;
|
||||
|
||||
jest.mock('./services/clientjs', () => {
|
||||
return {
|
||||
getFingerprint: () => {
|
||||
return 'dummy_fingerprint';
|
||||
},
|
||||
};
|
||||
});
|
||||
|
@ -1,103 +0,0 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
withScriptjs,
|
||||
withGoogleMap,
|
||||
GoogleMap,
|
||||
Marker
|
||||
} from 'react-google-maps';
|
||||
|
||||
const CustomSkinMap = withScriptjs(
|
||||
withGoogleMap(props => (
|
||||
<GoogleMap
|
||||
defaultZoom={13}
|
||||
defaultCenter={{ lat: 40.748817, lng: -73.985428 }}
|
||||
defaultOptions={{
|
||||
scrollwheel: false,
|
||||
zoomControl: true,
|
||||
styles: [
|
||||
{
|
||||
featureType: 'water',
|
||||
stylers: [
|
||||
{ saturation: 43 },
|
||||
{ lightness: -11 },
|
||||
{ hue: '#0088ff' }
|
||||
]
|
||||
},
|
||||
{
|
||||
featureType: 'road',
|
||||
elementType: 'geometry.fill',
|
||||
stylers: [
|
||||
{ hue: '#ff0000' },
|
||||
{ saturation: -100 },
|
||||
{ lightness: 99 }
|
||||
]
|
||||
},
|
||||
{
|
||||
featureType: 'road',
|
||||
elementType: 'geometry.stroke',
|
||||
stylers: [{ color: '#808080' }, { lightness: 54 }]
|
||||
},
|
||||
{
|
||||
featureType: 'landscape.man_made',
|
||||
elementType: 'geometry.fill',
|
||||
stylers: [{ color: '#ece2d9' }]
|
||||
},
|
||||
{
|
||||
featureType: 'poi.park',
|
||||
elementType: 'geometry.fill',
|
||||
stylers: [{ color: '#ccdca1' }]
|
||||
},
|
||||
{
|
||||
featureType: 'road',
|
||||
elementType: 'labels.text.fill',
|
||||
stylers: [{ color: '#767676' }]
|
||||
},
|
||||
{
|
||||
featureType: 'road',
|
||||
elementType: 'labels.text.stroke',
|
||||
stylers: [{ color: '#ffffff' }]
|
||||
},
|
||||
{ featureType: 'poi', stylers: [{ visibility: 'off' }] },
|
||||
{
|
||||
featureType: 'landscape.natural',
|
||||
elementType: 'geometry.fill',
|
||||
stylers: [{ visibility: 'on' }, { color: '#b8cb93' }]
|
||||
},
|
||||
{
|
||||
featureType: 'poi.park',
|
||||
stylers: [{ visibility: 'on' }]
|
||||
},
|
||||
{
|
||||
featureType: 'poi.sports_complex',
|
||||
stylers: [{ visibility: 'on' }]
|
||||
},
|
||||
{
|
||||
featureType: 'poi.medical',
|
||||
stylers: [{ visibility: 'on' }]
|
||||
},
|
||||
{
|
||||
featureType: 'poi.business',
|
||||
stylers: [{ visibility: 'simplified' }]
|
||||
}
|
||||
]
|
||||
}}
|
||||
>
|
||||
<Marker position={{ lat: 40.748817, lng: -73.985428 }} />
|
||||
</GoogleMap>
|
||||
))
|
||||
);
|
||||
|
||||
class Maps extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<CustomSkinMap
|
||||
googleMapURL="https://maps.googleapis.com/maps/api/js?key=YOUR_KEY_HERE"
|
||||
loadingElement={<div style={{ height: `100%` }} />}
|
||||
containerElement={<div style={{ height: `100vh` }} />}
|
||||
mapElement={<div style={{ height: `100%` }} />}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Maps;
|
@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
apt-get update && \
|
||||
apt-get install -y curl apt-transport-https zip && \
|
||||
curl -sL https://deb.nodesource.com/setup_10.x | bash - && \
|
||||
curl -sL https://deb.nodesource.com/setup_16.x | bash - && \
|
||||
apt-get update && \
|
||||
apt-get -y install nodejs && \
|
||||
npm --version && \
|
||||
|
Loading…
x
Reference in New Issue
Block a user