;\n\t\t}\n\t});\n};\n\nexport default FormBuilder;\n\nFormBuilder.propTypes = {\n\tprofilePicture: PropTypes.bool,\n};\n","import React, { useContext } from 'react';\n\nimport styledComponents from 'styled-components';\nimport { styled } from '@material-ui/core/styles';\nimport { LoginContext } from '@karpeleslab/klb-react-services';\n\nconst Div = styledComponents.div``;\nexport const OAuth2Wrapper = styled(Div)(style => {\n\treturn {\n\t\tdisplay: 'flex',\n\t\talignItems: 'center',\n\t\tjustifyContent: 'center',\n\t\t'& > *': {\n\t\t\tmargin: style.theme.spacing(4),\n\t\t},\n\t};\n});\nexport const OauthBtn = styled(Div)(style => {\n\treturn {\n\t\tborderRadius: '50%',\n\t\twidth: style.theme.spacing(7),\n\t\theight: style.theme.spacing(7),\n\t\tbackgroundPosition: '50%',\n\t\tbackgroundRepeat: 'no-repeat',\n\t\tbackgroundAttachment: 'scroll',\n\t\tbackgroundSize: '50%',\n\t\toverflow: 'hidden',\n\t\ttextIndent: '-1000px',\n\t\tcursor: style.button ? 'pointer' : 'inherit',\n\t\tbackgroundColor: style.backgroundColor,\n\t\tbackgroundImage: `url(${style.logo})`,\n\t\t'&:hover': {\n\t\t\topacity: style.button ? 0.4 : 1\n\t\t},\n\t\t'&.twitter': {\n\t\t\tbackgroundSize: '60%'\n\t\t},\n\t\t'&.line': {\n\t\t\tbackgroundSize: '70%'\n\t\t},\n\t\t'&.facebook': {\n\t\t\tbackgroundSize: '30%'\n\t\t}\n\t};\n});\n\nconst OauthBtnsBuilder = () => {\n\tconst { oauthFields, onOauthClicked } = useContext(LoginContext);\n\tif (!oauthFields)\n\t\treturn <>>;\n\n\treturn (\n\t\t
\n\t\t\t{\n\t\t\t\toauthFields.map(\n\t\t\t\t\t(field) => (\n\t\t\t\t\t\t {\n\t\t\t\t\t\t\t\tonOauthClicked(field.id);\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\talt={field.info.Name}\n\t\t\t\t\t\t\tclassName={field.info.Token_Name}\n\t\t\t\t\t\t\tbackgroundColor={field.button['background-color']}\n\t\t\t\t\t\t\tlogo={field.button['logo']}\n\t\t\t\t\t\t/>\n\t\t\t\t\t)\n\t\t\t\t)\n\t\t\t}\n\t\t \n\t);\n};\n\nexport default OauthBtnsBuilder;\n\nOauthBtnsBuilder.propTypes = {};\n","import React, { useContext } from 'react';\nimport { CSSTransition, SwitchTransition } from 'react-transition-group';\nimport Grid from '@material-ui/core/Grid';\nimport Loader from './../layout/Loader/Loader';\nimport ButtonsBuilder from './ButtonsBuilder';\nimport FormBuilder from './FormBuilder';\nimport OauthBtnsBuilder from './OauthBtnsBuilder';\nimport PropTypes from 'prop-types';\nimport { Button } from '@material-ui/core';\nimport useMediaQuery from '@material-ui/core/useMediaQuery';\nimport { LoginContext } from '@karpeleslab/klb-react-services';\n\n\nconst Login = ({ TitleComponent = 'h2', ButtonComponent = Button, profilePicture = true }) => {\n\tconst isMobile = useMediaQuery(theme => theme.breakpoints.down('sm'));\n\n\tconst { loading, handleSubmit, formTitle } = useContext(LoginContext);\n\n\treturn (\n\t\t
\n\t\t\t node.addEventListener('transitionend', done, false)}\n\t\t\t\tclassNames={isMobile ? 'u-transition--zoom' : 'u-transition--lateral'}\n\t\t\t>\n\t\t\t\t{\n\t\t\t\t\t!loading ? (\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t{formTitle} \n\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t) : (\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t
\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t \n\t\t \n\t);\n};\n\nexport default Login;\n\nLogin.propTypes = {\n\tTitleComponent: PropTypes.node,\n\tButtonComponent: PropTypes.any,\n\tprofilePicture: PropTypes.bool,\n};\n","import React from 'react';\nimport PageContainer from '../Container/PageContainer';\nimport Loader from './Loader';\nimport PropTypes from 'prop-types';\n\nconst PageLoader = ({ message = '' }) => {\n\treturn (\n\t\t
\n\t\t\t\n\t\t \n\t);\n};\n\nexport default PageLoader;\n\nPageLoader.propTypes = {\n\tmessage: PropTypes.string\n};\n","import React, { useEffect, useState } from 'react';\nimport { Redirect as ReactRedirect } from 'react-router-dom';\nimport PageLoader from '../../layout/Loader/PageLoader';\nimport PropTypes from 'prop-types';\n\nconst Redirect = ({ target }) => {\n\tconst [isExternal] = useState(target.startsWith('http'));\n\n\tuseEffect(() => {\n\t\tif (!isExternal || typeof window === 'undefined') return;\n\t\twindow.location.replace(target);\n\t}, [isExternal, target]);\n\n\tif (isExternal) return
;\n\treturn
;\n};\n\nexport default Redirect;\n\nRedirect.propTypes = {\n\ttarget: PropTypes.string.isRequired\n};\n","export default __webpack_public_path__ + \"static/media/shells_logo_vertical_white.9a0f9cbb.svg\";","import React, { useContext } from 'react';\nimport LoginComponent from './../../components/Login/Login';\nimport Helmet from 'react-helmet';\nimport { useHistory } from 'react-router';\nimport { useTranslation } from 'react-i18next';\nimport { getPrefix } from '@karpeleslab/klbfw';\nimport { UserContext } from '../../context/UserContext';\nimport { getShellsRoute } from '../../components/RouteController/Factory';\nimport Redirect from '../../components/core/utils/Redirect';\nimport Grid from '@material-ui/core/Grid';\nimport Hidden from '@material-ui/core/Hidden';\nimport Box from '@material-ui/core/Box';\nimport Graphic from '../../assets/img/shells_logo_vertical_white.svg';\nimport makeStyles from '@material-ui/core/styles/makeStyles';\nimport Button from '../../components/core/input/Button';\nimport { LoginContextContainer } from '@karpeleslab/klb-react-services';\n\nconst useStyles = makeStyles((theme) => {\n\treturn {\n\t\tfillHeight: {\n\t\t\theight: '100vh',\n\t\t},\n\t\tcontainer: {\n\t\t\twidth: '100%',\n\t\t\t[theme.breakpoints.down('sm')]: {\n\t\t\t\tpaddingRight: '12px',\n\t\t\t\tpaddingLeft: '12px',\n\t\t\t\tmargin: '0px'\n\t\t\t}\n\t\t},\n\n\t};\n});\n\nconst Login = () => {\n\tconst [user, setUser] = useContext(UserContext);\n\tconst history = useHistory();\n\tconst { t } = useTranslation();\n\tconst classes = useStyles();\n\n\tconst onValidated = (data) => {\n\t\tsetUser({\n\t\t\tloggedIn: true,\n\t\t\tuser: { data: data.user }\n\t\t});\n\t\thistory.push(data.Redirect.replace(getPrefix(), ''));\n\t};\n\n\tif (user.loggedIn)\n\t\treturn ;\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t{ /* https://devhints.io/html-meta */}\n\t\t\t\t{t('login')} \n\t\t\t \n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t \n\n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default Login;\n","import React, { useEffect, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\n\nimport Dialog from '@material-ui/core/Dialog';\nimport DialogActions from '@material-ui/core/DialogActions';\nimport DialogContent from '@material-ui/core/DialogContent';\nimport DialogContentText from '@material-ui/core/DialogContentText';\nimport DialogTitle from '@material-ui/core/DialogTitle';\nimport TextField from '@material-ui/core/TextField';\nimport PropTypes from 'prop-types';\nimport Button from '../../core/input/Button';\n\nconst RequestPasswordDialog = ({ open, setOpen, closeCallback }) => {\n\tconst { t } = useTranslation();\n\tconst [pwd, setPwd] = useState('');\n\tconst handleUnlock = () => {\n\t\tsetOpen(false);\n\t\tcloseCallback(pwd);\n\t};\n\n\tuseEffect(() => {\n\t\tsetPwd('');\n\t}, [open]);\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t{t('security_password_required_title')}\n\t\t\t \n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{t('security_password_required_description')}\n\t\t\t\t \n\t\t\t\t setPwd(e.target.value)}\n\t\t\t\t\tvariant=\"outlined\"\n\t\t\t\t\ttype='password'\n\t\t\t\t/>\n\t\t\t \n\t\t\t\n\t\t\t\t setOpen(false)}\n\t\t\t\t>\n\t\t\t\t\t{t('back_btn')}\n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t{t('unlock_btn')}\n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default RequestPasswordDialog;\n\nRequestPasswordDialog.propTypes = {\n\topen: PropTypes.bool.isRequired,\n\tsetOpen: PropTypes.func.isRequired,\n\tcloseCallback: PropTypes.func.isRequired\n};\n","import React, { useContext, useEffect, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Grid, TextField } from '@material-ui/core';\nimport RequestPasswordDialog from './RequestPasswordDialog';\nimport { UserContext } from '../../../context/UserContext';\nimport PropTypes from 'prop-types';\nimport Button from '../../core/input/Button';\nimport { useUserSetEmail } from '@karpeleslab/klb-react-services';\n\nconst ChangeEmail = ({ changingInfo = false }) => {\n\tconst [user, setUser] = useContext(UserContext);\n\tconst [email, setEmail] = useState(user.user.data.Email);\n\tconst [requestPwdOpen, setRequestPwdOpen] = useState(false);\n\tconst [saveEnabled, setSaveEnabled] = useState(false);\n\tconst [setNewEmail, loadingNewEmail] = useUserSetEmail('@');\n\tconst { t } = useTranslation();\n\n\tuseEffect(() => {\n\t\tif (email !== user.user.data.Email && !loadingNewEmail) {\n\t\t\tsetSaveEnabled(true);\n\t\t\treturn;\n\t\t}\n\t\tsetSaveEnabled(false);\n\t}, [email, user, loadingNewEmail]);\n\n\tconst handleChangeEmail = pwd => {\n\t\tsetNewEmail(email, pwd)\n\t\t\t.then(res => {\n\t\t\t\tif (res) {\n\t\t\t\t\tconst tmp = { ...user };\n\t\t\t\t\ttmp.user.data = res;\n\t\t\t\t\tsetUser(tmp);\n\t\t\t\t}\n\t\t\t});\n\t};\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t setEmail(e.target.value)}\n\t\t\t\t/>\n\t\t\t \n\t\t\t\n\t\t\t\t\n\t\t\t\t\t {\n\t\t\t\t\t\t\tif (user.user.data.Has_Password)\n\t\t\t\t\t\t\t\tsetRequestPwdOpen(true);\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\thandleChangeEmail(null);\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t{t('save_btn')}\n\t\t\t\t\t \n\n\t\t\t\t \n\t\t\t \n\t\t\t{user.user.data.Has_Password &&\n\t\t\t \n\t\t\t}\n\t\t \n\t);\n};\n\nexport default ChangeEmail;\n\nChangeEmail.propTypes = {\n\tchangingInfo: PropTypes.bool,\n};\n","import React from 'react';\nimport Typography from '@material-ui/core/Typography';\nimport makeStyles from '@material-ui/core/styles/makeStyles';\nimport PropTypes from 'prop-types';\n\nconst styles = makeStyles(() => ({\n\ttitle: {\n\t\tflex: '1 1 100%',\n\t},\n}));\nexport const Title = ({ children }) => {\n\tconst classes = styles();\n\treturn (\n\t\t\n\t\t\t{children}\n\t\t \n\t);\n};\n\nTitle.propTypes = {\n\tchildren: PropTypes.oneOfType([\n\t\tPropTypes.arrayOf(PropTypes.node),\n\t\tPropTypes.node\n\t])\n};\n","import React from 'react';\nimport { useTranslation } from 'react-i18next';\n\nimport ChangeEmail from './ChangeEmail';\nimport { Grid } from '@material-ui/core';\nimport { Title } from '../../core/typography/Title';\n\nconst Account = () => {\n\tconst { t } = useTranslation();\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t{t('profile_account')} \n\t\t\t \n\t\t\t\n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default Account;\n","import React, { useContext, useEffect, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Grid, TextField } from '@material-ui/core';\nimport { Title } from '../../core/typography/Title';\nimport { UserContext } from '../../../context/UserContext';\nimport Button from '../../core/input/Button';\nimport { useUserProfileUpdate } from '@karpeleslab/klb-react-services';\n\nconst Information = () => {\n\tconst { t } = useTranslation();\n\tconst [saveEnabled, setSaveEnabled] = useState(false);\n\tconst [user, setUser] = useContext(UserContext);\n\tconst [username, setUsername] = useState(user.user.data.Profile.Display_Name);\n\tconst [updateProfile, changingInfo] = useUserProfileUpdate('@');\n\n\n\tuseEffect(() => {\n\t\tif (username !== user.user.data.Profile.Display_Name) {\n\t\t\tsetSaveEnabled(true);\n\t\t\treturn;\n\t\t}\n\n\t\tsetSaveEnabled(false);\n\t}, [username, user]);\n\n\tconst handleSave = () => {\n\t\tlet p = {\n\t\t\tDisplay_Name: username\n\t\t};\n\n\t\tupdateProfile(p)\n\t\t\t.then(res => {\n\t\t\t\tif (res) {\n\t\t\t\t\tconst tmp = { ...user };\n\t\t\t\t\ttmp.user.data.Profile = res;\n\t\t\t\t\tsetUser(tmp);\n\t\t\t\t}\n\t\t\t});\n\t};\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t{t('profile_information')} \n\t\t\t \n\t\t\t\n\t\t\t\t setUsername(e.target.value)}\n\t\t\t\t/>\n\t\t\t \n\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t{t('save_btn')}\n\t\t\t\t\t \n\n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default Information;\n","import PropTypes from 'prop-types';\nimport React from 'react';\nimport ListItemAvatar from '@material-ui/core/ListItemAvatar';\nimport { OauthBtn } from '../../../Login/OauthBtnsBuilder';\nimport ListItemText from '@material-ui/core/ListItemText';\nimport CircularProgress from '@material-ui/core/CircularProgress';\nimport ListItem from '@material-ui/core/ListItem';\nimport { useConsumerLink } from '@karpeleslab/klb-react-services';\n\nconst OAuthItem = ({ consumer, setSelected, disabled = false, selected = false }) => {\n\tconst [fetchConsumerLink] = useConsumerLink(consumer.OAuth2_Consumer__);\n\n\tconst handleConsumerClick = () => {\n\t\tsetSelected(consumer);\n\t\tfetchConsumerLink(window.location.href)\n\t\t\t.then(d => window.location = d.redirect_url);\n\t};\n\n\treturn (\n\t\t handleConsumerClick(consumer)}\n\t\t\tkey={consumer.OAuth2_Consumer__}\n\t\t\tselected={selected}\n\t\t>\n\t\t\t\n\t\t\t\t \n\t\t\t \n\t\t\t\n\t\t\t{selected && }\n\t\t \n\t);\n};\n\nexport default OAuthItem;\n\nOAuthItem.propTypes = {\n\tconsumer: PropTypes.object.isRequired,\n\tdisabled: PropTypes.bool,\n\tselected: PropTypes.bool,\n\tsetSelected: PropTypes.func.isRequired\n};\n","import React, { useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { useRest } from '@karpeleslab/react-klbfw-hooks';\nimport Dialog from '@material-ui/core/Dialog';\nimport DialogActions from '@material-ui/core/DialogActions';\nimport DialogContent from '@material-ui/core/DialogContent';\nimport DialogContentText from '@material-ui/core/DialogContentText';\nimport DialogTitle from '@material-ui/core/DialogTitle';\nimport Grid from '@material-ui/core/Grid';\nimport List from '@material-ui/core/List';\nimport CircularProgress from '@material-ui/core/CircularProgress';\nimport PropTypes from 'prop-types';\nimport Button from '../../../core/input/Button';\nimport OAuthItem from './OAuthItem';\nimport { getOAuth2ConsumersEndpoint } from '@karpeleslab/klb-react-services';\n\nconst AddDialog = ({ open, setOpen }) => {\n\tconst { t } = useTranslation();\n\tconst [selectedConsumer, setSelectedConsumer] = useState(null);\n\tconst [consumers] = useRest(getOAuth2ConsumersEndpoint());\n\n\treturn (\n\t\t\n\t\t\t{t('link_service')} \n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{t('link_service_description')}\n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t{selectedConsumer && }\n\t\t\t\t\t\t{!selectedConsumer &&\n\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tconsumers && consumers.data && consumers.data.map(\n\t\t\t\t\t\t\t\t\tconsumer => {\n\t\t\t\t\t\t\t\t\t\tconst selected = selectedConsumer && selectedConsumer.OAuth2_Consumer__ === consumer.OAuth2_Consumer__;\n\n\t\t\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t\t\t );\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t
\n\t\t\t\t\t\t}\n\t\t\t\t\t \n\t\t\t\t \n\t\t\t \n\t\t\t\n\t\t\t\t setOpen(false)} disabled={!!selectedConsumer}\n\t\t\t\t>\n\t\t\t\t\t{t('close_btn')}\n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default AddDialog;\n\nAddDialog.propTypes = {\n\topen: PropTypes.bool.isRequired,\n\tsetOpen: PropTypes.func.isRequired,\n};\n","export default __webpack_public_path__ + \"static/media/oauthTokens.5687e287.svg\";","import React from 'react';\nimport { Trans, useTranslation } from 'react-i18next';\n\nimport EmptyState from './../../../../core/feedback/State/Empty';\nimport Graphic from './../../../../../assets/img/oauthTokens.svg';\n\nconst Empty = () => {\n\tconst { t } = useTranslation();\n\n\treturn (\n\t\t\n\t\t\t\tsample \n\t\t\t\tsample \n\t\t\t}\n\t\t\tgraphic={Graphic}\n\t\t/>\n\t);\n\n};\n\nexport default Empty;\n","import React from 'react';\nimport PropTypes from 'prop-types';\n\nconst TableDefinition = () => {\n\treturn (<>>);\n};\n\nexport default TableDefinition;\n\nTableDefinition.propTypes = {\n\tname: PropTypes.string.isRequired,\n\tlabel: PropTypes.string,\n\tsortable: PropTypes.bool,\n};\n","import TableSortLabel from '@material-ui/core/TableSortLabel';\nimport React from 'react';\nimport PropTypes from 'prop-types';\n\nexport default function SortableCell({ sort, field, label, onClick }) {\n\tlet direction = 'asc';\n\tlet sortHandlerDir = 'asc';\n\n\tif (sort && field in sort) {\n\t\tdirection = sort[field].toLowerCase();\n\t\tif (direction === 'asc') sortHandlerDir = 'DESC';\n\t\telse if (direction === 'desc') sortHandlerDir = 'ASC';\n\t}\n\n\treturn (\n\t\t {\n\t\t\t\tonClick(field, sortHandlerDir);\n\t\t\t}}\n\t\t\tactive={sort && field in sort}\n\t\t\tdirection={direction}>{label} \n\t);\n}\n\nSortableCell.propTypes = {\n\tsort: PropTypes.object,\n\tfield: PropTypes.string.isRequired,\n\tlabel: PropTypes.string,\n\tonClick: PropTypes.func.isRequired,\n};\n","import React from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Link } from 'react-router-dom';\n\nimport Box from '@material-ui/core/Box';\nimport Typography from '@material-ui/core/Typography';\nimport PropTypes from 'prop-types';\nimport Button from '../input/Button';\nimport Helmet from 'react-helmet';\nimport { useHistory } from 'react-router';\nimport useMediaQuery from '@material-ui/core/useMediaQuery';\n\nconst PageTitle = ({ backButton = false, backButtonText = null, children, title }) => {\n\tconst { t } = useTranslation();\n\tconst history = useHistory();\n\tconst isBackBtnUrl = typeof backButton === 'string' || backButton instanceof String;\n\tconst isMobile = useMediaQuery(theme => theme.breakpoints.down('xs'));\n\n\treturn (\n\t\t<>\n\t\t\t\n\t\t\t\t{ /* https://devhints.io/html-meta */}\n\t\t\t\t{title} \n\t\t\t \n\t\t\t{\n\t\t\t\tbackButton &&\n\t\t\t\t\n\t\t\t\t\t history.goBack() }\n\t\t\t\t\t\t}\n\t\t\t\t\t>\n\t\t\t\t\t\t{backButtonText || t('back_btn')}\n\t\t\t\t\t \n\t\t\t\t \n\t\t\t}\n\t\t\t\n\t\t\t\t{children ?? title}\n\t\t\t \n\t\t>\n\t);\n};\n\nexport default PageTitle;\n\nPageTitle.propTypes = {\n\tchildren: PropTypes.oneOfType([\n\t\tPropTypes.arrayOf(PropTypes.node),\n\t\tPropTypes.node\n\t]),\n\tbackButton: PropTypes.oneOfType([\n\t\tPropTypes.string,\n\t\tPropTypes.bool\n\t]),\n\tbackButtonText: PropTypes.string,\n\ttitle: PropTypes.string,\n};\n","import React from 'react';\nimport { Title } from './Title';\nimport { Toolbar as MUToolbar } from '@material-ui/core';\nimport Grid from '@material-ui/core/Grid';\nimport PropTypes from 'prop-types';\nimport PageTitle from './PageTitle';\n\n\nconst Toolbar = ({ title, children, disableGutters = false, justify = 'space-between', alignItems = 'stretch', startAdornment = null, endAdornment = null, pageTitle = false, pageTitleProps = {}, childItemProps = {}, titleItemProps = {}, toolbarProps = {} }) => {\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t{startAdornment && {startAdornment} }\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t{!pageTitle && {title} }\n\t\t\t\t\t\t\t{pageTitle && }\n\t\t\t\t\t\t \n\t\t\t\t\t\t{endAdornment && {endAdornment} }\n\n\t\t\t\t\t \n\t\t\t\t \n\t\t\t\t{children && {children} }\n\t\t\t \n\t\t \n\t);\n};\n\nexport default Toolbar;\n\nToolbar.propTypes = {\n\talignItems: PropTypes.string,\n\tchildItemProps: PropTypes.object,\n\tchildren: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]),\n\tdisableGutters: PropTypes.bool,\n\tendAdornment: PropTypes.node,\n\tjustify: PropTypes.string,\n\tpageTitle: PropTypes.bool,\n\tpageTitleProps: PropTypes.object,\n\tstartAdornment: PropTypes.node,\n\ttitle: PropTypes.any,\n\ttitleItemProps: PropTypes.object,\n\ttoolbarProps: PropTypes.object\n};\n","import React, { useEffect, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\n\nimport Box from '@material-ui/core/Box';\nimport CircularProgress from '@material-ui/core/CircularProgress';\nimport ClearIcon from '@material-ui/icons/Clear';\nimport DeleteForeverIcon from '@material-ui/icons/DeleteForever';\nimport Grid from '@material-ui/core/Grid';\nimport { IconButton } from '@material-ui/core';\nimport InputAdornment from '@material-ui/core/InputAdornment';\nimport MenuItem from '@material-ui/core/MenuItem';\nimport SearchIcon from '@material-ui/icons/Search';\nimport TextField from '@material-ui/core/TextField';\nimport Toolbar from '../../typography/Toolbar';\nimport PropTypes from 'prop-types';\nimport Button from '../../input/Button';\n\nconst TableToolbar = (\n\t{\n\t\ttitle,\n\t\tloading,\n\t\tsearch,\n\t\tsearchKey,\n\t\tfilters,\n\t\tchangeFiltersAndPaging,\n\t\tsearchCriteria = [], // [{ field: string, value: ''|[value1, value2, ...] }]\n\t\textra = [], //Array of extra element that will be append at the right of the search icon (used to add button etc)\n\t\ttoolbarProps = {}\n\t}\n) => {\n\tconst { t } = useTranslation();\n\tconst [showSearch, setShowSearch] = useState(false);\n\tconst [searchText, setSearchText] = useState('');\n\tconst [showCriteria, setShowCriteria] = useState(false);\n\tconst [currentCriterias, setCurrentCriterias] = useState([]);\n\n\tuseEffect(() => {\n\t\tif (searchKey in filters) {\n\t\t\tsetShowSearch(true);\n\n\t\t\tif (searchText !== filters[searchKey])\n\t\t\t\tsetSearchText(filters[searchKey]['$prefix']);\n\t\t}\n\t\t// eslint-disable-next-line\n\t}, [filters]);\n\n\tconst handleAdvancedSearch = () => {\n\t\tconst params = {};\n\t\tcurrentCriterias.forEach(c => {\n\t\t\tif (c.value.length > 0)\n\t\t\t\tparams[c.field] = c.value;\n\t\t});\n\t\tchangeFiltersAndPaging(params, { page_no: 1 });\n\t};\n\n\tconst handleSearch = () => {\n\t\tchangeFiltersAndPaging({ [searchKey]: { '$prefix': searchText } }, { page_no: 1 });\n\t};\n\n\tconst handleClear = () => {\n\t\tsetSearchText('');\n\t\tsetShowSearch(false);\n\t\tchangeFiltersAndPaging({}, { page_no: 1 });\n\t};\n\n\tconst handleSearchKeyPress = e => {\n\t\tif (e.key !== 'Enter') return;\n\t\thandleSearch();\n\t};\n\n\tconst handleSearchKeyUp = e => {\n\t\tif (e.key !== 'Escape') return;\n\t\tsetShowSearch(false);\n\t\thandleClear();\n\t};\n\n\tconst newCriteria = (e) => {\n\t\tsetCurrentCriterias([...currentCriterias, {\n\t\t\tfield: e.target.value,\n\t\t\tvalue: ''\n\t\t}]);\n\t};\n\n\tconst unsetCriteria = field => {\n\t\tconst idx = currentCriterias.findIndex(c => c.field === field);\n\t\tif (idx < 0)\n\t\t\treturn;\n\n\t\tconst tmp = [...currentCriterias];\n\t\ttmp.splice(idx, 1);\n\t\tsetCurrentCriterias(tmp);\n\t};\n\n\tconst updateCriteria = (field, value) => {\n\t\tconst idx = currentCriterias.findIndex(c => c.field === field);\n\t\tif (idx < 0)\n\t\t\treturn;\n\n\t\tconst tmp = [...currentCriterias];\n\t\ttmp[idx] = { field, value };\n\t\tsetCurrentCriterias(tmp);\n\t};\n\n\treturn (\n\t\t<>\n\t\t\t setSearchText(e.target.value)}\n\t\t\t\t\t\tonKeyPress={handleSearchKeyPress}\n\t\t\t\t\t\tonKeyUp={handleSearchKeyUp}\n\t\t\t\t\t\tInputProps={\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tendAdornment: (\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\tstartAdornment: (\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t handleSearch()} size='small'>\n\t\t\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t )\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t/> :\n\t\t\t\t\ttitle}\n\t\t\t\tendAdornment={\n\t\t\t\t\tloading ?\n\t\t\t\t\t\t :\n\t\t\t\t\t\tnull\n\t\t\t\t}\n\t\t\t>\n\t\t\t\t\n\t\t\t\t\t{/* remove 'false' in the following condition to display the advanced search */}\n\t\t\t\t\t{searchCriteria.length > 0 && false &&\n\t\t\t\t\t\n\t\t\t\t\t\t setShowCriteria(!showCriteria)}>\n\t\t\t\t\t\t\t{t('toggle_advanced_search', { state: showCriteria ? 'Hide' : 'Show' })}\n\t\t\t\t\t\t \n\t\t\t\t\t }\n\t\t\t\t\t{search &&\n\t\t\t\t\t\n\t\t\t\t\t\t setShowSearch(!showSearch)}>\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t }\n\n\t\t\t\t\t{extra && extra.map((e, idx) => {e} )}\n\t\t\t\t \n\n\t\t\t \n\t\t\t{showCriteria &&\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t{searchCriteria.filter(option => currentCriterias.findIndex(c => c.field === option.field) < 0).length > 0 &&\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t{searchCriteria.filter(option => currentCriterias.findIndex(c => c.field === option.field) < 0).map(option => (\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t{t(`label_criteria_${option.field.replace('.', '_')}`)}\n\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t \n\t\t\t\t\t\t}\n\t\t\t\t\t \n\t\t\t\t\t{\n\t\t\t\t\t\tcurrentCriterias.map(c => (\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t updateCriteria(c.field, e.target.value)}\n\t\t\t\t\t\t\t\t\tvalue={c.value}\n\t\t\t\t\t\t\t\t\tvariant='outlined'\n\t\t\t\t\t\t\t\t\tfullWidth\n\t\t\t\t\t\t\t\t\tInputProps={{\n\t\t\t\t\t\t\t\t\t\tendAdornment:\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t unsetCriteria(c.field)}\n\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t))\n\t\t\t\t\t}\n\t\t\t\t\t{\n\t\t\t\t\t\tcurrentCriterias.length > 0 &&\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t c.value.length > 0).length <= 0}\n\t\t\t\t\t\t\t\tonClick={handleAdvancedSearch}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{t('search')}\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t}\n\t\t\t\t \n\t\t\t \n\t\t\t}\n\t\t>\n\t);\n};\n\nexport default TableToolbar;\n\nTableToolbar.propTypes = {\n\tchangeFiltersAndPaging: PropTypes.func.isRequired,\n\textra: PropTypes.array,\n\tfilters: PropTypes.object.isRequired,\n\tloading: PropTypes.bool,\n\tsearch: PropTypes.bool,\n\tsearchCriteria: PropTypes.array,\n\tsearchKey: PropTypes.string,\n\ttitle: PropTypes.string,\n\ttoolbarProps: PropTypes.object\n};\n","import React, { useEffect, useRef, useState } from 'react';\nimport makeStyles from '@material-ui/core/styles/makeStyles';\nimport TableHead from '@material-ui/core/TableHead';\nimport TableRow from '@material-ui/core/TableRow';\nimport TableCell from '@material-ui/core/TableCell';\nimport SortableCell from './SortableCell';\nimport TableBody from '@material-ui/core/TableBody';\nimport TableFooter from '@material-ui/core/TableFooter';\nimport { Table as MUITable } from '@material-ui/core';\nimport TablePagination from '@material-ui/core/TablePagination';\nimport TablePaginationActions from '@material-ui/core/TablePagination/TablePaginationActions';\nimport TableContainer from '@material-ui/core/TableContainer';\nimport { Skeleton } from '@material-ui/lab';\nimport queryString from 'query-string';\nimport { useHistory, useLocation } from 'react-router-dom';\nimport { useTranslation } from 'react-i18next';\nimport Paper from '@material-ui/core/Paper';\nimport Grid from '@material-ui/core/Grid';\nimport TableToolbar from './TableToolbar';\nimport PropTypes from 'prop-types';\n\nconst useStyles = makeStyles(theme => ({\n\tcTable: {\n\t\t'& a:not([role=\"button\"])': {\n\t\t\tcolor: `${theme.palette.text.primary} !important`\n\t\t}\n\t}\n}));\n\nconst Table = ({ title, data, loading = false, fetch, children, search = true, searchKey, initialFilters = {}, paperProps = {}, searchCriteria = [], extra = [], emptyState = null, emptyText = null, RowComponent = TableRow, rowProps = {}, toolbarProps = {}, ...etc }) => {\n\tconst history = useHistory();\n\tconst location = useLocation();\n\tconst { t } = useTranslation();\n\tconst classes = useStyles();\n\n\tconst [paging, setPaging] = useState({});\n\tconst [filters, setFilters] = useState(initialFilters);\n\tconst [hasFilters, setHasFilters] = useState(false);\n\n\tconst displayData = () => {\n\t\tconst list = loading ?\n\t\t\t[...Array(paging.results_per_page ?? 10).keys()] :\n\t\t\t(data ? data.data ?? [] : []);\n\n\t\tif (list.length < 1) { // empty\n\t\t\treturn (\n\t\t\t\t\n\t\t\t\t\t{emptyText ?? t('table_empty_text')}\n\t\t\t\t \n\t\t\t );\n\t\t}\n\n\t\treturn list.map((d, rowIdx) =>\n\t\t\t\n\t\t\t\t{(Array.isArray(children) ? children : [children]).map(\n\t\t\t\t\t(child, cellIdx) => {\n\t\t\t\t\t\tif (!child)\n\t\t\t\t\t\t\treturn null;\n\n\t\t\t\t\t\t// eslint-disable-next-line\n\t\t\t\t\t\tconst { name, label, sortable, children, ...cellProps } = child.props;\n\n\t\t\t\t\t\treturn \n\t\t\t\t\t\t\t{loading && }\n\t\t\t\t\t\t\t{!loading && (children ?\n\t\t\t\t\t\t\t\tchildren(d, rowIdx, cellIdx) :\n\t\t\t\t\t\t\t\td[name])\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t ;\n\t\t\t\t\t}\n\t\t\t\t)}\n\t\t\t \n\t\t);\n\t};\n\n\tconst changePageHandler = (e, newPage) => {\n\t\t// The pagination component start at 0;...\n\t\tif (loading) return;\n\t\thandleFiltersAndPagingChange(null, { ...paging, page_no: parseInt(newPage) + 1 });\n\t};\n\n\tconst changeResultPerPageHandler = e => {\n\t\tif (loading) return;\n\t\thandleFiltersAndPagingChange(null, { ...paging, results_per_page: e.target.value });\n\t};\n\n\tconst changeFiltersHandler = filters => {\n\t\tif (loading) return;\n\t\tconst currentParams = queryString.parse(location.search);\n\t\tconst params = {};\n\t\t// We remove all existing filters\n\t\tObject.keys(currentParams ?? {}).forEach(pK => {\n\t\t\tif (pK.startsWith('f-')) return;\n\t\t\tparams[pK] = currentParams[pK];\n\t\t});\n\n\t\tObject.keys(filters ?? {}).forEach(key => {\n\t\t\tif (key === searchKey && '$prefix' in filters[key])\n\t\t\t\tparams[`f-${key}`] = filters[key]['$prefix'];\n\t\t\telse\n\t\t\t\tparams[`f-${key}`] = filters[key];\n\t\t});\n\n\n\t\thistory.push(location.pathname + '?' + queryString.stringify(params));\n\t};\n\n\n\tconst handleFiltersAndPagingChange = (filters, paging) => {\n\t\tif (loading) return;\n\n\t\tlet params = queryString.parse(location.search);\n\n\t\tif (filters !== null) { // We have some filter changes\n\t\t\t// We remove all existing filters\n\t\t\tObject.keys({ ...(params ?? {}) }).forEach(pK => {\n\t\t\t\tif (!pK.startsWith('f-')) return;\n\t\t\t\tdelete params[pK];\n\t\t\t});\n\n\t\t\t// We add the new filters\n\t\t\tObject.keys(filters ?? {}).forEach(key => {\n\t\t\t\tif (key === searchKey && '$prefix' in filters[key])\n\t\t\t\t\tparams[`f-${key}`] = filters[key]['$prefix'];\n\t\t\t\telse\n\t\t\t\t\tparams[`f-${key}`] = filters[key];\n\t\t\t});\n\n\t\t}\n\n\t\tif (paging !== null) {\n\t\t\tparams = { ...params, ...paging }; // we replace the paging information\n\t\t}\n\n\t\thistory.push(location.pathname + '?' + queryString.stringify(params));\n\t};\n\n\tconst sortHandler = (property, dir) => {\n\t\tlet p = { ...filters };\n\t\t// only 1 sort\n\t\tp.sort = {};\n\t\tp.sort[property] = dir;\n\t\tsetFilters(p);\n\t};\n\n\tconst pagingChangeHandler = params => {\n\t\tconst pNo = 'page_no' in params ? parseInt(params.page_no) : 1;\n\t\tconst perPage = 'results_per_page' in params ? parseInt(params.results_per_page) : 10;\n\t\tlet newPaging = null;\n\t\tif (paging.page_no !== pNo)\n\t\t\tnewPaging = { ...(newPaging ?? {}), page_no: pNo };\n\t\tif (paging.results_per_page !== perPage)\n\t\t\tnewPaging = { ...(newPaging ?? {}), results_per_page: perPage };\n\n\t\tif (newPaging) {\n\t\t\tsetPaging({ ...paging, ...newPaging });\n\t\t}\n\t};\n\n\tconst filtersChangeHandler = params => {\n\t\t// We need to compare the filters set in the url and the one we have.\n\t\t// We keep the sort filters, and the initial filters\n\t\t// We refresh only if a change occurred\n\t\tconst filtersInUrl = {};\n\t\tlet refreshNeeded = false;\n\n\t\t// We extract the filters in the url, all the table filter will begin by f-\n\t\t// We also use this to detect if an existing filter as changed\n\t\t// With this we can detect if filters has been added to the url, or changed\n\t\tObject.keys(params).forEach(k => {\n\t\t\tif (!k.startsWith('f-')) return;\n\t\t\tconst cleaned = k.replace('f-', '');\n\t\t\tfiltersInUrl[cleaned] = cleaned === searchKey ? { '$prefix': params[k] } : params[k];\n\t\t\t// Detect changes\n\t\t\tif (!(k in filters)) {\n\t\t\t\trefreshNeeded = true;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (cleaned === searchKey && filters[k]['$prefix'] !== params[k]['$prefix'])\n\t\t\t\trefreshNeeded = true;\n\t\t\telse if (cleaned !== searchKey && filters[k] !== params[k]) refreshNeeded = true;\n\t\t});\n\n\t\t//We need now to detect a filters has been removed from the url\n\t\tObject.keys(filters).forEach(k => {\n\t\t\tif (k in initialFilters) return; // this is an initial filters we don't touch it\n\t\t\tif (k === 'sort') return; // We don't handle sort filter here\n\n\t\t\t// There is a filter in the filters list but not in the url,\n\t\t\t// this means a filter has been deleted, we need to update the filter list\n\t\t\tif (!(k in filtersInUrl)) refreshNeeded = true;\n\t\t});\n\n\t\tif (refreshNeeded)\n\t\t\tsetFilters({ ...initialFilters, ...(filters.sort ?? {}), ...filtersInUrl });\n\t};\n\n\tuseEffect(() => {\n\t\tlet hasFilter = false;\n\t\tObject.keys(filters ?? {}).forEach(key => {\n\t\t\tif (key in (initialFilters ?? {}) || key === 'sort') return;\n\t\t\thasFilter = true;\n\t\t});\n\n\t\tsetHasFilters(hasFilter);\n\t}, [filters, setHasFilters]);\n\n\tuseEffect(() => {\n\t\tconst params = queryString.parse(location.search);\n\n\t\t// Change paging\n\t\tpagingChangeHandler(params);\n\n\t\t// Change filters\n\t\tfiltersChangeHandler(params);\n\n\n\t\t// eslint-disable-next-line\n\t}, [location]);\n\n\tconst firstUpdate = useRef(true);\n\n\t// Detect filter or paging changes\n\tuseEffect(() => {\n\t\t// Do not fetch on first render\n\t\t// The system will get the paging info from the url that will trigger the initial fetch\n\t\tif (firstUpdate.current) {\n\t\t\tfirstUpdate.current = false;\n\t\t\treturn;\n\t\t}\n\n\t\tfetch(filters, paging);\n\t\t// eslint-disable-next-line\n\t}, [filters, paging]);\n\n\treturn (\n\t\t\n\t\t\t{(loading || (data ? data.data ?? [] : []).length > 0 || (!emptyState || hasFilters)) &&\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t \n\t\t\t\t \n\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t{(Array.isArray(children) ? children : [children]).map(\n\t\t\t\t\t\t\t\t\t\t(child, idx) => {\n\t\t\t\t\t\t\t\t\t\t\tif (!child)\n\t\t\t\t\t\t\t\t\t\t\t\treturn null;\n\n\t\t\t\t\t\t\t\t\t\t\tconst { name, label, sortable, headerAlign, align, ...cellProps } = child.props;\n\n\t\t\t\t\t\t\t\t\t\t\tconst finalAlign = headerAlign ?? (align ?? undefined);\n\n\t\t\t\t\t\t\t\t\t\t\treturn \n\t\t\t\t\t\t\t\t\t\t\t\t{!sortable ? label :\n\t\t\t\t\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t ;\n\t\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t{displayData()}\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t !!c).length}\n\t\t\t\t\t\t\t\t\t\tcount={(data && data.paging) ? parseInt(data.paging.count ?? 0) : 10}\n\t\t\t\t\t\t\t\t\t\trowsPerPage={parseInt(paging.results_per_page ?? 10)}\n\t\t\t\t\t\t\t\t\t\tpage={paging ? parseInt(paging.page_no ?? 1) - 1 : 0}\n\t\t\t\t\t\t\t\t\t\tlabelRowsPerPage={t('rows_per_page')}\n\t\t\t\t\t\t\t\t\t\tSelectProps={{\n\t\t\t\t\t\t\t\t\t\t\tinputProps: { 'aria-label': t('rows_per_page') },\n\t\t\t\t\t\t\t\t\t\t\tnative: true,\n\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\tlabelDisplayedRows={\n\t\t\t\t\t\t\t\t\t\t\t({ from, to, count }) => t(count !== -1 ? 'table_paging' : 'table_paging_more', {\n\t\t\t\t\t\t\t\t\t\t\t\tfrom: from,\n\t\t\t\t\t\t\t\t\t\t\t\tto: to,\n\t\t\t\t\t\t\t\t\t\t\t\tcount: count\n\t\t\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\tonChangePage={changePageHandler}\n\t\t\t\t\t\t\t\t\t\tonChangeRowsPerPage={changeResultPerPageHandler}\n\t\t\t\t\t\t\t\t\t\tActionsComponent={TablePaginationActions}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t \n\t\t\t \n\t\t\t}\n\t\t\t{(emptyState && !loading && (data ? data.data ?? [] : []).length < 1 && !hasFilters) && emptyState}\n\t\t \n\t);\n};\n\nexport default Table;\n\nTable.propTypes = {\n\tRowComponent: PropTypes.any,\n\tchildren: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]),\n\tdata: PropTypes.object,\n\temptyState: PropTypes.any,\n\temptyText: PropTypes.string,\n\textra: PropTypes.array,\n\tfetch: PropTypes.func,\n\tinitialFilters: PropTypes.object,\n\tloading: PropTypes.bool,\n\tpaperProps: PropTypes.object,\n\trowProps: PropTypes.object,\n\tsearch: PropTypes.bool,\n\tsearchCriteria: PropTypes.array,\n\tsearchKey: PropTypes.string,\n\ttitle: PropTypes.string,\n\ttoolbarProps: PropTypes.object\n};\n","import React from 'react';\nimport { useTranslation } from 'react-i18next';\n\nimport DeleteForeverIcon from '@material-ui/icons/DeleteForever';\nimport DialogActions from '@material-ui/core/DialogActions';\nimport Dialog from '@material-ui/core/Dialog';\nimport DialogContent from '@material-ui/core/DialogContent';\nimport DialogContentText from '@material-ui/core/DialogContentText';\nimport DialogTitle from '@material-ui/core/DialogTitle';\nimport Typography from '@material-ui/core/Typography';\n\nimport PropTypes from 'prop-types';\nimport Button from '../../../core/input/Button';\nimport { useConsumerTokenUnlink } from '@karpeleslab/klb-react-services';\n\nconst DeleteDialog = ({ open, setOpen, token, onDeleted }) => {\n\tconst { t } = useTranslation();\n\tconst [unlinkToken, loading] = useConsumerTokenUnlink(token.OAuth2_Consumer_Token__);\n\n\tconst handleDelete = () => unlinkToken().then(onDeleted);\n\n\treturn (\n\t\t\n\t\t\t{t('confirm_delete_token_title')} \n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{t('confirm_delete_token_desc')}\n\t\t\t\t\t \n\t\t\t\t\t\n\t\t\t\t\t\t{t('are_you_sure')}\n\t\t\t\t\t \n\t\t\t\t \n\t\t\t \n\t\t\t\n\t\t\t\t setOpen(false)}\n\t\t\t\t\tdisabled={loading}\n\t\t\t\t>\n\t\t\t\t\t{t('back_btn')}\n\t\t\t\t \n\t\t\t\t }\n\t\t\t\t\tonClick={handleDelete}\n\t\t\t\t>\n\t\t\t\t\t{t('delete_btn')}\n\t\t\t\t\n\t\t\t \n\t\t \n\t);\n};\n\nexport default DeleteDialog;\n\n\nDeleteDialog.propTypes = {\n\topen: PropTypes.bool.isRequired,\n\tsetOpen: PropTypes.func.isRequired,\n\ttoken: PropTypes.object,\n\tonDeleted: PropTypes.func.isRequired,\n};\n","import React, { useState } from 'react';\nimport { useTranslation } from 'react-i18next';\n\nimport Empty from './Empty';\nimport TableDefinition from '../../../../core/data/table/TableDefinition';\nimport { OauthBtn } from '../../../../Login/OauthBtnsBuilder';\nimport DeleteForeverIcon from '@material-ui/icons/DeleteForever';\nimport Button from '../../../../core/input/Button';\nimport CoreTable from '../../../../core/data/table/Table';\nimport DeleteDialog from '../DeleteDialog';\nimport useMediaQuery from '@material-ui/core/useMediaQuery';\nimport { useConsumerTokens } from '@karpeleslab/klb-react-services';\n\nconst Table = () => {\n\tconst { t } = useTranslation();\n\n\tconst [tokens, fetch, loading] = useConsumerTokens();\n\tconst [selected, setSelected] = useState();\n\tconst [showDelete, setShowDelete] = useState(false);\n\tconst isMobile = useMediaQuery(theme => theme.breakpoints.down('xs'));\n\n\tconst deleteHandler = token => {\n\t\tsetSelected(token);\n\t\tsetShowDelete(true);\n\t};\n\n\treturn (\n\t\t<>\n\t\t\t }\n\t\t\t>\n\t\t\t\t\n\t\t\t\t\t{token => }\n\t\t\t\t \n\n\t\t\t\t{!isMobile && }\n\n\t\t\t\t \n\n\t\t\t\t\n\t\t\t\t\t{token => deleteHandler(token)}\n\t\t\t\t\t\tstartIcon={ }\n\t\t\t\t\t>\n\t\t\t\t\t\t{t('delete_btn')}\n\t\t\t\t\t }\n\t\t\t\t \n\t\t\t\n\t\t\t{selected && {\n\t\t\t\t\tfetch();\n\t\t\t\t\tsetSelected(null);\n\t\t\t\t\tsetShowDelete(false);\n\t\t\t\t}}\n\t\t\t/>\n\t\t\t}\n\t\t>\n\t);\n};\n\nexport default Table;\n","import React, { useState } from 'react';\nimport { useTranslation } from 'react-i18next';\n\nimport AddDialog from './AddDialog';\nimport AddIcon from '@material-ui/icons/Add';\nimport Alert from '@material-ui/lab/Alert';\nimport Grid from '@material-ui/core/Grid';\nimport Table from './table/Table';\nimport Toolbar from './../../../core/typography/Toolbar';\nimport Button from '../../../core/input/Button';\n\nconst OAuth = () => {\n\tconst { t } = useTranslation();\n\tconst [addDialogOpened, setAddDialogOpened] = useState(false);\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t }\n\t\t\t\t\t\tvariant='contained'\n\t\t\t\t\t\tcolor='primary'\n\t\t\t\t\t\tonClick={() => setAddDialogOpened(true)}\n\t\t\t\t\t>\n\t\t\t\t\t\t{t('add_btn')}\n\t\t\t\t\t\n\t\t\t\t \n\t\t\t \n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{t('profile_oauth_desc')}\n\t\t\t\t \n\t\t\t \n\t\t\t\n\t\t\t\t\n\t\t\t \n\t\t\t\n\t\t \n\t);\n};\n\nexport default OAuth; \n","import React, { useContext, useEffect, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\n\nimport { Grid } from '@material-ui/core';\nimport TextField from '@material-ui/core/TextField';\nimport { Title } from '../../core/typography/Title';\nimport RequestPasswordDialog from './RequestPasswordDialog';\nimport { UserContext } from '../../../context/UserContext';\nimport Button from '../../core/input/Button';\nimport { useUserChangePassword } from '@karpeleslab/klb-react-services';\n\nconst Security = () => {\n\tconst { t } = useTranslation();\n\tconst [newPassword, setNewPassword] = useState('');\n\tconst [newPasswordRepeat, setNewPasswordRepeat] = useState('');\n\tconst [saveEnabled, setSaveEnabled] = useState(false);\n\tconst [requestPwdOpen, setRequestPwdOpen] = useState(false);\n\tconst [user] = useContext(UserContext);\n\tconst [changePassword, changingInfo] = useUserChangePassword('@');\n\n\tconst resetFields = () => {\n\t\tsetNewPassword('');\n\t\tsetNewPasswordRepeat('');\n\t};\n\n\tuseEffect(() => {\n\t\tif (newPassword === '') {\n\t\t\tsetSaveEnabled(false);\n\t\t\treturn;\n\t\t}\n\n\t\tif (newPassword !== newPasswordRepeat) {\n\t\t\tsetSaveEnabled(false);\n\t\t\treturn;\n\t\t}\n\n\t\tsetSaveEnabled(true);\n\t}, [newPassword, newPasswordRepeat]);\n\n\tconst handleSave = old => {\n\t\tchangePassword(old, newPassword)\n\t\t\t.finally(resetFields);\n\t};\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t{t('profile_security')} \n\t\t\t \n\t\t\t\n\t\t\t\t setNewPassword(e.target.value)}\n\t\t\t\t\tvariant='outlined'\n\t\t\t\t\ttype='password'\n\t\t\t\t\tdisabled={changingInfo}\n\t\t\t\t/>\n\t\t\t \n\t\t\t\n\t\t\t\t setNewPasswordRepeat(e.target.value)}\n\t\t\t\t\tvariant='outlined'\n\t\t\t\t\ttype='password'\n\t\t\t\t\terror={newPasswordRepeat !== newPassword}\n\t\t\t\t\thelperText={newPasswordRepeat !== newPassword ? t('confirm_password_not_match') : ''}\n\t\t\t\t\tdisabled={changingInfo}\n\t\t\t\t/>\n\t\t\t \n\t\t\t\n\t\t\t\t\n\t\t\t\t\t {\n\t\t\t\t\t\t\tif (user.user.data.Has_Password)\n\t\t\t\t\t\t\t\tsetRequestPwdOpen(true);\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\thandleSave(null);\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t{t('save_btn')}\n\t\t\t\t\t \n\n\t\t\t\t \n\t\t\t \n\t\t\t{user.user.data.Has_Password &&\n\t\t\t \n\t\t\t}\n\t\t \n\t);\n};\n\nexport default Security;\n","export default __webpack_public_path__ + \"static/media/otp_empty_list.3896558a.svg\";","import React from 'react';\nimport { Trans, useTranslation } from 'react-i18next';\n\nimport EmptyState from './../../../../core/feedback/State/Empty';\nimport Graphic from './../../../../../assets/img/otp_empty_list.svg';\n\nconst Empty = () => {\n\tconst { t } = useTranslation();\n\n\treturn (\n\t\t\n\t\t\t\tsample \n\t\t\t\tsample \n\t\t\t}\n\t\t\tgraphic={Graphic}\n\t\t/>\n\t);\n};\n\nexport default Empty;\n","import React from 'react';\nimport Typography from '@material-ui/core/Typography';\nimport Box from '@material-ui/core/Box';\nimport PropTypes from 'prop-types';\n\nconst Panel = ({ children, value, index, boxProps = { p: 3 }, ...other }) => {\n\treturn (\n\t\t\n\t\t\t{value === index && {children} }\n\t\t \n\t);\n};\n\nexport default Panel;\n\nPanel.propTypes = {\n\tboxProps: PropTypes.object,\n\tchildren: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]),\n\tindex: PropTypes.any.isRequired,\n\tvalue: PropTypes.any.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React, { useEffect, useState } from 'react';\nimport Grid from '@material-ui/core/Grid';\nimport TextField from '@material-ui/core/TextField';\nimport { useTranslation } from 'react-i18next';\nimport DialogContent from '@material-ui/core/DialogContent';\nimport DialogActions from '@material-ui/core/DialogActions';\nimport Button from '../../../../core/input/Button';\nimport { useUserOTPCreate } from '@karpeleslab/klb-react-services';\nimport { TAB_ASSOCIATE } from './AddDialog';\n\nconst StepCreate = ({ handleClose, setStep, setOtp, setLoading }) => {\n\tconst { t } = useTranslation();\n\tconst [otpName, setOtpName] = useState();\n\tconst [create, creating] = useUserOTPCreate();\n\n\tuseEffect(() => {\n\t\tsetLoading(creating);\n\t}, [creating]);\n\n\tconst handleCreate = () => {\n\t\tcreate(otpName.trim())\n\t\t\t.then(res => {\n\t\t\t\tsetOtp(res);\n\t\t\t\tsetStep(TAB_ASSOCIATE);\n\t\t\t});\n\t};\n\n\treturn (\n\t\t<>\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t setOtpName(e.target.value)}\n\t\t\t\t\t\t\tvariant='outlined'\n\t\t\t\t\t\t\trequired\n\t\t\t\t\t\t\tdisabled={creating}\n\t\t\t\t\t\t/>\n\t\t\t\t\t \n\t\t\t\t \n\t\t\t \n\t\t\t\n\t\t\t\t{t('close_btn')} \n\t\t\t\t\n\t\t\t\t\t{t('otp_step_create_btn')}\n\t\t\t\t \n\n\t\t\t \n\t\t>\n\t);\n};\n\nexport default StepCreate;\n\nStepCreate.propTypes = {\n\thandleClose: PropTypes.func.isRequired,\n\tsetLoading: PropTypes.func.isRequired,\n\tsetOtp: PropTypes.func.isRequired,\n\tsetStep: PropTypes.func.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React, { useEffect, useState } from 'react';\nimport DialogContent from '@material-ui/core/DialogContent';\nimport DialogActions from '@material-ui/core/DialogActions';\nimport Grid from '@material-ui/core/Grid';\nimport RichAlert from '../../../../core/feedback/RichAlert';\nimport { Trans, useTranslation } from 'react-i18next';\nimport QRCode from 'qrcode.react';\nimport { Typography } from '@material-ui/core';\nimport TextField from '@material-ui/core/TextField';\nimport { useUserOTPAssociate } from '@karpeleslab/klb-react-services';\nimport { TAB_ACTIVATE } from './AddDialog';\nimport Button from '../../../../core/input/Button';\n\nconst buildOtpUrl = (name, keyB32) => {\n\treturn `otpauth://totp/${encodeURIComponent(`Shellsâ„¢:${name}`)}?secret=${keyB32}&issuer=${encodeURIComponent('Shellsâ„¢')}&digits=6&period=30`;\n};\n\nconst StepAssociate = ({ otp, handleClose, setStep, refresh, setLoading }) => {\n\tconst { t } = useTranslation();\n\tconst [otpConfirm, setOtpConfirm] = useState();\n\tconst [associate, associating] = useUserOTPAssociate(otp.User_Otp__);\n\n\tuseEffect(() => {\n\t\tsetLoading(associating);\n\t}, [associating]);\n\n\tconst handleAssociate = () => {\n\t\tassociate(otpConfirm, otp.Name)\n\t\t\t.then(() => {\n\t\t\t\trefresh();\n\t\t\t\tsetStep(TAB_ACTIVATE);\n\t\t\t});\n\t};\n\n\treturn (\n\t\t<>\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\tsample \n\t\t\t\t\t\t\t\tsample \n\t\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t{t('otp_b16_key', { key: otp.Key })}\n\t\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t{t('otp_b32_key', { key: otp.Key_base32 })}\n\t\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t setOtpConfirm(e.target.value)}\n\t\t\t\t\t\t\t\t\t\t\tvariant='outlined'\n\t\t\t\t\t\t\t\t\t\t\trequired\n\t\t\t\t\t\t\t\t\t\t\tdisabled={associating}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t \n\t\t\t \n\t\t\t\n\t\t\t\t{t('close_btn')} \n\t\t\t\t\n\t\t\t\t\t{t('otp_step_associate_btn')}\n\t\t\t\t \n\t\t\t \n\t\t>\n\t);\n};\n\nexport default StepAssociate;\n\nStepAssociate.propTypes = {\n\thandleClose: PropTypes.func.isRequired,\n\totp: PropTypes.object.isRequired,\n\trefresh: PropTypes.func.isRequired,\n\tsetLoading: PropTypes.func.isRequired,\n\tsetStep: PropTypes.func.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React from 'react';\nimport { useTranslation } from 'react-i18next';\nimport FormGroup from '@material-ui/core/FormGroup';\nimport FormControlLabel from '@material-ui/core/FormControlLabel';\nimport Checkbox from '@material-ui/core/Checkbox';\nimport { Grid } from '@material-ui/core';\nimport { useUserOTPSetAction, useUserOTPUnsetAction } from '@karpeleslab/klb-react-services';\n\nconst ACTIONS = ['login'];\n\nconst OtpActions = ({ otp, refresh }) => {\n\tconst { t } = useTranslation();\n\tconst [set, setting] = useUserOTPSetAction(otp.User_Otp__);\n\tconst [unset, unsetting] = useUserOTPUnsetAction(otp.User_Otp__);\n\n\tconst setHandler = action => {\n\t\tset(action).then(refresh);\n\t};\n\n\tconst unsetHandler = action => {\n\t\tunset(action).then(refresh);\n\t};\n\n\tconst isActivated = action => {\n\t\treturn (otp.Actions ?? []).includes(action);\n\t};\n\n\tconst createChangeHandler = action => e => {\n\t\tif (e.target.checked) setHandler(action);\n\t\telse unsetHandler(action);\n\t};\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t{ACTIONS.map(a =>\n\t\t\t\t\t\n\t\t\t\t\t\t \n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tlabel={t(`opt_action_${a}`)}\n\t\t\t\t\t\t/>\n\t\t\t\t\t \n\t\t\t\t)}\n\t\t\t \n\t\t \n\t);\n};\n\nexport default OtpActions;\n\nOtpActions.propTypes = {\n\totp: PropTypes.object,\n\trefresh: PropTypes.func.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React from 'react';\nimport DialogContent from '@material-ui/core/DialogContent';\nimport DialogActions from '@material-ui/core/DialogActions';\nimport Grid from '@material-ui/core/Grid';\nimport RichAlert from '../../../../core/feedback/RichAlert';\nimport { Trans, useTranslation } from 'react-i18next';\nimport OtpActions from '../OtpActions';\nimport Button from '../../../../core/input/Button';\n\nconst StepActivate = ({ otp, handleClose, refresh, setOtp }) => {\n\tconst { t } = useTranslation();\n\treturn (\n\t\t<>\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\tsample \n\t\t\t\t\t\t\t\tsample \n\t\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t\t\n\t\t\t\t\t\t {\n\t\t\t\t\t\t\trefresh();\n\t\t\t\t\t\t\tsetOtp(otp);\n\t\t\t\t\t\t}}/>\n\t\t\t\t\t \n\t\t\t\t \n\t\t\t \n\t\t\t\n\t\t\t\t{t('close_btn')} \n\t\t\t \n\t\t>\n\t);\n};\n\nexport default StepActivate;\n\nStepActivate.propTypes = {\n\thandleClose: PropTypes.func.isRequired,\n\totp: PropTypes.object.isRequired,\n\trefresh: PropTypes.func.isRequired,\n\tsetOtp: PropTypes.func.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React, { useState } from 'react';\nimport { useTranslation } from 'react-i18next';\n\nimport Dialog from '@material-ui/core/Dialog';\nimport DialogContent from '@material-ui/core/DialogContent';\nimport DialogContentText from '@material-ui/core/DialogContentText';\nimport DialogTitle from '@material-ui/core/DialogTitle';\nimport Grid from '@material-ui/core/Grid';\nimport Step from '@material-ui/core/Step';\nimport StepLabel from '@material-ui/core/StepLabel';\nimport Stepper from '@material-ui/core/Stepper';\nimport Panel from '../../../../layout/Container/tab/Panel';\nimport StepCreate from './StepCreate';\nimport StepAssociate from './StepAssociate';\nimport StepActivate from './StepActivate';\n\nexport const TAB_CREATE = 0;\nexport const TAB_ASSOCIATE = 1;\nexport const TAB_ACTIVATE = 2;\n\nconst AddDialog = ({ open, setOpen, refresh }) => {\n\tconst { t } = useTranslation();\n\tconst [step, setStep] = useState(TAB_CREATE);\n\tconst [otp, setOtp] = useState(null);\n\tconst [loading, setLoading] = useState(false);\n\n\tconst handleClose = () => setOpen(false);\n\n\n\tconst init = () => {\n\t\tsetStep(TAB_CREATE);\n\t\tsetOtp(null);\n\t};\n\n\treturn (\n\t\t {\n\t\t\t\tinit();\n\t\t\t}}\n\t\t>\n\t\t\t{t('add_otp_title')} \n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{t('add_otp_description')}\n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t{t('step_otp_config')} \n\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t{t('step_otp_associate')} \n\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t{t('step_otp_activate')} \n\t\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t \n\t\t\t \n\t\t\t\n\t\t\t\t\n\t\t\t \n\t\t\t\n\t\t\t\t{otp && }\n\t\t\t \n\t\t\t\n\t\t\t\t{otp && }\n\t\t\t \n\t\t \n\t);\n};\n\nexport default AddDialog;\n\nAddDialog.propTypes = {\n\topen: PropTypes.bool.isRequired,\n\trefresh: PropTypes.func.isRequired,\n\tsetOpen: PropTypes.func.isRequired\n};\n","import React from 'react';\nimport Dialog from '@material-ui/core/Dialog';\nimport DialogContentText from '@material-ui/core/DialogContentText';\nimport DialogContent from '@material-ui/core/DialogContent';\nimport { useTranslation } from 'react-i18next';\nimport DialogTitle from '@material-ui/core/DialogTitle';\nimport DialogActions from '@material-ui/core/DialogActions';\nimport RichAlert from '../../../core/feedback/RichAlert';\nimport Button from '../../../core/input/Button';\nimport PropTypes from 'prop-types';\nimport { useUserOTPDelete } from '@karpeleslab/klb-react-services';\n\nconst DeleteDialog = ({ otp, open, setOpen, refreshList, refreshing }) => {\n\tconst { t } = useTranslation();\n\tconst [deleteKey, deleting] = useUserOTPDelete(otp.User_Otp__);\n\n\tconst handleClose = () => {\n\t\tsetOpen(false);\n\t};\n\n\tconst handleDelete = e => {\n\t\te.preventDefault();\n\n\t\tdeleteKey()\n\t\t\t.then(() => refreshList())\n\t\t\t.then(handleClose);\n\t};\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t{t('dialog_delete_opt_title')}\n\t\t\t \n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t{t('dialog_delete_opt_desc', {\n\t\t\t\t\t\t\tname: otp?.Name,\n\t\t\t\t\t\t})}\n\t\t\t\t\t \n\t\t\t\t \n\t\t\t \n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{t('close_btn')}\n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t{t('delete_btn')}\n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default DeleteDialog;\n\nDeleteDialog.propTypes = {\n\totp: PropTypes.object,\n\topen: PropTypes.bool.isRequired,\n\trefreshList: PropTypes.func.isRequired,\n\trefreshing: PropTypes.bool.isRequired,\n\tsetOpen: PropTypes.func.isRequired\n};\n","import React, { useState } from 'react';\nimport { useTranslation } from 'react-i18next';\n\nimport Empty from './Empty';\nimport TableDefinition from '../../../../core/data/table/TableDefinition';\nimport DeleteForeverIcon from '@material-ui/icons/DeleteForever';\nimport Button from '../../../../core/input/Button';\nimport CoreTable from '../../../../core/data/table/Table';\nimport { Grid } from '@material-ui/core';\nimport Toolbar from '../../../../core/typography/Toolbar';\nimport AddIcon from '@material-ui/icons/Add';\nimport Alert from '@material-ui/lab/Alert';\nimport AddDialog from '../AddDialog/AddDialog';\nimport OtpActions from '../OtpActions';\nimport DeleteDialog from '../DeleteDialog';\nimport { useUserOTPs } from '@karpeleslab/klb-react-services';\n\nconst OtpTable = () => {\n\tconst { t } = useTranslation();\n\n\tconst [tokens, fetch, loading, setOtp] = useUserOTPs();\n\tconst [showCreate, setShowCreate] = useState(false);\n\tconst [showDelete, setShowDelete] = useState(false);\n\tconst [selected, setSelected] = useState(null);\n\n\tconst createSetOtpHandler = idx => otp => {\n\t\tsetOtp(idx, otp);\n\t};\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t }\n\t\t\t\t\t\tvariant='contained'\n\t\t\t\t\t\tcolor='primary'\n\t\t\t\t\t\tonClick={() => setShowCreate(true)}\n\t\t\t\t\t>\n\t\t\t\t\t\t{t('add_btn')}\n\t\t\t\t\t\n\t\t\t\t \n\t\t\t \n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{t('profile_otp_desc')}\n\t\t\t\t \n\t\t\t \n\n\t\t\t\n\t\t\t\t }\n\t\t\t\t>\n\n\t\t\t\t\t \n\t\t\t\t\t\n\t\t\t\t\t\t{(otp, idx) => }\n\t\t\t\t\t \n\n\t\t\t\t\t\n\t\t\t\t\t\t{otp =>\n\t\t\t\t\t\t\t(otp.Actions ?? []).length < 1 ? }\n\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\tsetSelected(otp);\n\t\t\t\t\t\t\t\t\tsetShowDelete(true);\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{t('delete_btn')}\n\t\t\t\t\t\t\t : <>>\n\t\t\t\t\t\t}\n\t\t\t\t\t \n\t\t\t\t\n\t\t\t \n\t\t\t \n\t\t\t{selected && \n\t\t\t}\n\t\t \n\t);\n};\n\nexport default OtpTable;\n","import React from 'react';\nimport { useTranslation } from 'react-i18next';\n\nimport Account from './../../components/common/profile/Account';\nimport Grid from '@material-ui/core/Grid';\nimport Helmet from 'react-helmet';\nimport Information from './../../components/common/profile/Information';\nimport OAuth from './../../components/common/profile/OAuth/OAuth';\nimport Security from './../../components/common/profile/Security';\nimport PageContainer from '../../components/layout/Container/PageContainer';\nimport OtpTable from '../../components/common/profile/OTP/table/OtpTable';\nimport ModeCheck from '../../components/layout/Mode/ModeCheck';\n\nconst Profile = () => {\n\tconst { t } = useTranslation();\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t{t('navigation_settings')} \n\t\t\t \n\t\t\t\n\t\t\t\t{ /* TBD add helmet */}\n\t\t\t\t\n\t\t\t\t\t \n\t\t\t\t \n\n\t\t\t\t\n\t\t\t\t\t \n\t\t\t\t \n\n\t\t\t\t\n\t\t\t\t\t \n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t \n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default Profile;\n","import React, { useEffect } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport TextField from '@material-ui/core/TextField';\nimport Grid from '@material-ui/core/Grid';\nimport PropTypes from 'prop-types';\n\nconst Form = ({ data, setData, setIsValid, disabled = false }) => {\n\tconst { t } = useTranslation();\n\n\tconst createChangeHandler = key => e => {\n\t\tsetData({ ...data, [key]: e.target.value });\n\t};\n\n\tconst getValue = (key, def = '') => {\n\t\tif (!(key in (data ?? {}))) return def;\n\t\treturn data[key];\n\t};\n\n\tuseEffect(() => {\n\t\tif (!('Label' in (data ?? {}))) setIsValid(false);\n\t\telse setIsValid(true);\n\t}, [data, setIsValid]);\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default Form;\n\nForm.propTypes = {\n\tdata: PropTypes.object.isRequired,\n\tsetData: PropTypes.func.isRequired,\n\tsetIsValid: PropTypes.func.isRequired,\n\tdisabled: PropTypes.bool,\n};\n","import React, { useState } from 'react';\nimport Dialog from '@material-ui/core/Dialog';\nimport DialogContentText from '@material-ui/core/DialogContentText';\nimport DialogContent from '@material-ui/core/DialogContent';\nimport { useTranslation } from 'react-i18next';\nimport DialogTitle from '@material-ui/core/DialogTitle';\nimport DialogActions from '@material-ui/core/DialogActions';\nimport { useHistory } from 'react-router-dom';\nimport Form from './Form';\nimport PropTypes from 'prop-types';\nimport { getSSHKeychainEditRoute } from '../../RouteController/Factory';\nimport Grid from '@material-ui/core/Grid';\nimport Button from '../../core/input/Button';\nimport { useKeychainCreate } from '@karpeleslab/klb-react-services';\n\nconst CreateDialog = ({ open, setOpen }) => {\n\tconst { t } = useTranslation();\n\tconst history = useHistory();\n\tconst [saveEnabled, setSaveEnabled] = useState(false);\n\tconst [data, setData] = useState({});\n\tconst [create, creating] = useKeychainCreate();\n\n\tconst handleClose = () => {\n\t\tsetOpen(false);\n\t};\n\n\tconst handleCreate = e => {\n\t\te.preventDefault();\n\t\tcreate(data.Label)\n\t\t\t.then(d => history.push(getSSHKeychainEditRoute(d.Keychain__)));\n\t};\n\n\treturn (\n\t\t setData({})}\n\t\t>\n\t\t\t\n\t\t \n\t);\n};\n\nexport default CreateDialog;\n\nCreateDialog.propTypes = {\n\topen: PropTypes.bool.isRequired,\n\tsetOpen: PropTypes.func.isRequired,\n};\n","import React from 'react';\nimport moment from 'moment';\nimport PropTypes from 'prop-types';\n\nconst DateUtil = ({ klbDateObj, format = 'YYYY-MM-DD HH:mm:ss' }) => {\n\tlet unixTime;\n\n\tif (klbDateObj && klbDateObj.unixms) unixTime = parseInt(klbDateObj.unixms);\n\telse if (klbDateObj && klbDateObj.unix)\n\t\tunixTime = parseInt(klbDateObj.unix) * 1000;\n\n\treturn <>{unixTime ? moment(unixTime).format(format) : 'N/A'}>;\n};\n\nexport default DateUtil;\n\n\nDateUtil.propTypes = {\n\tformat: PropTypes.string,\n\tklbDateObj: PropTypes.object,\n};\n","import React from 'react';\nimport { useTranslation } from 'react-i18next';\nimport Table from '../../core/data/table/Table';\nimport TableDefinition from '../../core/data/table/TableDefinition';\nimport DateUtil from '../../core/data/Date/DateUtil';\nimport Button from '../../core/input/Button';\nimport { getSSHKeychainEditRoute } from '../../RouteController/Factory';\nimport EditIcon from '@material-ui/icons/Edit';\nimport { Link } from 'react-router-dom';\nimport useMediaQuery from '@material-ui/core/useMediaQuery';\nimport { useKeychains } from '@karpeleslab/klb-react-services';\n\nconst KeychainTable = () => {\n\tconst [keychains, fetch, loading] = useKeychains();\n\tconst { t } = useTranslation();\n\tconst isMobile = useMediaQuery(theme => theme.breakpoints.down('xs'));\n\n\treturn (\n\t\t\n\t\t\t \n\t\t\t{!isMobile && \n\t\t\t\t{keychain => }\n\t\t\t }\n\n\t\t\t\n\t\t\t\t{keychain =>\n\t\t\t\t\t }\n\t\t\t\t\t>\n\t\t\t\t\t\t{t('edit_btn')}\n\t\t\t\t\t\n\t\t\t\t}\n\t\t\t \n\t\t
\n\t);\n};\n\nexport default KeychainTable;\n","import React, { useState } from 'react';\nimport { Grid } from '@material-ui/core';\nimport Button from '../../components/core/input/Button';\nimport { useTranslation } from 'react-i18next';\nimport AddIcon from '@material-ui/icons/Add';\nimport CreateDialog from '../../components/common/Keychain/CreateDialog';\nimport KeychainTable from '../../components/common/Keychain/KeychainTable';\nimport PageContainer from '../../components/layout/Container/PageContainer';\nimport Toolbar from '../../components/core/typography/Toolbar';\n\nconst Keychains = () => {\n\tconst { t } = useTranslation();\n\tconst [showCreate, setShowCreate] = useState(false);\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t setShowCreate(true)}\n\t\t\t\t\t\t\tsize=\"small\"\n\t\t\t\t\t\t\tvariant=\"contained\"\n\t\t\t\t\t\t\tcolor=\"primary\"\n\t\t\t\t\t\t\tstartIcon={ }\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{t('create_btn')}\n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t{t('account_keychains_description')}
\n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t \n\t\t\t\t \n\t\t\t\t\n\t\t\t \n\t\t \n\t);\n};\n\nexport default Keychains;\n","import React, { useEffect, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport Form from './Form';\nimport { deepCopy } from '../../../utils/misc';\nimport Button from '../../core/input/Button';\nimport Grid from '@material-ui/core/Grid';\nimport PropTypes from 'prop-types';\nimport { useKeychainUpdate } from '@karpeleslab/klb-react-services';\n\n\nconst UpdateForm = ({ keychain, setKeychain }) => {\n\tconst { t } = useTranslation();\n\tconst [data, setData] = useState(deepCopy(keychain));\n\tconst [isValid, setIsValid] = useState(false);\n\tconst [saveEnabled, setSaveEnabled] = useState(false);\n\tconst [update, updating] = useKeychainUpdate(keychain.Keychain__);\n\n\tuseEffect(() => {\n\t\tsetData(deepCopy(keychain));\n\t}, [keychain, setData]);\n\n\tuseEffect(() => {\n\t\tif (!isValid) {\n\t\t\tsetSaveEnabled(false);\n\t\t\treturn;\n\t\t}\n\n\t\tsetSaveEnabled(keychain.Label !== (data.Label ?? '').trim());\n\t}, [isValid, data, keychain, setSaveEnabled]);\n\n\tconst saveHandler = () => {\n\t\tupdate(data).then(setKeychain);\n\t};\n\n\treturn (\n\t\t\n\t\t\t{t('keychain_update_title')} \n\t\t\t\n\t\t\t\t \n\t\t\t \n\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t{t('save_btn')}\n\t\t\t\t\t \n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default UpdateForm;\n\nUpdateForm.propTypes = {\n\tkeychain: PropTypes.object.isRequired,\n\tsetKeychain: PropTypes.func.isRequired\n};\n","import React from 'react';\nimport Dialog from '@material-ui/core/Dialog';\nimport DialogContentText from '@material-ui/core/DialogContentText';\nimport DialogContent from '@material-ui/core/DialogContent';\nimport { useTranslation } from 'react-i18next';\nimport DialogTitle from '@material-ui/core/DialogTitle';\nimport DialogActions from '@material-ui/core/DialogActions';\nimport RichAlert from '../../../core/feedback/RichAlert';\nimport Button from '../../../core/input/Button';\nimport PropTypes from 'prop-types';\nimport { useKeychainKeyDelete } from '@karpeleslab/klb-react-services';\n\nconst DeleteDialog = ({ keychainKey, open, setOpen, refreshList, refreshing }) => {\n\tconst { t } = useTranslation();\n\tconst [deleteKey, deleting] = useKeychainKeyDelete(keychainKey?.Keychain_Key__);\n\n\tconst handleClose = () => {\n\t\tsetOpen(false);\n\t};\n\n\tconst handleDelete = e => {\n\t\te.preventDefault();\n\n\t\tdeleteKey()\n\t\t\t.then(() => refreshList())\n\t\t\t.then(handleClose);\n\t};\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t{t('dialog_delete_keychain_key_title')}\n\t\t\t \n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t{t('dialog_delete_keychain_key_description', {\n\t\t\t\t\t\t\tlabel: keychainKey?.Label,\n\t\t\t\t\t\t\tfingerprint: keychainKey?.Fingerprint\n\t\t\t\t\t\t})}\n\t\t\t\t\t \n\t\t\t\t \n\t\t\t \n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{t('close_btn')}\n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t{t('delete_btn')}\n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default DeleteDialog;\n\nDeleteDialog.propTypes = {\n\tkeychainKey: PropTypes.object,\n\topen: PropTypes.bool.isRequired,\n\trefreshList: PropTypes.func.isRequired,\n\trefreshing: PropTypes.bool.isRequired,\n\tsetOpen: PropTypes.func.isRequired\n};\n","import React from 'react';\nimport { DateTimePicker, MuiPickersUtilsProvider } from '@material-ui/pickers';\nimport MomentUtils from '@date-io/moment';\nimport { getLocale } from '@karpeleslab/klbfw';\nimport moment from 'moment';\nimport PropTypes from 'prop-types';\n\nconst locale = getLocale().split('-')[0];\nif (locale !== 'en')\n\trequire('moment/locale/' + locale);\n\nmoment.locale(locale);\n\nconst DateTime = ({ variant, ...props }) => {\n\tif (variant) props.inputVariant = variant;\n\n\treturn (\n\t\t\n\t\t\t \n\t\t \n\t);\n};\n\nexport default DateTime;\n\nDateTime.propTypes = {\n\tvariant: PropTypes.string,\n};\n","import PropTypes from 'prop-types';\nimport React from 'react';\nimport Grid from '@material-ui/core/Grid';\n\nconst TextWithIcon = ({ startIcon, endIcon, text }) => {\n\treturn (\n\t\t\n\t\t\t{startIcon && \n\t\t\t\t{startIcon}\n\t\t\t }\n\t\t\t\n\t\t\t\t{text}\n\t\t\t \n\t\t\t{endIcon && \n\t\t\t\t{endIcon}\n\t\t\t }\n\t\t \n\t);\n};\n\nexport default TextWithIcon;\n\nTextWithIcon.propTypes = {\n\tendIcon: PropTypes.element,\n\tstartIcon: PropTypes.element,\n\ttext: PropTypes.string.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React, { useEffect, useState } from 'react';\nimport { IconButton } from '@material-ui/core';\nimport TextWithIcon from '../../../core/typography/TextWithIcon';\nimport LoopIcon from '@material-ui/icons/Loop';\n\nconst KeyHashes = ({ hashes }) => {\n\tconst [idx, setIdx] = useState(0);\n\n\tuseEffect(() => {\n\t\tsetIdx(0);\n\t}, [hashes]);\n\n\tconst handleClick = () => {\n\t\tsetIdx(idx + 1 >= hashes.length ? 0 : idx + 1);\n\t};\n\n\tif (hashes.length < 1) return <>>;\n\treturn (\n\t\t\n\t\t\t\t\t \n\t\t\t\t\n\t\t\t}\n\t\t/>\n\t);\n};\n\nexport default KeyHashes;\n\nKeyHashes.propTypes = {\n\thashes: PropTypes.array.isRequired\n};\n","import React, { useEffect, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport TextField from '@material-ui/core/TextField';\nimport moment from 'moment';\nimport DateTime from '../../../core/input/DateTime';\nimport Grid from '@material-ui/core/Grid';\nimport PropTypes from 'prop-types';\nimport { useKeychainKeyCheck } from '@karpeleslab/klb-react-services';\nimport RichAlertTrans from '../../../core/feedback/RichAlertTrans';\nimport KeyHashes from './KeyHashes';\n\nconst Form = ({ data, setData, setIsValid, setChecking, disabled = false }) => {\n\tconst { t } = useTranslation();\n\n\tconst [hashes, setHashes] = useState(null);\n\tconst [validForm, setValidForm] = useState(false);\n\n\tconst [check, loading] = useKeychainKeyCheck();\n\n\tuseEffect(() => {\n\t\tsetChecking(loading);\n\t}, [setChecking, loading]);\n\n\tconst createChangeHandler = key => e => {\n\t\tlet toSet = { ...data, [key]: e.target.value };\n\n\t\tif (key === 'Data' && !getValue('Label')) {\n\t\t\tconst splited = toSet.Data.split(' ');\n\t\t\tif (splited.length >= 3) {\n\t\t\t\ttoSet.Label = splited[2];\n\t\t\t}\n\t\t}\n\n\t\tsetData(toSet);\n\t};\n\n\tconst getValue = (key, def = '') => {\n\t\tif (!(key in (data ?? {}))) return def;\n\t\treturn data[key];\n\t};\n\n\tconst getDateValue = (key, def = undefined) => {\n\t\tconst value = getValue(key, def);\n\t\tif (!value) return value;\n\t\tif (value instanceof moment) return value;\n\t\treturn moment(parseInt(data[key].unixms));\n\t};\n\n\tuseEffect(() => {\n\t\tsetIsValid(validForm && hashes !== 'error' && Array.isArray(hashes));\n\t}, [setIsValid, hashes, validForm]);\n\n\tuseEffect(() => {\n\t\tif (!('Data' in (data ?? {}))) {\n\t\t\tsetHashes('error');\n\n\t\t} else {\n\t\t\tcheck(data.Data, { handleError: false })\n\t\t\t\t.then(({ Hash }) => {\n\t\t\t\t\tsetHashes(Hash);\n\t\t\t\t})\n\t\t\t\t.catch(() => {\n\t\t\t\t\tsetHashes('error');\n\t\t\t\t});\n\t\t}\n\t}, [data, setHashes]);\n\n\tuseEffect(() => {\n\n\t\tif (!('Label' in (data ?? {})) || !('Data' in (data ?? {})))\n\t\t\tsetValidForm(false);\n\t\telse {\n\t\t\tsetValidForm(true);\n\n\t\t}\n\t}, [data, setValidForm]);\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t \n\t\t\t \n\t\t\t\n\t\t\t\t \n\t\t\t \n\t\t\t\n\t\t\t\t setData({ ...data, Expires: d })}\n\t\t\t\t\tclearable={true}\n\t\t\t\t\thelperText={t('keychain_key_expires_helperText')}\n\t\t\t\t\tfullWidth\n\t\t\t\t\tdisablePast\n\t\t\t\t/>\n\t\t\t \n\t\t\t{hashes === 'error' &&\n\t\t\t\n\t\t\t\t \n\t\t\t }\n\n\t\t\t{Array.isArray(hashes) && \n\t\t\t\t\n\t\t\t }\n\t\t \n\t);\n};\n\nexport default Form;\n\nForm.propTypes = {\n\tdata: PropTypes.object.isRequired,\n\tdisabled: PropTypes.bool,\n\tsetChecking: PropTypes.func.isRequired,\n\tsetData: PropTypes.func.isRequired,\n\tsetIsValid: PropTypes.func.isRequired\n};\n","export default () => {\n\tlet dt = new Date().getTime();\n\treturn 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {\n\t\tlet r = (dt + Math.random() * 16) % 16 | 0;\n\t\tdt = Math.floor(dt / 16);\n\t\treturn (c === 'x' ? r : ((r & 0x3) | 0x8)).toString(16);\n\t});\n};\n\nexport const validate = (uuid, prefix= null) => {\n\tconst r1 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;\n\tif (r1.exec(uuid) !== null) return true;\n\n\tif(prefix && !uuid.startsWith(prefix)) return false;\n\n\tconst r2 = /[a-z2-7]{6}-[a-z2-7]{4}-[a-z2-7]{4}-[a-z2-7]{4}-[a-z2-7]{8}$/;\n\treturn r2.exec(uuid) !== null;\n};\n","import React, { useEffect, useState } from 'react';\nimport Dialog from '@material-ui/core/Dialog';\nimport DialogContentText from '@material-ui/core/DialogContentText';\nimport DialogContent from '@material-ui/core/DialogContent';\nimport { useTranslation } from 'react-i18next';\nimport DialogTitle from '@material-ui/core/DialogTitle';\nimport DialogActions from '@material-ui/core/DialogActions';\nimport Form from './Form';\nimport moment from 'moment';\nimport Button from '../../../core/input/Button';\nimport Grid from '@material-ui/core/Grid';\nimport PropTypes from 'prop-types';\nimport { useKeychainKeyCreate } from '@karpeleslab/klb-react-services';\nimport uuid from '../../../../utils/uuid';\n\nconst CreateDialog = ({ keychain, open, setOpen, refresh, refreshing }) => {\n\tconst { t } = useTranslation();\n\tconst [saveEnabled, setSaveEnabled] = useState(false);\n\tconst [data, setData] = useState({});\n\tconst [create, creating] = useKeychainKeyCreate(keychain.Keychain__);\n\tconst [isValid, setIsValid] = useState(false);\n\tconst [isChecking, setIsChecking] = useState(false);\n\tconst [formKey, setFormKey] = useState(uuid()); // Because form as an internal state, use the key to reinitialize it.\n\n\tuseEffect(() => {\n\t\tsetSaveEnabled(isValid && !isChecking);\n\t}, [isValid, isChecking, setSaveEnabled]);\n\n\tconst handleClose = () => {\n\t\tsetOpen(false);\n\t};\n\n\tconst handleCreate = e => {\n\t\te.preventDefault();\n\t\tlet expires = null;\n\n\t\tif (data.Expires && data.Expires instanceof moment) {\n\t\t\texpires = '@' + data.Expires.unix();\n\t\t}\n\n\t\tcreate(data.Label.trim(), data.Data.trim(), expires)\n\t\t\t.then(() => refresh())\n\t\t\t.then(handleClose);\n\t};\n\n\treturn (\n\t\t {\n\t\t\t\tsetFormKey(uuid());\n\t\t\t\tsetData({});\n\t\t\t}}\n\t\t>\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{t('dialog_create_keychain_key_title')}\n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t{t('account_keychains_description')}\n\t\t\t\t\t \n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t{t('close_btn')}\n\t\t\t\t\t \n\t\t\t\t\t\n\t\t\t\t\t\t{t('add_btn')}\n\t\t\t\t\t \n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default CreateDialog;\n\nCreateDialog.propTypes = {\n\tkeychain: PropTypes.object.isRequired,\n\topen: PropTypes.bool.isRequired,\n\trefresh: PropTypes.func.isRequired,\n\trefreshing: PropTypes.bool.isRequired,\n\tsetOpen: PropTypes.func.isRequired\n};\n","import React, { useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport DeleteDialog from './DeleteDialog';\nimport Table from '../../../core/data/table/Table';\nimport TableDefinition from '../../../core/data/table/TableDefinition';\nimport DateUtil from '../../../core/data/Date/DateUtil';\nimport Button from '../../../core/input/Button';\nimport moment from 'moment';\nimport DeleteIcon from '@material-ui/icons/DeleteForever';\nimport PropTypes from 'prop-types';\nimport { Grid, IconButton } from '@material-ui/core';\nimport Toolbar from '../../../core/typography/Toolbar';\nimport AddIcon from '@material-ui/icons/Add';\nimport CreateDialog from './CreateDialog';\nimport { formatFingerprint } from '../../../../utils/crypt';\nimport useMediaQuery from '@material-ui/core/useMediaQuery';\nimport { useKeychainKeys } from '@karpeleslab/klb-react-services';\nimport KeyHashes from './KeyHashes';\n\nconst KeyTable = ({ keychain }) => {\n\tconst isMobile = useMediaQuery(theme => theme.breakpoints.down('xs'));\n\n\tconst [keys, fetch, loading] = useKeychainKeys(keychain.Keychain__);\n\tconst { t } = useTranslation();\n\n\tconst [selected, setSelected] = useState(null);\n\tconst [showDelete, setShowDelete] = useState(false);\n\tconst [showCreate, setShowCreate] = useState(false);\n\n\tconst onSelected = key => {\n\t\tsetSelected(key);\n\t\tsetShowDelete(true);\n\t};\n\n\tconst formatExpires = key => {\n\t\tconst expires = key.Expires ? moment(parseInt(key.Expires.unixms)) : null;\n\t\tif (!expires) return t('keychain_key_expires_never');\n\t\tif (expires && expires > moment()) return expires.format('LLL');\n\t\tif (expires && expires <= moment()) return t('keychain_key_expires_expired', { date: expires.format('LLL') });\n\t};\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t setShowCreate(true)}\n\t\t\t\t\t\tsize='small'\n\t\t\t\t\t\tvariant='contained'\n\t\t\t\t\t\tcolor='primary'\n\t\t\t\t\t\tstartIcon={ }\n\t\t\t\t\t>\n\t\t\t\t\t\t{t('add_btn')}\n\t\t\t\t\t \n\t\t\t\t \n\t\t\t \n\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t{key => {\n\t\t\t\t\t\t\tif (!isMobile) return key.Label;\n\t\t\t\t\t\t\treturn <>\n\t\t\t\t\t\t\t\t{key.Label} \n\t\t\t\t\t\t\t\t{formatFingerprint(key.Fingerprint)} \n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t{`${t('tablecell_key_expires')}: ${formatExpires(key)}`} \n\t\t\t\t\t\t\t\t\t onSelected(key)}\n\t\t\t\t\t\t\t\t\t\tsize='small'\n\t\t\t\t\t\t\t\t\t\tcolor='secondary'\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t>;\n\t\t\t\t\t\t}}\n\t\t\t\t\t \n\n\t\t\t\t\t{!isMobile &&\n\t\t\t\t\t\n\t\t\t\t\t\t{key => }\n\t\t\t\t\t \n\t\t\t\t\t}\n\n\t\t\t\t\t{!isMobile &&\n\t\t\t\t\t\n\t\t\t\t\t\t{key => formatExpires(key)}\n\t\t\t\t\t \n\t\t\t\t\t}\n\n\t\t\t\t\t{!isMobile &&\n\t\t\t\t\t\n\t\t\t\t\t\t{key => }\n\t\t\t\t\t \n\t\t\t\t\t}\n\t\t\t\t\t{!isMobile &&\n\t\t\t\t\t\n\t\t\t\t\t\t{key =>\n\t\t\t\t\t\t\t onSelected(key)}\n\t\t\t\t\t\t\t\tvariant='outlined'\n\t\t\t\t\t\t\t\tsize='small'\n\t\t\t\t\t\t\t\tcolor='secondary'\n\t\t\t\t\t\t\t\tstartIcon={ }\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{t('delete_btn')}\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t}\n\t\t\t\t\t \n\t\t\t\t\t}\n\t\t\t\t
\n\t\t\t \n\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default KeyTable;\n\nKeyTable.propTypes = {\n\tkeychain: PropTypes.object.isRequired\n};\n","export const sha1 = str => {\n\t// discuss at: https://locutus.io/php/sha1/\n\t// original by: Webtoolkit.info (https://www.webtoolkit.info/)\n\t// improved by: Michael White (https://getsprink.com)\n\t// improved by: Kevin van Zonneveld (https://kvz.io)\n\t// input by: Brett Zamir (https://brett-zamir.me)\n\t// note 1: Keep in mind that in accordance with PHP, the whole string is buffered and then\n\t// note 1: hashed. If available, we'd recommend using Node's native crypto modules directly\n\t// note 1: in a steaming fashion for faster and more efficient hashing\n\t// example 1: sha1('Kevin van Zonneveld')\n\t// returns 1: '54916d2e62f65b3afa6e192e6a601cdbe5cb5897'\n\n\tvar hash;\n\ttry {\n\t\tvar crypto = require('crypto');\n\t\tvar sha1sum = crypto.createHash('sha1');\n\t\tsha1sum.update(str);\n\t\thash = sha1sum.digest('hex');\n\t} catch (e) {\n\t\thash = undefined;\n\t}\n\n\tif (hash !== undefined) {\n\t\treturn hash;\n\t}\n\n\tvar _rotLeft = function (n, s) {\n\t\tvar t4 = (n << s) | (n >>> (32 - s));\n\t\treturn t4;\n\t};\n\n\tvar _cvtHex = function (val) {\n\t\tvar str = '';\n\t\tvar i;\n\t\tvar v;\n\n\t\tfor (i = 7; i >= 0; i--) {\n\t\t\tv = (val >>> (i * 4)) & 0x0f;\n\t\t\tstr += v.toString(16);\n\t\t}\n\t\treturn str;\n\t};\n\n\tvar blockstart;\n\tvar i, j;\n\tvar W = new Array(80);\n\tvar H0 = 0x67452301;\n\tvar H1 = 0xefcdab89;\n\tvar H2 = 0x98badcfe;\n\tvar H3 = 0x10325476;\n\tvar H4 = 0xc3d2e1f0;\n\tvar A, B, C, D, E;\n\tvar temp;\n\n\t// utf8_encode\n\tstr = unescape(encodeURIComponent(str));\n\tvar strLen = str.length;\n\n\tvar wordArray = [];\n\tfor (i = 0; i < strLen - 3; i += 4) {\n\t\tj =\n\t\t\t(str.charCodeAt(i) << 24) |\n\t\t\t(str.charCodeAt(i + 1) << 16) |\n\t\t\t(str.charCodeAt(i + 2) << 8) |\n\t\t\tstr.charCodeAt(i + 3);\n\t\twordArray.push(j);\n\t}\n\n\tswitch (strLen % 4) {\n\t\tcase 0:\n\t\t\ti = 0x080000000;\n\t\t\tbreak;\n\t\tcase 1:\n\t\t\ti = (str.charCodeAt(strLen - 1) << 24) | 0x0800000;\n\t\t\tbreak;\n\t\tcase 2:\n\t\t\ti =\n\t\t\t\t(str.charCodeAt(strLen - 2) << 24) |\n\t\t\t\t(str.charCodeAt(strLen - 1) << 16) |\n\t\t\t\t0x08000;\n\t\t\tbreak;\n\t\tcase 3:\n\t\t\ti =\n\t\t\t\t(str.charCodeAt(strLen - 3) << 24) |\n\t\t\t\t(str.charCodeAt(strLen - 2) << 16) |\n\t\t\t\t(str.charCodeAt(strLen - 1) << 8) |\n\t\t\t\t0x80;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\n\twordArray.push(i);\n\n\twhile (wordArray.length % 16 !== 14) {\n\t\twordArray.push(0);\n\t}\n\n\twordArray.push(strLen >>> 29);\n\twordArray.push((strLen << 3) & 0x0ffffffff);\n\n\tfor (blockstart = 0; blockstart < wordArray.length; blockstart += 16) {\n\t\tfor (i = 0; i < 16; i++) {\n\t\t\tW[i] = wordArray[blockstart + i];\n\t\t}\n\t\tfor (i = 16; i <= 79; i++) {\n\t\t\tW[i] = _rotLeft(W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16], 1);\n\t\t}\n\n\t\tA = H0;\n\t\tB = H1;\n\t\tC = H2;\n\t\tD = H3;\n\t\tE = H4;\n\n\t\tfor (i = 0; i <= 19; i++) {\n\t\t\ttemp =\n\t\t\t\t(_rotLeft(A, 5) + ((B & C) | (~B & D)) + E + W[i] + 0x5a827999) &\n\t\t\t\t0x0ffffffff;\n\t\t\tE = D;\n\t\t\tD = C;\n\t\t\tC = _rotLeft(B, 30);\n\t\t\tB = A;\n\t\t\tA = temp;\n\t\t}\n\n\t\tfor (i = 20; i <= 39; i++) {\n\t\t\ttemp =\n\t\t\t\t(_rotLeft(A, 5) + (B ^ C ^ D) + E + W[i] + 0x6ed9eba1) & 0x0ffffffff;\n\t\t\tE = D;\n\t\t\tD = C;\n\t\t\tC = _rotLeft(B, 30);\n\t\t\tB = A;\n\t\t\tA = temp;\n\t\t}\n\n\t\tfor (i = 40; i <= 59; i++) {\n\t\t\ttemp =\n\t\t\t\t(_rotLeft(A, 5) +\n\t\t\t\t\t((B & C) | (B & D) | (C & D)) +\n\t\t\t\t\tE +\n\t\t\t\t\tW[i] +\n\t\t\t\t\t0x8f1bbcdc) &\n\t\t\t\t0x0ffffffff;\n\t\t\tE = D;\n\t\t\tD = C;\n\t\t\tC = _rotLeft(B, 30);\n\t\t\tB = A;\n\t\t\tA = temp;\n\t\t}\n\n\t\tfor (i = 60; i <= 79; i++) {\n\t\t\ttemp =\n\t\t\t\t(_rotLeft(A, 5) + (B ^ C ^ D) + E + W[i] + 0xca62c1d6) & 0x0ffffffff;\n\t\t\tE = D;\n\t\t\tD = C;\n\t\t\tC = _rotLeft(B, 30);\n\t\t\tB = A;\n\t\t\tA = temp;\n\t\t}\n\n\t\tH0 = (H0 + A) & 0x0ffffffff;\n\t\tH1 = (H1 + B) & 0x0ffffffff;\n\t\tH2 = (H2 + C) & 0x0ffffffff;\n\t\tH3 = (H3 + D) & 0x0ffffffff;\n\t\tH4 = (H4 + E) & 0x0ffffffff;\n\t}\n\n\ttemp = _cvtHex(H0) + _cvtHex(H1) + _cvtHex(H2) + _cvtHex(H3) + _cvtHex(H4);\n\treturn temp.toLowerCase();\n};\n\nexport const formatFingerprint = fingerprint => {\n\treturn fingerprint.replace(/(.{2})/g, '$1:').slice(0, -1);\n};\n","import React from 'react';\nimport { useTranslation } from 'react-i18next';\nimport EmptyState from './Empty';\nimport Graphic from './../../../../assets/img/404.svg';\n\nconst NotFound = () => {\n\tconst { t } = useTranslation();\n\treturn (\n\t\t \n\t);\n};\n\nexport default NotFound;\n","import React from 'react';\nimport PageContainer from '../../components/layout/Container/PageContainer';\nimport NotFound from '../../components/core/feedback/State/NotFound';\nimport Helmet from 'react-helmet';\nimport { useTranslation } from 'react-i18next';\n\nconst PageNotFound = () => {\n\tconst { t } = useTranslation();\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t{ /* https://devhints.io/html-meta */}\n\t\t\t\t{t('page_notfound_title')} \n\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default PageNotFound;\n","import React from 'react';\nimport { Grid } from '@material-ui/core';\nimport { useTranslation } from 'react-i18next';\nimport PageContainer from '../../components/layout/Container/PageContainer';\nimport Toolbar from '../../components/core/typography/Toolbar';\nimport { useParams } from 'react-router';\nimport PageLoader from '../../components/layout/Loader/PageLoader';\nimport UpdateForm from '../../components/common/Keychain/UpdateForm';\nimport KeyTable from '../../components/common/Keychain/Key/KeyTable';\nimport PageNotFound from '../System/PageNotFound';\nimport { getSSHKeychainRoute } from '../../components/RouteController/Factory';\nimport { useKeychain } from '@karpeleslab/klb-react-services';\n\nconst KeychainEdit = () => {\n\tconst { t } = useTranslation();\n\tconst { keychainId } = useParams();\n\tconst [keychain, refresh] = useKeychain(keychainId);\n\n\tif (!keychain) return ;\n\tif (!keychain.data) return ;\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t \n\t\t\t\t \n\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t \n\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default KeychainEdit;\n","import PropTypes from 'prop-types';\nimport React, { useState } from 'react';\nimport TextField from '@material-ui/core/TextField';\nimport { Trans, useTranslation } from 'react-i18next';\nimport InputAdornment from '@material-ui/core/InputAdornment';\nimport CircularProgress from '@material-ui/core/CircularProgress';\nimport Grid from '@material-ui/core/Grid';\nimport Alert from '@material-ui/lab/Alert';\nimport HelpOutlineIcon from '@material-ui/icons/HelpOutline';\nimport Tooltip from '@material-ui/core/Tooltip';\n\nconst Affiliate = ({ affiliate }) => {\n\tconst { t } = useTranslation();\n\tconst [referral, setReferral] = useState('');\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t{t(`partnership_rate_${affiliate.Type.toLowerCase()}`)} \n\t\t\t \n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t} : undefined\n\t\t\t\t\t}\n\t\t\t\t/>\n\t\t\t \n\t\t\t\n\t\t\t\t setReferral(e.target.value)}\n\t\t\t\t\tvariant='outlined'\n\t\t\t\t\tfullWidth\n\t\t\t\t\tinputProps={{\n\t\t\t\t\t\tmaxLength: 64,\n\t\t\t\t\t}}\n\t\t\t\t\tInputProps={\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tendAdornment:\n\t\t\t\t\t\t\t\t(\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\tsample \n\t\t\t\t\t\t\t\t\t\t\t\tsample \n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\tplacement='top'\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t )\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t/>\n\t\t\t \n\t\t \n\t);\n};\n\nexport default Affiliate;\n\nAffiliate.propTypes = {\n\taffiliate: PropTypes.object.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React from 'react';\nimport { useTranslation } from 'react-i18next';\nimport Typography from '@material-ui/core/Typography';\nimport { Grid } from '@material-ui/core';\n\nconst AffiliatePayoutDetailsPaypal = ({ bankAccount }) => {\n\tconst { t } = useTranslation();\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{t('partnership_transfer_paypal_title')}\n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t{bankAccount.Meta.email}\n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default AffiliatePayoutDetailsPaypal;\n\nAffiliatePayoutDetailsPaypal.propTypes = {\n\tbankAccount: PropTypes.object.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React from 'react';\nimport { useTranslation } from 'react-i18next';\nimport Typography from '@material-ui/core/Typography';\nimport { Skeleton } from '@material-ui/lab';\nimport { useMoneySwift } from '@karpeleslab/klb-react-services';\nimport { Grid } from '@material-ui/core';\n\nconst AffiliatePayoutDetailsPaypalTransfer = ({ bankAccount }) => {\n\tconst { t } = useTranslation();\n\tconst [details] = useMoneySwift(bankAccount.Meta.swift ?? bankAccount.Meta.aba, !!bankAccount.Meta.aba);\n\n\tif (!details || !details.data) {\n\t\treturn ;\n\t}\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{t('partnership_transfer_bank_title')}\n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t{bankAccount.Meta.account_number}\n\t\t\t\t \n\t\t\t \n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{t('partnership_bank_info_name', { value: bankAccount.Meta.name })}\n\t\t\t\t \n\t\t\t \n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{\n\t\t\t\t\t\tt(`partnership_bank_info_${bankAccount.Meta.swift ? 'swift' : 'aba'}`,\n\t\t\t\t\t\t\t{ value: bankAccount.Meta.swift ?? bankAccount.Meta.aba }\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\t\t\t\t \n\t\t\t \n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{t('partnership_bank_institution', {\n\t\t\t\t\t\tvalue: details.data.Institution_Name,\n\t\t\t\t\t\tcountry: details.data.Iso_Country_Code\n\t\t\t\t\t})}\n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default AffiliatePayoutDetailsPaypalTransfer;\n\nAffiliatePayoutDetailsPaypalTransfer.propTypes = {\n\tbankAccount: PropTypes.object.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React from 'react';\nimport Skeleton from '@material-ui/lab/Skeleton';\nimport AffiliatePayoutDetailsPaypal from './AffiliatePayoutDetailsPaypal';\nimport AffiliatePayoutDetailsTransfer from './AffiliatePayoutDetailsTransfer';\nimport { useMoneyBankAccount } from '@karpeleslab/klb-react-services';\n\nconst AffiliatePayoutDetails = ({ bankAccountId }) => {\n\tconst [bankAccount] = useMoneyBankAccount(bankAccountId);\n\n\tif (!bankAccount || !bankAccount.data)\n\t\treturn ;\n\n\tif (bankAccount.data.Meta.transfer_type === 'paypal')\n\t\treturn ;\n\n\treturn ;\n};\n\nexport default AffiliatePayoutDetails;\n\nAffiliatePayoutDetails.propTypes = {\n\tbankAccountId: PropTypes.string.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React from 'react';\nimport DialogTitle from '@material-ui/core/DialogTitle';\nimport DialogContent from '@material-ui/core/DialogContent';\nimport DialogActions from '@material-ui/core/DialogActions';\nimport Button from '../../core/input/Button';\nimport Dialog from '@material-ui/core/Dialog';\nimport { useTranslation } from 'react-i18next';\nimport AffiliatePayoutDetails from './AffiliatePayoutDetails';\n\nconst AffiliatePayoutDetailsDialog = ({ open, setOpen, moneyBankAccountId }) => {\n\tconst { t } = useTranslation();\n\n\tconst handleClose = () => {\n\t\tsetOpen(false);\n\t};\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t{t('dialog_payout_details_title')}\n\t\t\t \n\t\t\t\n\t\t\t\t\n\t\t\t \n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{t('close_btn')}\n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default AffiliatePayoutDetailsDialog;\n\nAffiliatePayoutDetailsDialog.propTypes = {\n\topen: PropTypes.bool.isRequired,\n\tsetOpen: PropTypes.func.isRequired,\n\tmoneyBankAccountId: PropTypes.string.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React, { useEffect, useState } from 'react';\nimport { useUserWalletAutos } from '@karpeleslab/klb-react-services';\nimport Grid from '@material-ui/core/Grid';\nimport { Skeleton } from '@material-ui/lab';\nimport { useTranslation } from 'react-i18next';\nimport Button from '../../../core/input/Button';\nimport AffiliatePayoutDetailsDialog from '../AffiliatePayoutDetailsDialog';\n\nconst WalletTablePayout = ({ wallet }) => {\n\tconst { t } = useTranslation();\n\n\tconst [list, fetch, loading] = useUserWalletAutos(wallet.User_Wallet__);\n\tconst [showPayoutDetails, setShowPayoutDetails] = useState(false);\n\tconst [selected, setSelected] = useState(null);\n\n\tuseEffect(() => {\n\t\t// We are not making a table but directly displaying everything\n\t\t// There will be usually 0 or 1 User Wallet Auto per wallet, so querying 100 per page is far enough\n\t\tfetch({ results_per_page: 100 });\n\t\t// eslint-disable-next-line\n\t}, []);\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t{(loading || !list) && }\n\t\t\t\t{(!loading && !!list && list.data.length < 1) && t('affiliate_no_user_wallet_payout')}\n\t\t\t\t{(!loading && !!list && list.data.length > 0) &&\n\t\t\t\t\n\t\t\t\t\t{list.data.map(userWalletAuto =>\n\t\t\t\t\t\t(\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t {\n\t\t\t\t\t\t\t\t\t\tsetSelected(userWalletAuto.Money_Bank_Account__);\n\t\t\t\t\t\t\t\t\t\tsetShowPayoutDetails(true);\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\tvariant='outlined'\n\t\t\t\t\t\t\t\t\tcolor='primary'\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{userWalletAuto.Money_Bank_Account.Label}\n\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t \n\t\t\t\t\t\t)\n\t\t\t\t\t)}\n\t\t\t\t \n\t\t\t\t}\n\t\t\t \n\t\t\t{/*Not really optimized as this component is called in a Table, so if will include several time the dialog,\n\t\t\t but the table itself will contains 1 entries most of the time*/}\n\t\t\t{selected && }\n\t\t \n\t);\n};\n\nexport default WalletTablePayout;\n\nWalletTablePayout.propTypes = {\n\twallet: PropTypes.object.isRequired\n};\n","import React from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { useUserWallets } from '@karpeleslab/klb-react-services';\nimport TableDefinition from '../../../core/data/table/TableDefinition';\nimport Table from '../../../core/data/table/Table';\nimport WalletTablePayout from './WalletTablePayout';\n\nconst WalletsTable = (props) => {\n\tconst { t } = useTranslation();\n\tconst [wallets, fetch, loading] = useUserWallets('@');\n\n\treturn (\n\t\t\n\t\t\t \n\t\t\t\n\t\t\t\t{wallet => }\n\t\t\t \n\t\t\t\n\t\t\t\t{wallet => wallet.Balance.display}\n\t\t\t \n\t\t
\n\t);\n};\n\nexport default WalletsTable;\n","import React, { useEffect, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport TextField from '@material-ui/core/TextField';\nimport PropTypes from 'prop-types';\nimport moment from 'moment';\nimport { isString } from '../../../utils/misc';\n\nconst YearSelector = ({ value, setValue, interval = [-3, 0], disabled = false, required = false, ...rest }) => {\n\tconst { t } = useTranslation();\n\tconst [possibleValues, setPossibleValues] = useState([]);\n\n\tuseEffect(() => {\n\t\tconst now = parseInt(moment().format('YYYY'));\n\t\tlet cleanedInterval = interval;\n\t\tif(cleanedInterval.length < 1) cleanedInterval.push(0);\n\t\tif(cleanedInterval.length === 1) cleanedInterval.push(0);\n\t\tconst tmp = [];\n\n\t\tconst from = isString(cleanedInterval[0]) ? parseInt(cleanedInterval[0]) : now + cleanedInterval[0];\n\t\tconst to = isString(cleanedInterval[1]) ? parseInt(cleanedInterval[1]) : now + cleanedInterval[1];\n\n\t\tfor (let i = to; i >= from; i--) {\n\t\t\ttmp.push(i);\n\t\t}\n\n\t\tsetPossibleValues(tmp);\n\t}, [setPossibleValues]);\n\n\treturn (\n\t\t setValue(e.target.value)}\n\t\t\tselect\n\t\t\tfullWidth\n\t\t\tdisabled={disabled}\n\t\t\trequired={required}\n\t\t\tvariant='outlined'\n\t\t\tSelectProps={{\n\t\t\t\tnative: true\n\t\t\t}}\n\t\t\t{...rest}\n\t\t>\n\t\t\t{possibleValues.map(v => {v} )}\n\t\t \n\t);\n};\n\nexport default YearSelector;\n\nYearSelector.propTypes = {\n\tdisabled: PropTypes.bool,\n\tinterval: PropTypes.number,\n\trequired: PropTypes.bool,\n\tsetValue: PropTypes.func.isRequired,\n\tvalue: PropTypes.string\n};\n","import React, { createContext, memo, useContext, useEffect, useState } from 'react';\nimport PropTypes from 'prop-types';\nimport { RestContext } from '@karpeleslab/klb-react-services';\nimport { useTranslation } from 'react-i18next';\n\nexport const SnackbarValueContext = createContext({});\nexport const SnackbarSetContext = createContext(() => {\n});\n\nconst SnackbarProvider = memo(({ setSnackbar, children }) => {\n\tconst handleSnackbarSet = (message, type = 'default') => {\n\t\tsetSnackbar({ message, type });\n\t};\n\n\treturn (\n\t\t\n\t\t\t{children}\n\t\t \n\t);\n});\n\nSnackbarProvider.displayName = 'SnackbarProvider';\nSnackbarProvider.propTypes = {\n\tsetSnackbar: PropTypes.func.isRequired,\n\tchildren: PropTypes.oneOfType([\n\t\tPropTypes.arrayOf(PropTypes.node),\n\t\tPropTypes.node\n\t]).isRequired\n};\n\nexport const SnackbarContainer = ({ children }) => {\n\tconst { t } = useTranslation();\n\tconst [snackbar, setSnackbar] = useState({\n\t\tmessage: '',\n\t\ttype: 'default'\n\t});\n\n\tconst { setSnackMessageCallback } = useContext(RestContext);\n\n\tuseEffect(() => {\n\t\tsetSnackMessageCallback((message, type, i18n) => {\n\t\t\t// Ignore this message as now a proper modal is shown when the user's session (PR 162)\n\t\t\tif (message === 'error_login_required') return;\n\t\t\tsetSnackbar({ message: i18n ? t(message) : message, type });\n\t\t});\n\t}, [setSnackbar, setSnackMessageCallback]);\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t{children}\n\t\t\t \n\t\t \n\t);\n};\n\n\nSnackbarContainer.propTypes = {\n\tchildren: PropTypes.oneOfType([\n\t\tPropTypes.arrayOf(PropTypes.node),\n\t\tPropTypes.node\n\t]).isRequired\n};\n","import { useContext } from 'react';\nimport { SnackbarSetContext, SnackbarValueContext } from '../context/SnackbarContext';\n\nconst useSetSnackbar = () => useContext(SnackbarSetContext);\nconst useGetSnackbar = () => useContext(SnackbarValueContext);\nconst useSnackbar = () => {\n\tconst setSnackbar = useContext(SnackbarSetContext);\n\tconst snackbar = useContext(SnackbarValueContext);\n\n\treturn {\n\t\tsetSnackbar,\n\t\tsnackbar\n\t};\n};\n\nexport {\n\tuseGetSnackbar,\n\tuseSetSnackbar,\n\tuseSnackbar\n};\n","import PropTypes from 'prop-types';\nimport React, { useEffect, useState } from 'react';\nimport Grid from '@material-ui/core/Grid';\nimport YearSelector from '../../core/input/YearSelector';\nimport Button from '../../core/input/Button';\nimport { useTranslation } from 'react-i18next';\nimport { useAffiliateExportOrder } from '@karpeleslab/klb-react-services';\nimport { rest } from '@karpeleslab/klbfw';\nimport { useSetSnackbar } from '../../../hooks/useSnackbar';\n\nconst OrdersExport = ({ affiliate }) => {\n\tconst [year, setYear] = useState(new Date().getFullYear());\n\tconst [generating, setGenerating] = useState(false);\n\tconst [generate] = useAffiliateExportOrder(affiliate.Affiliate__);\n\tconst [interval, setIntervalVar] = useState(null);\n\tconst setSnackbar = useSetSnackbar();\n\n\tconst { t } = useTranslation();\n\n\tconst handleExport = () => {\n\t\tsetGenerating(true);\n\t\tgenerate().then(j => {\n\t\t\t// This is dirty AF but we don't have realtime management stuff to handle the job so we pull it every 5 sec;\n\t\t\t// One day maybe once we will take this we will clean that\n\t\t\tconst interval = setInterval(() => {\n\t\t\t\trest(`Job/${j.Job__}`)\n\t\t\t\t\t.then(d => d.data)\n\t\t\t\t\t.then(j => {\n\t\t\t\t\t\tif (!j.Finished) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tclearInterval(interval);\n\t\t\t\t\t\tsetIntervalVar(null);\n\t\t\t\t\t\tsetGenerating(false);\n\t\t\t\t\t\tsetSnackbar(t('affiliate_export_order_success'), 'success');\n\t\t\t\t\t});\n\t\t\t}, 5000);\n\t\t});\n\t};\n\n\tuseEffect(() => {\n\t\tif (!interval) return;\n\t\treturn () => clearInterval(interval);\n\t}, [interval]);\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{t('affiliate_order_export_btn')}\n\t\t\t\t \n\t\t\t \n\t\t\t\n\t\t\t\t \n\t\t\t \n\n\t\t \n\t);\n};\n\nexport default OrdersExport;\n\nOrdersExport.propTypes = {\n\taffiliate: PropTypes.object.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React from 'react';\nimport Table from '../../core/data/table/Table';\nimport { useTranslation } from 'react-i18next';\nimport TableDefinition from '../../core/data/table/TableDefinition';\nimport DateUtil from '../../core/data/Date/DateUtil';\nimport { useOrders } from '@karpeleslab/klb-react-services';\nimport OrdersExport from './OrdersExport';\n\nconst PendingOrder = ({ affiliate }) => {\n\tconst { t } = useTranslation();\n\tconst [orders, fetch, loading] = useOrders();\n\n\treturn (\n\t\t\n\t\t\t]}\n\t\t>\n\t\t\t\n\t\t\t\t{order => }\n\t\t\t \n\n\t\t\t \n\n\t\t\t\n\t\t\t\t{order => order.Affiliate_Total.display ?? '-'}\n\t\t\t \n\t\t
\n\t);\n};\n\nexport default PendingOrder;\n\nPendingOrder.propTypes = {\n\taffiliate: PropTypes.object.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React from 'react';\nimport { useTranslation } from 'react-i18next';\nimport Table from '../../core/data/table/Table';\nimport TableDefinition from '../../core/data/table/TableDefinition';\nimport DateUtil from '../../core/data/Date/DateUtil';\nimport { useMoneyBankWithdraws } from '@karpeleslab/klb-react-services';\n\nconst PendingPayout = ({ affiliate, statuses = [] }) => {\n\tconst { t } = useTranslation();\n\tconst [withdraw, fetch, loading] = useMoneyBankWithdraws();\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t{w => }\n\t\t\t \n\n\t\t\t\n\t\t\t\t{() => affiliate.Money_Bank_Account ? affiliate.Money_Bank_Account.Label : '-'}\n\t\t\t \n\n\t\t\t\n\t\t\t\t{w => t(`partnership_payout_status_${w.Status.toLocaleLowerCase()}`)}\n\t\t\t \n\n\t\t\t\n\t\t\t\t{w => w.Amount.display ?? '-'}\n\t\t\t \n\t\t
\n\t);\n};\n\nexport default PendingPayout;\n\nPendingPayout.propTypes = {\n\taffiliate: PropTypes.object.isRequired,\n\tstatuses: PropTypes.array\n};\n","import React, { useState } from 'react';\nimport PageContainer from '../../components/layout/Container/PageContainer';\nimport PageTitle from '../../components/core/typography/PageTitle';\nimport { Trans, useTranslation } from 'react-i18next';\nimport { Grid } from '@material-ui/core';\nimport Affiliate from '../../components/common/Affiliate/Affiliate';\nimport WalletsTable from '../../components/common/Affiliate/Wallet/WalletsTable';\nimport PageLoader from '../../components/layout/Loader/PageLoader';\nimport Tabs from '@material-ui/core/Tabs';\nimport Tab from '@material-ui/core/Tab';\nimport Panel from '../../components/layout/Container/tab/Panel';\nimport PendingOrder from '../../components/common/Affiliate/PendingOrder';\nimport PendingPayout from '../../components/common/Affiliate/PendingPayout';\nimport PageNotFound from '../System/PageNotFound';\nimport { useAffiliate } from '@karpeleslab/klb-react-services';\n\nconst TRANSFER_TAB_ORDER_PENDING = 0;\nconst TRANSFER_TAB_BANK_PENDING = 1;\n\nconst Partnership = () => {\n\tconst { t } = useTranslation();\n\tconst [affiliate] = useAffiliate('@');\n\tconst [transferTab, setTransferTab] = useState(TRANSFER_TAB_ORDER_PENDING);\n\n\tconst handleTabChange = (event, newValue) => {\n\t\tsetTransferTab(newValue);\n\t};\n\n\tif (!affiliate) return ;\n\tif (!affiliate.data) return ;\n\n\treturn (\n\t\t\n\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\tsample \n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\tsample\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\tsample\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t
\n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t \n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t{affiliate.data.Payout_Method === 'transfer' &&\n\t\t\t\t\t\t\n\t\t\t\t\t\t}\n\t\t\t\t\t \n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t \n\n\t\t\t\t\t{affiliate.data.Payout_Method === 'transfer' &&\n\t\t\t\t\t\n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t\t}\n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default Partnership;\n","import React from 'react';\nimport { useTranslation } from 'react-i18next';\nimport makeStyles from '@material-ui/core/styles/makeStyles';\nimport Card from '@material-ui/core/Card';\nimport CardContent from '@material-ui/core/CardContent';\nimport Typography from '@material-ui/core/Typography';\nimport Grid from '@material-ui/core/Grid';\nimport Skeleton from '@material-ui/lab/Skeleton';\nimport PropTypes from 'prop-types';\nimport DateUtil from '../../../core/data/Date/DateUtil';\n\nconst useStyles = makeStyles(() => ({\n\tcard: {\n\t\twhiteSpace: 'pre-wrap',\n\t\theight: '100%'\n\t}\n}));\n\n\nconst OrderInfo = ({ order, elevation = 0 }) => {\n\tconst classes = useStyles();\n\tconst { t } = useTranslation();\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{t('details')}\n\t\t\t\t \n\n\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t{t('order_payment_status')}: \n\t\t\t\t\t \n\n\t\t\t\t\t\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\torder &&\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t{t('order_status_' + order.Status)}\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t}\n\t\t\t\t\t\t{!order && }\n\t\t\t\t\t \n\n\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t{t('label_order_date')}: \n\t\t\t\t\t \n\n\t\t\t\t\t\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\torder && }\n\t\t\t\t\t\t{!order && }\n\t\t\t\t\t \n\n\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t{t('label_paid_date')}: \n\t\t\t\t\t \n\n\n\t\t\t\t\t\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\torder && \n\t\t\t\t\t\t}\n\t\t\t\t\t\t{!order && }\n\t\t\t\t\t \n\n\t\t\t\t \n\n\t\t\t \n\t\t \n\t);\n};\n\nexport default OrderInfo;\n\nOrderInfo.propTypes = {\n\televation: PropTypes.number,\n\torder: PropTypes.number\n};\n","import React from 'react';\nimport PropTypes from 'prop-types';\n\nconst OrderPaymentMethod = ({ order }) => {\n\treturn (\n\t\t\n\t\t\t{(order.Payment_Method && order.Payment_Class) && order.Payment_Method + ' - ' + order.Payment_Class}\n\t\t\t{(!order.Payment_Method && order.Payment_Class) && order.Payment_Class}\n\t\t\t{(order.Payment_Method && !order.Payment_Class) && order.Payment_Method}\n\t\t \n\t);\n};\n\nexport default OrderPaymentMethod;\n\nOrderPaymentMethod.propTypes = {\n\torder: PropTypes.object.isRequired\n};\n","import React from 'react';\nimport makeStyles from '@material-ui/core/styles/makeStyles';\nimport { useTranslation } from 'react-i18next';\nimport CardContent from '@material-ui/core/CardContent';\nimport Typography from '@material-ui/core/Typography';\nimport Grid from '@material-ui/core/Grid';\nimport Skeleton from '@material-ui/lab/Skeleton';\nimport Card from '@material-ui/core/Card';\nimport OrderPaymentMethod from './OrderPaymentMethod';\nimport PropTypes from 'prop-types';\n\n\nconst useStyles = makeStyles(() => ({\n\tcard: {\n\t\twhiteSpace: 'pre-wrap',\n\t\theight: '100%'\n\t}\n}));\n\n\nconst OrderPaymentInfo = ({ order, elevation = 0 }) => {\n\tconst classes = useStyles();\n\tconst { t } = useTranslation();\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{t('order_payment_info')}\n\t\t\t\t \n\n\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t{t('order_payment_method')}: \n\t\t\t\t\t \n\n\t\t\t\t\t\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\torder &&\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t}\n\t\t\t\t\t\t{!order && }\n\t\t\t\t\t \n\n\n\t\t\t\t\t{(order && order.Payment_Last4) &&\n\t\t\t\t\t<>\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t{t('order_payment_card')}: \n\t\t\t\t\t\t \n\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t{`${order.Payment_Method}⋯${order.Payment_Last4}`}\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t>\n\t\t\t\t\t}\n\t\t\t\t \n\n\t\t\t \n\t\t \n\t);\n};\n\nexport default OrderPaymentInfo;\n\nOrderPaymentInfo.propTypes = {\n\televation: PropTypes.number,\n\torder: PropTypes.object\n};\n","import React from 'react';\nimport makeStyles from '@material-ui/core/styles/makeStyles';\nimport Card from '@material-ui/core/Card';\nimport CardContent from '@material-ui/core/CardContent';\nimport Typography from '@material-ui/core/Typography';\nimport Skeleton from '@material-ui/lab/Skeleton';\nimport PhoneIcon from '@material-ui/icons/Phone';\nimport PropTypes from 'prop-types';\n\nconst useStyles = makeStyles(() => ({\n\tcard: {\n\t\twhiteSpace: 'pre-wrap',\n\t\theight: '100%'\n\t}\n}));\n\nconst UserLocation = ({ title, address, elevation = 0 }) => {\n\tconst classes = useStyles();\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t{title} \n\n\t\t\t\t{!address && }\n\t\t\t\t{\n\t\t\t\t\taddress &&\n\t\t\t\t\t\n\t\t\t\t\t\t{address.Display.join('\\n')}\n\t\t\t\t\t \n\t\t\t\t}\n\t\t\t\t{\n\t\t\t\t\t(address && address.Contact_Phone) &&\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t{address.Contact_Phone}\n\t\t\t\t\t \n\t\t\t\t}\n\t\t\t \n\t\t \n\t);\n};\n\nexport default UserLocation;\n\nUserLocation.propTypes = {\n\taddress: PropTypes.bool,\n\televation: PropTypes.number,\n\ttitle: PropTypes.string\n};\n","import React, { useEffect, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport TableContainer from '@material-ui/core/TableContainer';\nimport Table from '@material-ui/core/Table';\nimport TableHead from '@material-ui/core/TableHead';\nimport TableCell from '@material-ui/core/TableCell';\nimport TableRow from '@material-ui/core/TableRow';\nimport TableBody from '@material-ui/core/TableBody';\nimport Skeleton from '@material-ui/lab/Skeleton';\nimport Paper from '@material-ui/core/Paper';\nimport PropTypes from 'prop-types';\n\nconst OrderTable = ({ order, elevation = 0 }) => {\n\tconst [rowSpan, setRowSpan] = useState(3);\n\tconst { t } = useTranslation();\n\tuseEffect(() => {\n\t\tif (!order) return;\n\t\tlet c = 3;\n\t\tif (parseInt(order.Subtotals.shipping.value_int)) c += 1;\n\t\tif (parseInt(order.Subtotals.discount.value_int)) c += 1;\n\n\t\tsetRowSpan(c);\n\n\t}, [order]);\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t{t('details')}\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t{t('order_detail_price')} \n\t\t\t\t\t\t \n\t\t\t\t\t\t\n\t\t\t\t\t\t\t{t('order_detail_description')} \n\t\t\t\t\t\t\t{t('order_detail_quantity')} \n\t\t\t\t\t\t\t{t('order_detail_unit')} \n\t\t\t\t\t\t\t{t('order_detail_sum')} \n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t\t\n\t\t\t\t\t\t{order && order.Items.map(row => (\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t{row.Catalog_Product['Basic.Name']} \n\t\t\t\t\t\t\t\t{row.Quantity} \n\t\t\t\t\t\t\t\t{row.Price.display} \n\t\t\t\t\t\t\t\t{row.Full_Price.display} \n\t\t\t\t\t\t\t \n\t\t\t\t\t\t))}\n\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t!order &&\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t \n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t{t('order_detail_subtotal')} \n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t{order && order.Total.display}\n\t\t\t\t\t\t\t\t{!order && }\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t \n\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t(order && parseInt(order.Subtotals.shipping.value_int) !== 0) &&\n\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t{t('order_detail_shipping')} \n\t\t\t\t\t\t\t\t{order.Subtotals.shipping.display} \n\t\t\t\t\t\t\t \n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t{t('order_detail_tax')} \n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t{order && order.Vat_Rate + '%'}\n\t\t\t\t\t\t\t\t{!order && }\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t{order && order.Vat_Amount.display}\n\t\t\t\t\t\t\t\t{!order && }\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t \n\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t(order && parseInt(order.Subtotals.discount.value_int) !== 0) &&\n\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t{t('order_detail_discount')} \n\t\t\t\t\t\t\t\t{order.Subtotals.discount.display} \n\t\t\t\t\t\t\t \n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t{t('order_detail_total')} \n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t{order && order.Total_Vat.display}\n\t\t\t\t\t\t\t\t{!order && }\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t
\n\t\t\t \n\t\t \n\t);\n};\n\nexport default OrderTable;\n\nOrderTable.propTypes = {\n\televation: PropTypes.number,\n\torder: PropTypes.object\n};\n","import PropTypes from 'prop-types';\nimport React from 'react';\nimport Tab from '@material-ui/core/Tab';\nimport { useTranslation } from 'react-i18next';\n\nconst PaymentMethodTab = ({ method, ...rest }) => {\n\tconst { t } = useTranslation();\n\n\tswitch (method) {\n\t\tcase 'Bitpay':\n\t\tcase 'Free':\n\t\tcase 'OnFile':\n\t\tcase 'Wallet':\n\t\tcase 'Stripe':\n\t\tcase 'Paypal':\n\t\t\treturn ;\n\t\tdefault:\n\t\t\treturn null;\n\t}\n};\n\nexport default PaymentMethodTab;\n\nPaymentMethodTab.propTypes = {\n\tdisabled: PropTypes.bool.isRequired,\n\tmethod: PropTypes.string.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React, { useCallback, useEffect, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { useOrderProcess } from '@karpeleslab/klb-react-services';\nimport Grid from '@material-ui/core/Grid';\nimport Button from '../../../../../core/input/Button';\nimport { useSetSnackbar } from '../../../../../../hooks/useSnackbar';\nimport RichAlertTrans from '../../../../../core/feedback/RichAlertTrans';\n\nconst Bitpay = ({ order, settings, setPaying, refreshOrder, setDialogActions = null }) => {\n\tconst { t } = useTranslation();\n\n\tconst [processOrder] = useOrderProcess(order.Order__);\n\n\t// Setting the bitpay script will set this var\n\tconst [loading, setLoading] = useState(!!window.bitpay_loading);\n\n\tconst setSnackbar = useSetSnackbar();\n\n\tconst bitpayListenerCallback = useCallback((e) => {\n\t\tif (e.data.status !== 'paid') return;\n\n\t\twindow.removeEventListener('message', bitpayListenerCallback);\n\t\t// Doing so will refresh the order data\n\t\t// handleError: false because bitpay is crap\n\t\tprocessOrder(settings.session, settings.method, {}, { snackMessageToken: 'order_paid', handleError: false })\n\t\t\t.then(d => refreshOrder(d.order));\n\t}, []);\n\n\tconst loadBitpayScript = (src, onLoad) => {\n\t\tconst existing = document.getElementById('bitpay-script');\n\t\tif (existing) {\n\t\t\tdelete window.bitpay;\n\t\t\texisting.remove();\n\t\t}\n\n\t\tconst scriptEl = document.createElement('script');\n\t\tscriptEl.setAttribute('id', 'bitpay-script');\n\t\tscriptEl.async = false;\n\t\tscriptEl.src = src;\n\t\tscriptEl.onload = onLoad;\n\t\tdocument.body.appendChild(scriptEl);\n\t};\n\n\tconst resetScript = useCallback(() => {\n\t\tconst existing = document.getElementById('bitpay-script');\n\t\tif (existing) {\n\t\t\tdelete window.bitpay;\n\t\t\texisting.remove();\n\t\t}\n\t\twindow.dispatchEvent(new CustomEvent('loadingChange', { detail: false }));\n\t}, []);\n\n\n\tconst init = async () => {\n\t\tconst process = await processOrder(settings.session, settings.method, {}, { handleError: false });\n\n\t\tif (!process) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst js = process.methods.Bitpay.fields._javascript;\n\t\tconst invoiceId = process.methods.Bitpay.fields.Bitpay_Invoice_Id;\n\n\t\tif (!js) {\n\t\t\treturn false;\n\t\t}\n\n\t\tloadBitpayScript(js, () => {\n\t\t\tif (process) refreshOrder(process.order);\n\n\t\t\twindow.dispatchEvent(new CustomEvent('loadingChange', { detail: true }));\n\t\t\twindow.bitpay.showInvoice(invoiceId);\n\t\t\twindow.bitpay.onModalWillLeave(resetScript);\n\t\t});\n\n\t\treturn true;\n\t};\n\n\tuseEffect(() => {\n\t\tif (typeof window === 'undefined' || order.Status === 'pending') {\n\t\t\treturn;\n\t\t}\n\t\t// Bitpay is sometimes crap and the event 'message' is not trigger\n\t\t// So we use an active pulling just in case to check if the order is paid\n\t\tconst interval = setInterval(() => {\n\t\t\t// handleError: false because bitpay is crap\n\t\t\tprocessOrder(settings.session, settings.method, {}, { handleError: false })\n\t\t\t\t.then(process => {\n\t\t\t\t\tif (!process.order.Paid) return;\n\t\t\t\t\t// We need to set the confirmation message manually\n\t\t\t\t\tsetSnackbar(t('order_paid'), 'success');\n\t\t\t\t\trefreshOrder(process.order);\n\t\t\t\t});\n\t\t}, 60 * 1000);\n\n\t\treturn () => {\n\t\t\tclearInterval(interval);\n\t\t};\n\t}, [order]);\n\n\t// Listen for bitpay events\n\tuseEffect(() => {\n\t\tif (typeof window === 'undefined')\n\t\t\treturn;\n\n\t\twindow.addEventListener('message', bitpayListenerCallback);\n\n\t\treturn () => {\n\t\t\twindow.removeEventListener('message', bitpayListenerCallback);\n\t\t};\n\t}, [bitpayListenerCallback]);\n\n\tconst handleLoading = useCallback(event => {\n\t\twindow.bitpay_loading = event.detail;\n\t\tsetLoading(event.detail);\n\t}, []);\n\n\tuseEffect(() => {\n\t\twindow.addEventListener('loadingChange', handleLoading);\n\t\treturn () => {\n\t\t\twindow.removeEventListener('loadingChange', handleLoading);\n\t\t};\n\n\t}, []);\n\n\n\t// The button is only use the first time, when the payment method hasn't been set\n\tconst handleProcess = async () => {\n\t\tif (typeof window === 'undefined') return;\n\n\t\t// We simply at maximum the process, always reload bitpay completely,\n\t\t// It will be slower, but if will simplify A LOT the process\n\t\tsetPaying(true); // Will block all other payment method\n\n\t\twindow.dispatchEvent(new CustomEvent('loadingChange', { detail: true }));\n\n\t\tconst result = await init();\n\t\tif (!result) {\n\t\t\tsetPaying(false);\n\t\t\twindow.dispatchEvent(new CustomEvent('loadingChange', { detail: false }));\n\t\t}\n\t};\n\n\tuseEffect(() => {\n\t\tif (!setDialogActions) return;\n\t\tsetDialogActions((\n\t\t\t\n\t\t\t\t{t(order.Status !== 'pending' ? 'continue_with_bitpay_btn' : 'checkout_with_bitpay_btn')}\n\t\t\t \n\t\t));\n\t}, [setDialogActions, loading, order]);\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{order.Status !== 'pending' &&\n\t\t\t\t\t\n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t\t}\n\t\t\t\t\t{order.Status === 'pending' &&\n\t\t\t\t\t\n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t\t}\n\t\t\t\t\t{!setDialogActions && \n\t\t\t\t\t\t\n\t\t\t\t\t\t\t{t(order.Status !== 'pending' ? 'continue_with_bitpay_btn' : 'checkout_with_bitpay_btn')}\n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t\t}\n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default Bitpay;\n\nBitpay.propTypes = {\n\trefreshOrder: PropTypes.func.isRequired,\n\tsetPaying: PropTypes.func.isRequired,\n\tsettings: PropTypes.object.isRequired,\n\torder: PropTypes.object.isRequired,\n\tsetDialogActions: PropTypes.func // Used when the component is used in a dialog in order to integrate the action into the dialog actions\n};\n","import PropTypes from 'prop-types';\nimport React, { useEffect } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { useOrderProcess } from '@karpeleslab/klb-react-services';\nimport Grid from '@material-ui/core/Grid';\nimport { Typography } from '@material-ui/core';\nimport Button from '../../../../../core/input/Button';\n\nconst Free = ({ order, settings, setPaying, refreshOrder, setDialogActions = null }) => {\n\tconst { t } = useTranslation();\n\n\tconst [processOrder, processingOrder] = useOrderProcess(order.Order__);\n\n\tuseEffect(() => {\n\t\tsetPaying(processingOrder);\n\t}, [processingOrder]);\n\n\tconst handleProcess = () => {\n\t\tprocessOrder(settings.session, settings.method, {}, { snackMessageToken: 'order_paid' })\n\t\t\t.then(d => refreshOrder(d.order));\n\t};\n\n\tuseEffect(() => {\n\t\tif (!setDialogActions) return;\n\t\tsetDialogActions((\n\t\t\t\n\t\t\t\t{t('free_order_btn')}\n\t\t\t \n\t\t));\n\n\t}, [setDialogActions, processingOrder]);\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t{t('free_order_text')} \n\t\t\t \n\t\t\t{!setDialogActions && \n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t{t('free_order_btn')}\n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t \n\t\t\t \n\t\t\t}\n\t\t \n\t);\n};\n\nexport default Free;\n\nFree.propTypes = {\n\trefreshOrder: PropTypes.func.isRequired,\n\tsetPaying: PropTypes.func.isRequired,\n\tsettings: PropTypes.object.isRequired,\n\torder: PropTypes.object.isRequired,\n\tsetDialogActions: PropTypes.func // Used when the component is used in a dialog in order to integrate the action into the dialog actions\n};\n","import PropTypes from 'prop-types';\nimport React, { useEffect, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { useOrderProcess } from '@karpeleslab/klb-react-services';\nimport { Grid } from '@material-ui/core';\nimport Button from '../../../../../core/input/Button';\nimport TextField from '@material-ui/core/TextField';\n\nconst OnFile = ({ order, settings, setPaying, refreshOrder, setDialogActions = null }) => {\n\tconst { t } = useTranslation();\n\tconst [selected, setSelected] = useState();\n\n\tconst [processOrder, processingOrder] = useOrderProcess(order.Order__);\n\n\tuseEffect(() => {\n\t\tsetPaying(processingOrder);\n\t}, [processingOrder]);\n\n\tuseEffect(() => {\n\t\tconst billings = settings.fields.user_billing.values;\n\t\tconst billingId = billings.length > 0 ? billings[0].User_Billing__ : null;\n\t\tsetSelected(billingId);\n\t}, [settings, setSelected]);\n\n\tconst handleProcess = () => {\n\t\tprocessOrder(settings.session, settings.method, { user_billing: selected }, { snackMessageToken: 'order_paid' })\n\t\t\t.then(d => refreshOrder(d.order));\n\t};\n\n\tuseEffect(() => {\n\t\tif (!setDialogActions) return;\n\t\tsetDialogActions((\n\t\t\t\n\t\t\t\t{t('onfile_checkout_btn')}\n\t\t\t \n\t\t));\n\t}, [setDialogActions, processingOrder, selected]);\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t setSelected(e.target.value)}\n\t\t\t\t\tdisabled={processingOrder}\n\t\t\t\t\tSelectProps={{\n\t\t\t\t\t\tnative: true\n\t\t\t\t\t}}\n\t\t\t\t\tinputProps={{\n\t\t\t\t\t\tid: 'billing-select'\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t \n\t\t\t\t\t{settings.fields.user_billing.values.map(billing => (\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t{t('user_billing_selector_value', {\n\t\t\t\t\t\t\t\tname: billing.Methods[0].Name,\n\t\t\t\t\t\t\t\texp: billing.Methods[0].Expiration\n\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t \n\t\t\t\t\t))}\n\t\t\t\t \n\t\t\t \n\t\t\t{!setDialogActions && \n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t{t('onfile_checkout_btn')}\n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t \n\t\t\t \n\t\t\t}\n\t\t \n\t);\n};\n\nexport default OnFile;\n\nOnFile.propTypes = {\n\trefreshOrder: PropTypes.func.isRequired,\n\tsetPaying: PropTypes.func.isRequired,\n\tsettings: PropTypes.object.isRequired,\n\torder: PropTypes.object.isRequired,\n\tsetDialogActions: PropTypes.func // Used when the component is used in a dialog in order to integrate the action into the dialog actions\n};\n","import PropTypes from 'prop-types';\nimport React, { useEffect } from 'react';\nimport { useOrderProcess } from '@karpeleslab/klb-react-services';\nimport { Grid } from '@material-ui/core';\nimport { useTranslation } from 'react-i18next';\nimport Alert from '@material-ui/lab/Alert';\nimport Button from '../../../../../core/input/Button';\n\nconst Wallet = ({ order, settings, setPaying, refreshOrder, setDialogActions = null }) => {\n\tconst { t } = useTranslation();\n\n\tconst [processOrder, processingOrder] = useOrderProcess(order.Order__);\n\n\tuseEffect(() => {\n\t\tsetPaying(processingOrder);\n\t}, [processingOrder]);\n\n\tconst handleProcess = () => {\n\t\tprocessOrder(settings.session, settings.method, {}, { snackMessageToken: 'order_paid' })\n\t\t\t.then(d => refreshOrder(d.order));\n\t};\n\n\tuseEffect(() => {\n\t\tif (!setDialogActions) return;\n\n\t\tsetDialogActions((\n\t\t\t\n\t\t\t\t{t('wallet_checkout_btn')}\n\t\t\t \n\t\t));\n\t}, [setDialogActions, processingOrder]);\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{t('wallet_balance', { balance: settings.fields.Wallet.Balance.display })}\n\t\t\t\t \n\t\t\t \n\t\t\t{!setDialogActions && \n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t{t('wallet_checkout_btn')}\n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t \n\t\t\t \n\t\t\t}\n\t\t \n\t);\n};\n\nexport default Wallet;\n\nWallet.propTypes = {\n\trefreshOrder: PropTypes.func.isRequired,\n\tsetPaying: PropTypes.func.isRequired,\n\tsettings: PropTypes.object.isRequired,\n\torder: PropTypes.object.isRequired,\n\tsetDialogActions: PropTypes.func // Used when the component is used in a dialog in order to integrate the action into the dialog actions\n};\n","import React, {useEffect,} from 'react';\nimport {PaymentElement, useElements, useStripe} from '@stripe/react-stripe-js';\nimport PropTypes from 'prop-types';\n\n\nexport default function StripeIntent({setStripe, setStripeElements, onChange}) {\n\tconst stripe = useStripe();\n\tconst stripeElements = useElements();\n\n\tuseEffect(() => {\n\t\tsetStripe(stripe);\n\t\tsetStripeElements(stripeElements);\n\t}, [setStripe, setStripeElements, stripe, stripeElements]);\n\n\tconst paymentElementOptions = {\n\t\tlayout: 'tabs'\n\t};\n\n\treturn (\n\t\t\n\t);\n}\n\nStripeIntent.propTypes = {\n\tonChange: PropTypes.func.isRequired,\n\tsetStripe: PropTypes.func.isRequired,\n\tsetStripeElements: PropTypes.func.isRequired,\n};\n","import PropTypes from 'prop-types';\nimport React, {useEffect, useState} from 'react';\nimport {loadStripe} from '@stripe/stripe-js';\nimport {Elements} from '@stripe/react-stripe-js';\nimport Loader from '../../../layout/Loader/Loader';\nimport {rest} from '@karpeleslab/klbfw';\nimport StripeIntent from './StripeIntent';\n\nlet stripePromise = null;\nconst initStripe = (token, account_id = undefined) => {\n\n\tif (!stripePromise) {\n\t\tconst options = account_id ? {stripeAccount: account_id} : undefined;\n\t\tstripePromise = loadStripe(token, options);\n\t}\n\treturn stripePromise;\n};\n\nconst Stripe = ({setStripe, setStripeElements, onChange, settings = null, setIntent = null}) => {\n\tconst [stripePromise, setStripePromise] = useState(null);\n\tconst [paymentInfo, setPaymentInfo] = useState(settings);\n\tconst [clientSecret, setClientSecret] = useState('');\n\n\tuseEffect(() => {\n\t\tif (settings) return;\n\n\t\tPromise.all([\n\t\t\trest('Realm/PaymentMethod:setup', 'POST', {method: 'stripe'}),\n\t\t\trest('Order/Payment:methodInfo', 'GET', {method: 'stripe'})\n\t\t]).then(d => {\n\t\t\tconst intentResult = d[0].data;\n\t\t\tconst infoResult = d[1].data;\n\t\t\tif (setIntent) {\n\t\t\t\tsetIntent(intentResult.Setup);\n\t\t\t}\n\t\t\tsetPaymentInfo({\n\t\t\t\tstripe_intent: {attributes: {client_secret: intentResult.Setup.client_secret}},\n\t\t\t\tcc_token: infoResult.Fields.cc_token\n\t\t\t});\n\t\t});\n\t}, [setPaymentInfo, settings, setIntent]);\n\n\tuseEffect(() => {\n\t\tif (!paymentInfo) return;\n\t\tsetClientSecret(paymentInfo.stripe_intent.attributes.client_secret);\n\t\tsetStripePromise(initStripe(paymentInfo.cc_token.attributes.key, paymentInfo.cc_token.attributes.options.stripe_account));\n\t}, [paymentInfo, setStripePromise]);\n\n\tif (!stripePromise || !clientSecret) return ;\n\n\tconst appearance = {\n\t\ttheme: 'stripe',\n\t};\n\n\tconst options = {\n\t\tclientSecret,\n\t\tappearance,\n\t};\n\n\treturn (\n\t\t\n\t\t\t\n\t\t \n\t);\n};\n\nexport default Stripe;\nStripe.propTypes = {\n\tsettings: PropTypes.object,\n\tsetIntent: PropTypes.func,\n\tonChange: PropTypes.func.isRequired,\n\tsetStripe: PropTypes.func.isRequired,\n\tsetStripeElements: PropTypes.func.isRequired,\n\tspacing: PropTypes.number\n};\n","import PropTypes from 'prop-types';\nimport React, { useEffect, useState } from 'react';\nimport { useOrderProcess } from '@karpeleslab/klb-react-services';\nimport { useTranslation } from 'react-i18next';\nimport { Grid } from '@material-ui/core';\nimport Alert from '@material-ui/lab/Alert';\nimport Button from '../../../../../core/input/Button';\nimport StripeForm from '../../../../../core/input/Stripe/Stripe';\nimport {getOrderViewRoute} \t\t\t from '../../../../../RouteController/Factory';\n\nconst Stripe = ({ order, settings, setPaying, refreshOrder, setDialogActions = null }) => {\n\tconst { t } = useTranslation();\n\n\tconst [processingOrder, setProcessingOrder] = useState(false);\n\tconst [processOrder] = useOrderProcess(order.Order__);\n\n\tconst [stripe, setStripe] = useState(null);\n\tconst [stripeElements, setStripeElements] = useState(null);\n\tconst [stripeError, setStripeError] = useState(null);\n\tconst [saveEnabled, setSaveEnabled] = useState(false);\n\n\n\tuseEffect(() => {\n\t\tif (!stripe) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst clientSecret = new URLSearchParams(window.location.search).get('payment_intent_client_secret');\n\n\t\tif (!clientSecret) {\n\t\t\treturn;\n\t\t}\n\n\t\tstripe.retrievePaymentIntent(clientSecret).then(({paymentIntent}) => {\n\t\t\tswitch (paymentIntent.status) {\n\t\t\t\tcase 'succeeded':\n\t\t\t\t\tprocessOrder(settings.session, settings.method, {stripe_intent: 1})\n\t\t\t\t\t\t.then(d => {\n\t\t\t\t\t\t\tsetProcessingOrder(false);\n\t\t\t\t\t\t\trefreshOrder(d.order);\n\t\t\t\t\t\t});\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'processing':\n\t\t\t\t\tsetStripeError(t('payment_processing'));\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'requires_payment_method':\n\t\t\t\t\tsetStripeError(t('requires_payment_method'));\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tsetStripeError(t('unexpected_error'));\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t});\n\t\t// eslint-disable-next-line\n\t}, [stripe, setStripeError, processOrder, setProcessingOrder]);\n\n\n\n\tuseEffect(() => {\n\t\tsetPaying(processingOrder);\n\t}, [processingOrder]);\n\n\tconst onStripeChange = e => {\n\t\tsetSaveEnabled(e.complete === true);\n\t};\n\n\tconst handleProcess = async () => {\n\t\tif (!stripe || !stripeElements)\n\t\t\treturn; // stripe not loaded yet\n\n\t\tsetProcessingOrder(true);\n\n\t\tconst result = await stripe.confirmPayment({\n\t\t\telements: stripeElements,\n\t\t\tredirect: 'if_required',\n\t\t\tconfirmParams: {\n\t\t\t\t//setup_future_usage: ccRemember ? 'off_session' : undefined,\n\t\t\t\tpayment_method_data: {\n\t\t\t\t\tbilling_details: {\n\t\t\t\t\t\tname: `${order.Billing_User_Location.First_Name} ${order.Billing_User_Location.Last_Name}`,\n\t\t\t\t\t\temail: order.User.Email,\n\t\t\t\t\t\taddress: {\n\t\t\t\t\t\t\tcountry: order.Billing_User_Location.Country__,\n\t\t\t\t\t\t\tpostal_code: order.Billing_User_Location.Zip,\n\t\t\t\t\t\t\tstate: order.Billing_User_Location.Province ? order.Billing_User_Location.Province : '',\n\t\t\t\t\t\t\tcity: order.Billing_User_Location.City ? order.Billing_User_Location.City : '',\n\t\t\t\t\t\t\tline1: order.Billing_User_Location.Address ? order.Billing_User_Location.Address : '',\n\t\t\t\t\t\t\tline2: order.Billing_User_Location.Address2 ? order.Billing_User_Location.Address2 : '',\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}, // Make sure to change this to your payment completion page\n\t\t\t\treturn_url: `https://${window.location.host}${getOrderViewRoute(order.Order__)}`,\n\t\t\t},\n\t\t});\n\n\t\tif (result.error) {\n\t\t\tif (result.error.type === 'card_error' || result.error.type === 'validation_error') {\n\t\t\t\tsetStripeError(result.error.message);\n\t\t\t} else {\n\t\t\t\tsetStripeError(t('unexpected_error'));\n\t\t\t}\n\n\t\t\tsetProcessingOrder(false);\n\t\t\treturn;\n\t\t}\n\n\t\tprocessOrder(settings.session, settings.method, {stripe_intent: 1})\n\t\t\t.then(d => {\n\t\t\t\tsetProcessingOrder(false);\n\t\t\t\trefreshOrder(d.order);\n\t\t\t}).finally(() => {\n\t\t\t\tsetProcessingOrder(false);\n\t\t\t});\n\t};\n\n\tuseEffect(() => {\n\t\tif (!setDialogActions) return;\n\t\tsetDialogActions((\n\t\t\t\n\t\t\t\t{t('purchase_btn')}\n\t\t\t \n\t\t));\n\n\t}, [setDialogActions, processingOrder, stripe, stripeElements, saveEnabled]);\n\n\treturn (\n\t\t\n\t\t\t{stripeError && \n\t\t\t\t\n\t\t\t\t\t{stripeError}\n\t\t\t\t \n\t\t\t \n\t\t\t}\n\n\t\t\t\n\t\t\t\t \n\t\t\t \n\n\t\t\t{!setDialogActions && \n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t{t('purchase_btn')}\n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t \n\t\t\t \n\t\t\t}\n\t\t \n\t);\n};\n\nexport default Stripe;\n\nStripe.propTypes = {\n\trefreshOrder: PropTypes.func.isRequired,\n\tsetPaying: PropTypes.func.isRequired,\n\tsettings: PropTypes.object.isRequired,\n\torder: PropTypes.object.isRequired,\n\tsetDialogActions: PropTypes.func // Used when the component is used in a dialog in order to integrate the action into the dialog actions\n};\n","import PropTypes from 'prop-types';\nimport React, { useEffect } from 'react';\nimport { FUNDING, PayPalButtons, usePayPalScriptReducer } from '@paypal/react-paypal-js';\nimport CircularProgress from '@material-ui/core/CircularProgress';\nimport { useTranslation } from 'react-i18next';\n\nconst Buttons = ({ order, onApproved, onError = undefined, disabled = false, onCancel = undefined, onLoadFailed, fundingSource = FUNDING.PAYPAL }) => {\n\tconst { t } = useTranslation();\n\n\tconst [{ isPending, isRejected }] = usePayPalScriptReducer();\n\n\n\tuseEffect(() => {\n\t\tif (!isRejected) return;\n\t\tonLoadFailed();\n\t}, [isRejected]);\n\n\tif (isPending) return ;\n\tif (isRejected) return t('paypal_load_failed_label');\n\n\treturn (\n\t\t actions.order.create(order) : undefined}\n\t\t\tonApprove={(data) => {\n\t\t\t\tonApproved(data);\n\t\t\t\t//return actions.order.capture().then(onComplete);\n\t\t\t}}\n\t\t\tonCancel={onCancel}\n\t\t\tonError={onError}\n\t\t/>\n\t);\n};\n\nexport default Buttons;\n\nButtons.propTypes = {\n\tdisabled: PropTypes.bool,\n\tfundingSource: PropTypes.oneOf([Object.values(FUNDING)]),\n\tonCancel: PropTypes.func,\n\tonApproved: PropTypes.func.isRequired,\n\tonError: PropTypes.func,\n\tonLoadFailed: PropTypes.func,\n\torder: PropTypes.object.isRequired\n};\n","import React, { useCallback } from 'react';\nimport { FUNDING, PayPalScriptProvider } from '@paypal/react-paypal-js';\nimport Buttons from './Buttons';\nimport PropTypes from 'prop-types';\nimport { useSetSnackbar } from '../../../../hooks/useSnackbar';\nimport { useTranslation } from 'react-i18next';\n\nconst Paypal = ({ clientId, order, onApproved, style = {}, disabled = false, onOrderCanceled = undefined, fundingSource = FUNDING.PAYPAL }) => {\n\tconst { t } = useTranslation();\n\tconst setSnackbar = useSetSnackbar();\n\n\tconst handleLoadFailed = useCallback(() => {\n\t\tsetSnackbar(t('paypal_load_failed_alert'), 'error');\n\t}, []);\n\n\tconst handlePaymentCanceled = useCallback(() => {\n\t\tif (onOrderCanceled) onOrderCanceled();\n\t}, []);\n\n\tconst handlePaymentError = useCallback(() => {\n\t\tsetSnackbar(t('paypal_error_alert'), 'error');\n\t\tif (onOrderCanceled) onOrderCanceled();\n\t}, []);\n\n\treturn (\n\t\t\n\t\t\t \n\t\t \n\t);\n};\n\nexport default Paypal;\n\nPaypal.propTypes = {\n\tclientId: PropTypes.string.isRequired,\n\tdisabled: PropTypes.bool,\n\tfundingSource: PropTypes.oneOf([Object.values(FUNDING)]),\n\tonApproved: PropTypes.func.isRequired,\n\tonOrderCanceled: PropTypes.func,\n\torder: PropTypes.object.isRequired,\n\tstyle: PropTypes.object\n};\n","import React, { useCallback, useEffect } from 'react';\nimport PropTypes from 'prop-types';\nimport PaypalPayment from '../../../../../core/input/Paypal/Paypal';\nimport Grid from '@material-ui/core/Grid';\nimport RichAlertTrans from '../../../../../core/feedback/RichAlertTrans';\nimport { useOrderProcess } from '@karpeleslab/klb-react-services';\nimport Button from '../../../../../core/input/Button';\nimport { useTranslation } from 'react-i18next';\n\nconst Paypal = ({ order, setPaying, settings, refreshOrder, setDialogActions = null }) => {\n\tconst { t } = useTranslation();\n\n\tconst [processOrder, processing] = useOrderProcess(order.Order__);\n\n\tconst handleComplete = useCallback((data) => {\n\t\tprocessOrder(\n\t\t\tsettings.session,\n\t\t\tsettings.method,\n\t\t\t{ order_id: data.orderID }\n\t\t\t, { snackMessageToken: 'order_paid', handleError: false })\n\t\t\t.then(d => refreshOrder(d.order));\n\t}, []);\n\n\tuseEffect(() => {\n\t\tsetPaying(processing);\n\t}, [setPaying, processing]);\n\n\tuseEffect(() => {\n\t\tif (!setDialogActions) return;\n\t\tif (processing) {\n\t\t\tsetDialogActions(\n\t\t\t\t\n\t\t\t\t\t{t('processing_order_btn')}\n\t\t\t\t \n\t\t\t);\n\t\t} else {\n\t\t\tsetDialogActions(\n\t\t\t\t );\n\t\t}\n\n\t}, [setDialogActions, processing]);\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t \n\t\t\t \n\t\t\t{(!setDialogActions && !processing) && \n\t\t\t\t \n\t\t\t \n\t\t\t}\n\t\t\t{(!setDialogActions && processing) && \n\t\t\t\t\n\t\t\t\t\t{t('processing_order_btn')}\n\t\t\t\t \n\t\t\t \n\t\t\t}\n\t\t \n\t);\n};\n\nexport default Paypal;\n\nPaypal.propTypes = {\n\torder: PropTypes.object.isRequired,\n\trefreshOrder: PropTypes.func.isRequired,\n\tsetDialogActions: PropTypes.func,\n\tsetPaying: PropTypes.func.isRequired,\n\tsettings: PropTypes.object.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React, { useEffect, useState } from 'react';\nimport Panel from '../../../../layout/Container/tab/Panel';\nimport Bitpay from './Methods/Bitpay';\nimport Free from './Methods/Free';\nimport OnFile from './Methods/OnFile';\nimport Wallet from './Methods/Wallet';\nimport Stripe from './Methods/Stripe';\nimport Paypal from './Methods/Paypal';\n\nconst PaymentMethodContent = ({ order, selectedPaymentMethod, method, methodData, setPaying, refreshOrder, setDialogActions = null }) => {\n\tconst [component, setComponent] = useState(null);\n\n\tuseEffect(() => {\n\t\tswitch (method) {\n\t\t\tcase 'Bitpay':\n\t\t\t\tsetComponent(\n\t\t\t\t\t );\n\t\t\t\tbreak;\n\t\t\tcase 'Free':\n\t\t\t\tsetComponent(\n\t\t\t\t\t \n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase 'OnFile':\n\t\t\t\tsetComponent(\n\t\t\t\t\t \n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase 'Wallet':\n\t\t\t\tsetComponent(\n\t\t\t\t\t );\n\t\t\t\tbreak;\n\t\t\tcase 'Stripe':\n\t\t\t\tsetComponent(\n\t\t\t\t\t \n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase 'Paypal':\n\t\t\t\tsetComponent(\n\t\t\t\t\t \n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\treturn <>>;\n\t\t}\n\n\t}, [setComponent, methodData]);\n\n\tif (!component) return <>>;\n\n\treturn (\n\t\t\n\t\t\t{component}\n\t\t \n\t);\n};\n\nexport default PaymentMethodContent;\n\nPaymentMethodContent.propTypes = {\n\tmethod: PropTypes.string.isRequired,\n\tmethodData: PropTypes.object.isRequired,\n\torder: PropTypes.object.isRequired,\n\tselectedPaymentMethod: PropTypes.string.isRequired,\n\tsetPaying: PropTypes.func.isRequired,\n\trefreshOrder: PropTypes.func.isRequired,\n\tsetDialogActions: PropTypes.func // Used when the component is used in a dialog in order to integrate the action into the dialog actions\n};\n","import PropTypes from 'prop-types';\nimport React, { useEffect, useState } from 'react';\nimport { Grid } from '@material-ui/core';\nimport { Title } from '../../../../core/typography/Title';\nimport { useTranslation } from 'react-i18next';\nimport { useOrderProcess } from '@karpeleslab/klb-react-services';\nimport Loader from '../../../../layout/Loader/Loader';\nimport Tabs from '@material-ui/core/Tabs';\nimport useMediaQuery from '@material-ui/core/useMediaQuery';\nimport PaymentMethodTab from './PaymentMethodTab';\nimport PaymentMethodContent from './PaymentMethodContent';\n\nconst OrderPayments = ({ order, refresh, setDialogActions = null }) => {\n\tconst { t } = useTranslation();\n\tconst [processOrder, processingOrder] = useOrderProcess(order.Order__);\n\tconst [processResult, setProcessResult] = useState(null);\n\n\tconst [paying, setPaying] = useState(false);\n\n\tconst [paymentMethod, setPaymentMethod] = useState();\n\n\tconst isMobile = useMediaQuery(theme => theme.breakpoints.down('xs'));\n\n\tconst handleTabChange = (event, newValue) => {\n\t\tsetPaymentMethod(newValue);\n\t};\n\n\tuseEffect(() => {\n\t\tprocessOrder().then(setProcessResult);\n\t}, [processOrder, setProcessResult]);\n\n\n\tuseEffect(() => {\n\t\tif (paymentMethod || !processResult) return;\n\n\t\tconst clientSecret = new URLSearchParams(window.location.search).get('payment_intent_client_secret');\n\n\t\tif (clientSecret) {\n\t\t\t// If we are redirected to the order page from stripe, select the stripe payment method;\n\t\t\tsetPaymentMethod('Stripe');\n\t\t\treturn;\n\t\t}\n\n\t\t// Select default payment method\n\t\tif (processResult.methods_order.includes('OnFile')) {\n\t\t\tsetPaymentMethod('OnFile');\n\t\t} else {\n\t\t\tsetPaymentMethod(processResult.methods_order[0]);\n\t\t}\n\t}, [processResult, setPaymentMethod]);\n\n\tif (processingOrder || !processResult) {\n\t\treturn (\n\t\t\t\n\t\t\t\t \n\t\t\t \n\t\t);\n\t}\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{t('order_payment_methods')}\n\t\t\t\t \n\t\t\t \n\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{processResult.methods_order.map(method => )}\n\t\t\t\t \n\t\t\t \n\n\t\t\t\n\t\t\t\t{processResult.methods_order.map(method => )}\n\t\t\t \n\t\t \n\t);\n};\n\nexport default OrderPayments;\n\nOrderPayments.propTypes = {\n\torder: PropTypes.object.isRequired,\n\trefresh: PropTypes.func.isRequired,\n\tsetDialogActions: PropTypes.func // Used when the component is used in a dialog in order to integrate the action into the dialog actions\n};\n","import { useCallback, useEffect, useRef, useState } from 'react';\n\nconst MIN_REFRESH_INTERVAL = 30 * 1000; // minimum 30 seconds between refresh;\nconst BACKGROUND_INTERVAL_REFRESH = 60 * 1000 * 30; // Background refresh every 30 minutes;\n\nexport const useAutoRefresher = (refresh, backGroundRefresh = BACKGROUND_INTERVAL_REFRESH) => {\n\tconst timeoutId = useRef(null);\n\tconst lastRefresh = useRef(0);\n\tconst [backGroundRefreshInterval] = useState(backGroundRefresh < MIN_REFRESH_INTERVAL? MIN_REFRESH_INTERVAL : backGroundRefresh);\n\n\tconst clear = useCallback(() => {\n\t\tclearTimeout(timeoutId.current);\n\t}, []);\n\n\tconst executeRefresh = useCallback(() => {\n\t\tif (Date.now() - lastRefresh.current < MIN_REFRESH_INTERVAL) return false;\n\t\tlastRefresh.current = Date.now();\n\t\trefresh();\n\t\treturn true;\n\t}, [refresh]);\n\n\n\tconst restart = useCallback(() => {\n\t\tif (timeoutId.current) clear();\n\t\ttimeoutId.current = setTimeout(() => {\n\t\t\texecuteRefresh();\n\t\t\trestart(); // Timer as reached the end, restart it.\n\t\t}, backGroundRefreshInterval);\n\t}, [executeRefresh]);\n\n\tconst onFocus = useCallback(() => {\n\t\tif (document.visibilityState === 'hidden') return;\n\t\t// Only restart the timer if the refresh has been done to reset it to BACKGROUND_INTERVAL_REFRESH\n\t\tif (executeRefresh())\n\t\t\trestart();\n\t}, [executeRefresh, restart]);\n\n\tuseEffect(() => {\n\t\trestart();\n\n\t\treturn () => {\n\t\t\tif (timeoutId.current) clear();\n\t\t};\n\t}, [restart, clear]);\n\n\tuseEffect(() => {\n\t\tif (typeof document === 'undefined') return;\n\n\t\tdocument.removeEventListener('visibilitychange', onFocus);\n\t\tdocument.removeEventListener('focus', onFocus);\n\n\t\tdocument.addEventListener('visibilitychange', onFocus);\n\t\tdocument.addEventListener('focus', onFocus);\n\t\treturn () => {\n\t\t\tdocument.removeEventListener('visibilitychange', onFocus);\n\t\t\tdocument.removeEventListener('focus', onFocus);\n\t\t};\n\t}, [onFocus]);\n};\n","import PropTypes from 'prop-types';\nimport React, { useCallback } from 'react';\nimport RichAlertTrans from '../../../core/feedback/RichAlertTrans';\nimport { useAutoRefresher } from '../../../../hooks/useAutoRefresher';\nimport { useSetSnackbar } from '../../../../hooks/useSnackbar';\nimport { useTranslation } from 'react-i18next';\n\nconst OrderProcessingAlert = ({ refresh }) => {\n\tconst setSnackbar = useSetSnackbar();\n\tconst { t } = useTranslation();\n\n\tconst refresher = useCallback(() => {\n\t\trefresh().then(o => {\n\t\t\tif (o.data.Status !== 'completed') return;\n\t\t\tsetSnackbar(t('order_completed_success'), 'success');\n\t\t});\n\t}, []);\n\n\tuseAutoRefresher(refresher, 60 * 1000);\n\n\treturn (\n\t\t \n\t);\n};\n\nexport default OrderProcessingAlert;\n\nOrderProcessingAlert.propTypes = {\n\trefresh: PropTypes.func.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React, { useCallback, useEffect } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Grid } from '@material-ui/core';\nimport { Title } from '../../../core/typography/Title';\nimport OrderTable from './OrderTable';\nimport OrderPayments from './Payments/OrderPayments';\nimport OrderProcessingAlert from './OrderProcessingAlert';\nimport RichAlertTrans from '../../../core/feedback/RichAlertTrans';\n\nconst OrderWithPayment = ({ order, refresh, onComplete, setDialogActions = null }) => {\n\tconst { t } = useTranslation();\n\n\tconst detectComplete = useCallback(newOrder => {\n\t\tif (order.Status !== newOrder.Status &&\n\t\t\tnewOrder.Status === 'completed' &&\n\t\t\tonComplete) {\n\t\t\tonComplete(newOrder);\n\t\t}\n\n\t\trefresh(newOrder);\n\t}, [order]);\n\n\tuseEffect(() => {\n\t\t// This will remove the pay action button once the order is paid\n\t\tif (!order.Paid || !setDialogActions) return;\n\t\tsetDialogActions(null);\n\t}, [order, setDialogActions]);\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{t('order_details')}\n\t\t\t\t \n\t\t\t \n\n\t\t\t{(order.Paid && order.Status !== 'completed') &&\n\t\t\t\n\t\t\t\t\n\t\t\t \n\t\t\t}\n\n\t\t\t{(order.Status === 'completed') &&\n\t\t\t\n\t\t\t\t \n\t\t\t \n\t\t\t}\n\n\t\t\t\n\t\t\t\t\n\t\t\t \n\n\t\t\t{(!order.Paid && order.Status !== 'completed') &&\n\t\t\t\n\t\t\t\t\n\t\t\t \n\t\t\t}\n\t\t \n\t);\n};\n\nexport default OrderWithPayment;\n\nOrderWithPayment.propTypes = {\n\torder: PropTypes.object.isRequired,\n\trefresh: PropTypes.func.isRequired,\n\tonComplete: PropTypes.func,\n\tsetDialogActions: PropTypes.func // Used when the component is used in a dialog in order to integrate the action into the dialog actions\n};\n","import React from 'react';\nimport { Grid } from '@material-ui/core';\nimport Toolbar from '../../components/core/typography/Toolbar';\nimport PageContainer from '../../components/layout/Container/PageContainer';\nimport { useTranslation } from 'react-i18next';\nimport { useParams } from 'react-router';\nimport PageLoader from '../../components/layout/Loader/PageLoader';\nimport OrderInfo from '../../components/common/Order/order/OrderInfo';\nimport OrderPaymentInfo from '../../components/common/Order/order/OrderPaymentInfo';\nimport UserLocation from '../../components/common/User/Location/UserLocation';\nimport PageNotFound from '../System/PageNotFound';\nimport { useOrder } from '@karpeleslab/klb-react-services';\nimport { getBillingRoute } from '../../components/RouteController/Factory';\nimport OrderWithPayment from '../../components/common/Order/order/OrderWithPayment';\n\n\nconst ViewOrder = () => {\n\tconst { t } = useTranslation();\n\tconst { orderId } = useParams();\n\tconst [order, refresh] = useOrder(orderId);\n\n\tif (!order) return ;\n\tif (!order.data) return ;\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t \n\t\t\t\t \n\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t \n\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t \n\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t \n\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t \n\n\t\t\t\t\n\t\t\t\t\t \n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default ViewOrder;\n","import React from 'react';\nimport { Trans, useTranslation } from 'react-i18next';\nimport Empty from '../../../core/feedback/State/Empty';\nimport Graphic from '../../../../assets/img/shells_logo_vertical_white.svg';\nimport AddIcon from '@material-ui/icons/Add';\n\nconst EmptyList = () => {\n\tconst { t } = useTranslation();\n\n\treturn (\n\t\t\n\t\t\t\t\tsample \n\t\t\t\t\tsample \n\t\t\t\t\n\t\t\t}\n\t\t\tgraphic={Graphic}\n\t\t\taction={\n\t\t\t\t{\n\t\t\t\t\tcomponent: 'a',\n\t\t\t\t\ttitle: t('order_new_shell_btn'),\n\t\t\t\t\trel: 'noopener noreferrer',\n\t\t\t\t\tendIcon: ,\n\t\t\t\t\ttarget: '_blank',\n\t\t\t\t\thref: `${process.env.REACT_APP_SHELL_URL}/join`\n\t\t\t\t}\n\t\t\t}\n\t\t/>\n\t);\n};\n\nexport default EmptyList;\n","import { useContext, useEffect, useState } from 'react';\nimport { ModeContext } from '../context/ModeContext';\n\nexport const useIsMode = mode => {\n\tconst [modeContext] = useContext(ModeContext);\n\tconst [ok, setOk] = useState(modeContext === mode);\n\n\tuseEffect(() => {\n\t\tsetOk(modeContext === mode);\n\t}, [mode, modeContext, setOk]);\n\n\treturn ok;\n};\n","import PropTypes from 'prop-types';\nimport React from 'react';\nimport { useTranslation } from 'react-i18next';\nimport Tab from '@material-ui/core/Tab';\nimport Tabs from '@material-ui/core/Tabs';\nimport AlbumIcon from '@material-ui/icons/Album';\nimport SettingsIcon from '@material-ui/icons/Settings';\nimport ShareIcon from '@material-ui/icons/Share';\nimport { useIsMode } from '../../../../hooks/useIsMode';\nimport { ADVANCED_MODE } from '../../../../context/ModeContext';\n\nexport const OS_OFFICIAL = 'official';\nexport const OS_PRIVATE = 'private';\nexport const OS_SHARE = 'share';\n\nconst SourceTabs = ({ tab, setTab, setValue, disabled = false }) => {\n\tconst { t } = useTranslation();\n\tconst isAdvanced = useIsMode(ADVANCED_MODE);\n\n\tconst handleTabChange = (event, newValue) => {\n\t\tsetTab(newValue);\n\t\tsetValue(null);\n\t};\n\n\treturn (\n\t\t\n\t\t\t} value={OS_OFFICIAL} label={t('shell_os_tab_official')} disabled={disabled}/>\n\n\t\t\t{isAdvanced &&\n\t\t\t} value={OS_PRIVATE} label={t('shell_os_tab_my')} disabled={disabled}/>}\n\n\t\t\t{isAdvanced &&\n\t\t\t} value={OS_SHARE} label={t('shell_os_tab_share')} disabled={disabled}/>}\n\t\t \n\t);\n};\n\nexport default SourceTabs;\n\nSourceTabs.propTypes = {\n\tdisabled: PropTypes.bool,\n\tsetTab: PropTypes.func.isRequired,\n\tsetValue: PropTypes.func.isRequired,\n\ttab: PropTypes.any\n};\n","import { useCallback } from 'react';\nimport { rest } from '@karpeleslab/klbfw';\nimport { getShellOsEndpoint, useApiErrorHandler } from '@karpeleslab/klb-react-services';\n\nexport const ICON_VARIATION = 'strip&scale_crop=40x40&format=png';\n\nexport const useFetchOperatingSystem = () => {\n\tconst [catchRedirect] = useApiErrorHandler();\n\n\tconst fetch = useCallback(\n\t\t(osId, params) => {\n\t\t\treturn rest(getShellOsEndpoint(osId), 'GET', params)\n\t\t\t\t.then(catchRedirect)\n\t\t\t\t.then(d => d);\n\t\t}\n\t\t, []); //eslint-disable-line\n\n\treturn [fetch];\n};\n","export default __webpack_public_path__ + \"static/media/shells_icon_white.6ab594e5.svg\";","import PropTypes from 'prop-types';\nimport React from 'react';\nimport makeStyles from '@material-ui/core/styles/makeStyles';\n\nconst useStyles = makeStyles(() => ({\n\troot: {\n\t\tdisplay: '-webkit-box',\n\t\t'-webkit-line-clamp': props => props.row,\n\t\t'-webkit-box-orient': 'vertical',\n\t\toverflow: 'hidden',\n\t}\n}));\n\nconst Ellipsis = ({ children, row = 2 }) => {\n\tconst classes = useStyles({ row: row });\n\treturn (\n\t\t\n\t\t\t{children}\n\t\t
\n\t);\n};\n\nexport default Ellipsis;\n\nEllipsis.propTypes = {\n\tchildren: PropTypes.oneOfType([\n\t\tPropTypes.arrayOf(PropTypes.node),\n\t\tPropTypes.node\n\t]),\n\trow: PropTypes.number\n};\n","import makeStyles from '@material-ui/core/styles/makeStyles';\nimport { fade } from '@material-ui/core/styles/colorManipulator';\n\nexport const useStyles = makeStyles(theme => {\n\treturn {\n\t\troot: {\n\t\t\tposition: 'relative',\n\t\t\theight: '100%'\n\t\t},\n\t\tactionArea: {\n\t\t\theight: '100%'\n\t\t},\n\t\tmedia: {\n\t\t\tmargin: theme.spacing(2),\n\t\t\tmarginLeft: 'auto',\n\t\t\tmarginRight: 'auto'\n\t\t},\n\t\tmediaLoading: {\n\t\t\theight: '75px',\n\t\t\twidth: '75px',\n\t\t\tmargin: theme.spacing(0),\n\t\t\tmarginLeft: 'auto',\n\t\t\tmarginRight: 'auto'\n\t\t},\n\t\tselected: {\n\t\t\tborderColor: theme.palette.primary.light,\n\t\t\tbackgroundColor: fade(theme.palette.primary.light, 0.18),\n\t\t},\n\t\tselectedTitle: {\n\t\t\tfontWeight: 'bold',\n\t\t\tcolor: theme.palette.primary.dark,\n\t\t},\n\t\tdescription: {\n\t\t\tfontSize: '0.75rem'\n\t\t},\n\t\tcontent: {\n\t\t\tpaddingTop: theme.spacing(1),\n\t\t},\n\t\tdetailsBtb: {\n\t\t\tposition: 'absolute',\n\t\t\ttop: 0,\n\t\t\tright: 0,\n\t\t\tzIndex: 1,\n\t\t},\n\t\tribbon: {\n\t\t\tbackgroundColor: 'transparent',\n\t\t\tposition: 'absolute',\n\t\t\tcolor: theme.palette.secondary.light,\n\t\t\tborder: `1px solid ${theme.palette.secondary.light}`,\n\t\t\twidth: 150,\n\t\t\tzIndex: 3,\n\t\t\ttextAlign: 'center',\n\t\t\ttextTransform: 'uppercase',\n\t\t\tpadding: 5,\n\t\t\t[theme.breakpoints.down('sm')]: {\n\t\t\t\tpadding: 2,\n\t\t\t},\n\t\t\t'&::before': {\n\t\t\t\tposition: 'absolute',\n\t\t\t\tzIndex: -1,\n\t\t\t\tcontent: '',\n\t\t\t\tdisplay: 'block',\n\t\t\t\tborder: `5px solid ${theme.palette.secondary.light}`,\n\t\t\t},\n\t\t\t'&::after': {\n\t\t\t\tposition: 'absolute',\n\t\t\t\tzIndex: -1,\n\t\t\t\tcontent: '',\n\t\t\t\tdisplay: 'block',\n\t\t\t\tborder: `5px solid ${theme.palette.secondary.dark}`,\n\t\t\t},\n\t\t\ttransform: 'rotate(-45deg)',\n\t\t\ttop: theme.spacing(2),\n\t\t\tmarginLeft: -40,\n\t\t},\n\t};\n});\n","import { useCallback, useState } from 'react';\nimport { rest } from '@karpeleslab/klbfw';\nimport { getShellLicenseEndpoint, useApiErrorHandler } from '@karpeleslab/klb-react-services';\n\nexport const useShellHasLicense = (shellId) => {\n\tconst [catchRedirect] = useApiErrorHandler();\n\tconst [loading, setLoading] = useState(true);\n\n\tconst fetch = useCallback(\n\t\t(licenseKey) => {\n\t\t\tsetLoading(true);\n\t\t\treturn rest(getShellLicenseEndpoint(licenseKey, shellId))\n\t\t\t\t.then(catchRedirect)\n\t\t\t\t.then(d => {\n\t\t\t\t\treturn !!d.data;\n\t\t\t\t})\n\t\t\t\t.catch(() => {\n\t\t\t\t\treturn false;\n\t\t\t\t})\n\t\t\t\t.finally(() => {\n\t\t\t\t\tsetLoading(false);\n\t\t\t\t});\n\t\t}\n\t\t, [shellId]); //eslint-disable-line\n\n\treturn [fetch, loading];\n};\n","import PropTypes from 'prop-types';\nimport React, { useEffect, useState } from 'react';\nimport { Skeleton } from '@material-ui/lab';\nimport { useShellHasLicense } from '../../../../hooks/useShellLicense';\nimport { Trans } from 'react-i18next';\nimport { Typography } from '@material-ui/core';\nimport RichAlert from '../../../core/feedback/RichAlert';\n\nconst OsItemLicense = ({ shell, os, detailed = false }) => {\n\tconst [hasLicense, setHasLicense] = useState(false);\n\tconst [fetch, loading] = useShellHasLicense(shell.Shell__);\n\n\tuseEffect(() => {\n\t\tfetch(os.Catalog_Product['Shell.LicenseType']).then(setHasLicense);\n\t}, [os]);\n\n\n\tif (loading) return ;\n\tif (hasLicense) return <>>;\n\n\tif (!detailed) {\n\t\treturn \n\t\t\t\n\t\t\t\tA X license is required\n\t\t\t \n\t\t ;\n\t}\n\n\treturn \n\t\t\n\t\t\tA X license is required\n\t\t \n\t ;\n};\n\nexport default OsItemLicense;\n\nOsItemLicense.propTypes = {\n\tdetailed: PropTypes.bool,\n\tos: PropTypes.object.isRequired,\n\tshell: PropTypes.object.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React, { useEffect, useState } from 'react';\nimport makeStyles from '@material-ui/core/styles/makeStyles';\n\nconst useStyles = makeStyles(() => ({\n\troot: {\n\t\tposition: 'relative',\n\t\ttextAlign: props => props.centered ? 'center' : 'inherit',\n\t\t'&::after': {\n\t\t\ttop: 0,\n\t\t\tdisplay: props => props.loaded ? 'none' : 'block',\n\t\t\tcontent: '\"\"',\n\t\t\tposition: 'absolute',\n\t\t\twidth: '100%',\n\t\t\theight: '100%',\n\t\t\ttransform: 'translateX(-100%)',\n\t\t\t//background: '-webkit-gradient(linear, left top, right top, from(transparent), color-stop(rgba(255, 255, 255, 0.2)), to(transparent))',\n\t\t\t'background': 'linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent)',\n\t\t\t'animation': '$loading 0.8s infinite',\n\t\t}\n\t},\n\n\t/* Loading Animation */\n\t'@keyframes loading': {\n\t\t'100%': {\n\t\t\ttransform: 'translateX(100%)',\n\t\t}\n\t},\n\n\tplaceholder: {\n\t\t'-webkit-transition': 'opacity 0.2s ease-in-out',\n\t\t'-moz-transition': 'opacity 0.2s ease-in-out',\n\t\t'-o-transition': 'opacity 0.2s ease-in-out',\n\t\t'transition': 'opacity 0.2s ease-in-out',\n\t\tfilter: 'grayscale(0.7)',\n\t\t'opacity': props => props.loaded ? '0' : '1',\n\t},\n\n\tfinal: {\n\t\tleft: props => props.centered && !props.cleaned ? '50%' : '0',\n\t\ttransform: props => props.centered && !props.cleaned ? 'translate(-50%, 0%)' : 'unset',\n\t\tposition: 'absolute',\n\t\t'-webkit-transition': 'opacity 0.2s ease-in-out',\n\t\t'-moz-transition': 'opacity 0.2s ease-in-out',\n\t\t'-o-transition': 'opacity 0.2s ease-in-out',\n\t\t'transition': 'opacity 0.2s ease-in-out',\n\t\t'opacity': props => props.loaded ? '1' : '0',\n\t}\n}));\n\nconst Img = ({ loaderStyle = {}, rootStyle = {}, centered = false, ...rest }) => {\n\tconst [loading, setLoading] = useState(true);\n\t// Use the remove all reference to the loader image and lighten the dom\n\tconst [cleaned, setCleaned] = useState(false);\n\tconst classes = useStyles({ loaded: !loading, cleaned: cleaned, centered: centered });\n\tconst [cleanedStyle, setCleanedStyle] = useState({});\n\n\tuseEffect(() => {\n\t\tif (loading) return;\n\t\tconst t = setTimeout(() => {\n\t\t\tsetCleanedStyle({\n\t\t\t\tposition: 'inherit',\n\t\t\t\ttransform: 'unset',\n\t\t\t\tleft: 'unset',\n\t\t\t});\n\t\t\tsetCleaned(true);\n\t\t}, 1000);\n\t\treturn () => {\n\t\t\tclearTimeout(t);\n\t\t};\n\t}, [loading, setCleaned, setCleanedStyle]);\n\n\treturn (\n\t\t\n\t\t\t{!cleaned &&
}\n\n\t\t\t
setLoading(false)}\n\t\t\t/>\n\t\t
\n\t);\n};\n\nexport default Img;\n\nImg.propTypes = {\n\tloaderStyle: PropTypes.object,\n\trootStyle: PropTypes.object,\n\tstyle: PropTypes.any,\n\tcentered: PropTypes.bool\n};\n","import PropTypes from 'prop-types';\nimport React from 'react';\nimport { Typography } from '@material-ui/core';\nimport { useTranslation } from 'react-i18next';\nimport HelpOutlineIcon from '@material-ui/icons/HelpOutline';\nimport Tooltip from '@material-ui/core/Tooltip';\n\nconst OsItemShellKernel = ({ detailed = false }) => {\n\tconst { t } = useTranslation();\n\n\tif (detailed) {\n\t\treturn (\n\t\t\t\n\t\t\t\t{t('os_powered_by_shell_desc')}\n\t\t\t \n\t\t);\n\t}\n\treturn (\n\t\t\n\t\t\t{t('os_powered_by_shell_title')}\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t \n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default OsItemShellKernel;\n\nOsItemShellKernel.propTypes = {\n\tdetailed: PropTypes.bool\n};\n","import PropTypes from 'prop-types';\nimport React from 'react';\nimport Card from '@material-ui/core/Card';\nimport CardActionArea from '@material-ui/core/CardActionArea';\nimport { ICON_VARIATION } from '../../../../hooks/useOperatingSystems';\nimport defaultIcon from '../../../../assets/img/shells_icon_white.svg';\nimport { useTranslation } from 'react-i18next';\nimport CardContent from '@material-ui/core/CardContent';\nimport Typography from '@material-ui/core/Typography';\nimport Ellipsis from '../../../core/typography/Ellipsis';\nimport { Box, Grid } from '@material-ui/core';\nimport { Skeleton } from '@material-ui/lab';\nimport { useStyles } from './OSItem.style';\nimport IconButton from '@material-ui/core/IconButton';\nimport OsItemLicense from './OSItemLicense';\nimport InfoIcon from '@material-ui/icons/Info';\nimport Img from '../../../core/data/Image/Img';\nimport { isShellKernel } from '../../../../utils/misc';\nimport OsItemShellKernel from './OSItemShellKernel';\n\nconst OsItem = ({ shell, setSelected, setShowDetailsFor, selected = false, disabled = false, loading = true, os = null }) => {\n\tconst { t } = useTranslation();\n\tconst classes = useStyles();\n\n\tconst handleClick = () => {\n\t\tif (loading || selected) return;\n\t\tsetSelected(os);\n\t};\n\n\tconst handleDetailsClick = () => {\n\t\tsetShowDetailsFor(os);\n\t};\n\n\treturn (\n\t\t\n\t\t\t{(!loading && os.Beta === 'Y') &&\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{t('shell_os_beta_mark')}\n\t\t\t\t \n\t\t\t
\n\t\t\t}\n\t\t\t\n\t\t\t\t{(!loading && (!!os.Description || !!os.Short_Description)) &&\n\t\t\t\t\n\t\t\t\t\t \n\t\t\t\t \n\t\t\t\t}\n\t\t\t
\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t{!loading && \n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t{loading && }\n\t\t\t\t\t\t \n\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t{!loading &&\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t{os.Name}\n\t\t\t\t\t\t\t }\n\t\t\t\t\t\t\t{loading && }\n\t\t\t\t\t\t \n\t\t\t\t\t\t\n\t\t\t\t\t\t\t{loading && }\n\t\t\t\t\t\t\t{!loading && \n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t{os.Short_Description}\n\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t \n\t\t\t\t\t\t{((!loading && (os.Catalog_Product__ || isShellKernel(os)))) &&\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t{os.Catalog_Product__ && }\n\t\t\t\t\t\t\t\t{isShellKernel(os) && }\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t\t}\n\t\t\t\t\t \n\n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default OsItem;\n\nOsItem.propTypes = {\n\tdisabled: PropTypes.bool,\n\tloading: PropTypes.bool,\n\tos: PropTypes.object,\n\tselected: PropTypes.bool,\n\tsetSelected: PropTypes.func.isRequired,\n\tsetShowDetailsFor: PropTypes.func.isRequired,\n\tshell: PropTypes.object.isRequired\n};\n","import React from 'react';\nimport { useTranslation } from 'react-i18next';\nimport TextField from '@material-ui/core/TextField';\nimport PropTypes from 'prop-types';\n\nexport const SHELL_OS_PURPOSE_LIST = [\n\t'desktop',\n\t'server',\n\t'mobile',\n\t'unknown'\n];\n\nexport const SHELL_OS_PURPOSE_LITE_LIST = [\n\t'desktop',\n];\n\nconst OSPurposeSelector = ({ value, setValue, disabled = false, required = false, hideAll = false, list = SHELL_OS_PURPOSE_LIST, ...rest }) => {\n\tconst { t } = useTranslation();\n\n\treturn (\n\t\t setValue(e.target.value === 'all' ? null : e.target.value)}\n\t\t\tselect\n\t\t\tfullWidth\n\t\t\tdisabled={disabled}\n\t\t\trequired={required}\n\t\t\tvariant='outlined'\n\t\t\tSelectProps={{\n\t\t\t\tnative: true\n\t\t\t}}\n\t\t\t{...rest}\n\t\t>\n\t\t\t{!hideAll && {t('shell_os_filter_all')} }\n\t\t\t{list.map(p => {t(`shell_os_filter_${p}`)} )}\n\t\t \n\t);\n};\n\nexport default OSPurposeSelector;\n\nOSPurposeSelector.propTypes = {\n\tdisabled: PropTypes.bool,\n\thideAll: PropTypes.bool,\n\tlist: PropTypes.array,\n\trequired: PropTypes.bool,\n\tsetValue: PropTypes.func.isRequired,\n\tvalue: PropTypes.string\n};\n","import PropTypes from 'prop-types';\nimport React from 'react';\nimport { Grid, Radio } from '@material-ui/core';\nimport FormControlLabel from '@material-ui/core/FormControlLabel';\nimport Checkbox from '@material-ui/core/Checkbox';\nimport { useTranslation } from 'react-i18next';\nimport FormLabel from '@material-ui/core/FormLabel';\nimport FormControl from '@material-ui/core/FormControl';\nimport { SHELL_OS_PURPOSE_LIST, SHELL_OS_PURPOSE_LITE_LIST } from '../../../core/input/OSPurposeSelector';\nimport { useIsMode } from '../../../../hooks/useIsMode';\nimport { ADVANCED_MODE } from '../../../../context/ModeContext';\n\nconst OsFilters = ({ filters, setFilters, spacing, disabled = false }) => {\n\tconst { t } = useTranslation();\n\tconst isAdvanced = useIsMode(ADVANCED_MODE);\n\n\tconst handleBeta = e => {\n\t\tconst checked = e.target.checked;\n\t\tconst cpy = { ...filters };\n\t\tchecked ? delete cpy.Beta : cpy.Beta = 'N';\n\t\tsetFilters(cpy);\n\t};\n\n\tconst handleChange = e => {\n\t\tconst checked = e.target.checked;\n\t\tconst value = e.target.value;\n\t\tconst cpy = { ...filters };\n\t\tif (!checked) return;\n\n\t\tif (value === 'all') {\n\t\t\tdelete cpy.Purpose;\n\t\t} else {\n\t\t\tcpy.Purpose = value;\n\t\t}\n\n\t\tsetFilters(cpy);\n\t};\n\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{t('shell_os_filter_title')} \n\t\t\t\t \n\n\t\t\t\t{isAdvanced && \n\t\t\t\t\t \n\t\t\t\t\t\t}\n\t\t\t\t\t\tlabel={t('shell_os_filter_all')}\n\t\t\t\t\t/>\n\t\t\t\t \n\t\t\t\t}\n\n\t\t\t\t{\n\t\t\t\t\t(isAdvanced ? SHELL_OS_PURPOSE_LIST : SHELL_OS_PURPOSE_LITE_LIST).map(\n\t\t\t\t\t\tpurpose => {\n\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\tlabel={t(`shell_os_filter_${purpose}`)}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t)}\n\n\t\t\t\t\n\t\t\t\t\t \n\t\t\t\t\t\t}\n\t\t\t\t\t\tlabel={t('shell_os_filter_beta')}\n\t\t\t\t\t/>\n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default OsFilters;\n\nOsFilters.propTypes = {\n\tdisabled: PropTypes.bool,\n\tfilters: PropTypes.object.isRequired,\n\tsetFilters: PropTypes.func.isRequired,\n\tspacing: PropTypes.number.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React, { useEffect, useState } from 'react';\nimport { ICON_VARIATION } from '../../../../hooks/useOperatingSystems';\nimport { useTranslation } from 'react-i18next';\nimport CircularProgress from '@material-ui/core/CircularProgress';\nimport { Grid, Typography } from '@material-ui/core';\nimport TablePaginationActions from '@material-ui/core/TablePagination/TablePaginationActions';\nimport TablePagination from '@material-ui/core/TablePagination';\nimport { useOperatingSystems } from '@karpeleslab/klb-react-services';\nimport OsItem from './OSItem';\nimport OsFilters from './OSFilters';\nimport useDimensions from 'react-cool-dimensions';\nimport useTheme from '@material-ui/core/styles/useTheme';\n\nconst OsList = ({ shell, value, setValue, setShowDetailsFor, own = false, disabled = false, spacing = 3, initialFilters = { Beta: 'N' } }) => {\n\tconst { t } = useTranslation();\n\tconst [os, fetch] = useOperatingSystems();\n\tconst [loading, setLoading] = useState(true);\n\tconst [filters, setFilters] = useState({\n\t\tReady: 'Y',\n\t\timage_variation: [ICON_VARIATION],\n\t\t...initialFilters\n\t});\n\tconst [paging, setPaging] = useState({ results_per_page: 12, page_no: 1 });\n\tconst theme = useTheme();\n\tconst [perRow, setPerRow] = useState(6);\n\n\tconst { observe } = useDimensions({\n\t\tbreakpoints: {\n\t\t\t'2': theme.breakpoints.values.xs,\n\t\t\t'3': theme.breakpoints.values.sm,\n\t\t\t'4': theme.breakpoints.values.md,\n\t\t\t'6': theme.breakpoints.values.lg\n\t\t},\n\t\tupdateOnBreakpointChange: true,\n\t\tonResize: ({ currentBreakpoint }) => {\n\t\t\tsetPerRow(parseInt(currentBreakpoint));\n\t\t},\n\t});\n\n\tuseEffect(() => {\n\t\tconst params = { ...filters };\n\t\tparams.Visible = own ? 'N' : 'Y';\n\n\t\tsetLoading(true);\n\t\tsetValue(null);\n\t\tfetch(params, paging).then(() => setLoading(false));\n\t}, [own, filters, paging, setLoading]);\n\n\tconst changePageHandler = (e, newPage) => {\n\t\tsetPaging({ ...paging, page_no: parseInt(newPage) + 1 });\n\t};\n\n\tif (!loading && !os) return ;\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t \n\t\t\t \n\n\t\t\t{\n\t\t\t\t(\n\t\t\t\t\t(!loading && os) ? os.data : [...Array(4).keys()]\n\t\t\t\t).map(\n\t\t\t\t\to => {\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t setValue(o)}\n\t\t\t\t\t\t\t\t\tselected={loading ? false : (value ? value.Shell_OS__ === o.Shell_OS__ : false)}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t)\n\t\t\t}\n\t\t\t{(!loading && os && os.data.length < 1) &&\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{t('shell_os_filter_no_result')}\n\t\t\t\t \n\t\t\t \n\t\t\t}\n\t\t\t{(!loading && os && os.paging.page_max > 1) &&\n\t\t\t\n\t\t\t\t t(count !== -1 ? 'table_paging' : 'table_paging_more', {\n\t\t\t\t\t\t\tfrom: from,\n\t\t\t\t\t\t\tto: to,\n\t\t\t\t\t\t\tcount: count\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\t\t\t\t\tonChangePage={changePageHandler}\n\t\t\t\t\tActionsComponent={TablePaginationActions}\n\t\t\t\t/>\n\t\t\t \n\t\t\t}\n\t\t \n\t);\n};\n\nexport default OsList;\n\nOsList.propTypes = {\n\tdisabled: PropTypes.bool,\n\tinitialFilters: PropTypes.object,\n\town: PropTypes.bool,\n\tsetShowDetailsFor: PropTypes.func.isRequired,\n\tsetValue: PropTypes.func.isRequired,\n\tshell: PropTypes.object.isRequired,\n\tspacing: PropTypes.number,\n\tvalue: PropTypes.any\n};\n","import PropTypes from 'prop-types';\nimport React, { useEffect, useState } from 'react';\nimport { Grid } from '@material-ui/core';\nimport RichAlertTrans from '../../../core/feedback/RichAlertTrans';\nimport TextField from '@material-ui/core/TextField';\nimport { validate } from '../../../../utils/uuid';\nimport { useTranslation } from 'react-i18next';\nimport { ICON_VARIATION, useFetchOperatingSystem } from '../../../../hooks/useOperatingSystems';\nimport InputAdornment from '@material-ui/core/InputAdornment';\nimport CircularProgress from '@material-ui/core/CircularProgress';\nimport OsItem from './OSItem';\n\nconst InputSharedOS = ({ shell, value, setValue, setShowDetailsFor, disabled = false, spacing = 3 }) => {\n\tconst { t } = useTranslation();\n\tconst [shareInput, setShareInput] = useState('');\n\tconst [fetch] = useFetchOperatingSystem();\n\tconst [loading, setLoading] = useState(false);\n\tconst [error, setError] = useState(false);\n\n\tuseEffect(() => {\n\t\tif (!validate(shareInput, 'shlos')) return;\n\t\tsetLoading(true);\n\t\tconst params = { image_variation: [ICON_VARIATION] };\n\t\tfetch(shareInput, params)\n\t\t\t.then(os => {\n\t\t\t\tif (os.data.Ready !== 'Y') {\n\t\t\t\t\tsetError(true);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (os.data.Visible !== 'Y' && os.data.Public !== 'Y') {\n\t\t\t\t\tsetError(true);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tsetValue(os.data);\n\t\t\t\tsetError(false);\n\t\t\t})\n\t\t\t.catch(() => setError(true))\n\t\t\t.finally(() => setLoading(false));\n\t}, [shareInput, setLoading, fetch]);\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t \n\t\t\t \n\t\t\t\n\t\t\t\t setShareInput(e.target.value)}\n\t\t\t\t\tInputProps={\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tendAdornment: (\n\t\t\t\t\t\t\t\tloading ?\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t: null\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t/>\n\t\t\t \n\t\t\t{value &&\n\t\t\t\n\t\t\t\t {\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tloading={loading}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\tos={loading ? null : value}\n\t\t\t\t\tsetShowDetailsFor={setShowDetailsFor}\n\t\t\t\t\tselected={true}\n\t\t\t\t/>\n\t\t\t \n\t\t\t}\n\t\t\t{(shareInput && error) &&\n\t\t\t\n\t\t\t\t \n\t\t\t \n\t\t\t}\n\t\t \n\t);\n};\n\nexport default InputSharedOS;\n\nInputSharedOS.propTypes = {\n\tdisabled: PropTypes.bool,\n\tsetShowDetailsFor: PropTypes.func.isRequired,\n\tsetValue: PropTypes.func.isRequired,\n\tshell: PropTypes.object.isRequired,\n\tspacing: PropTypes.number,\n\tvalue: PropTypes.object\n};\n","import React, { useEffect, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport TextField from '@material-ui/core/TextField';\nimport InputAdornment from '@material-ui/core/InputAdornment';\nimport CircularProgress from '@material-ui/core/CircularProgress';\nimport PropTypes from 'prop-types';\nimport { ICON_VARIATION } from '../../../hooks/useOperatingSystems';\nimport { useOperatingSystems } from '@karpeleslab/klb-react-services';\n\nconst ShellOsSelector = ({ value, setValue, own = false, label = null, allowEmpty = false, emptyText = null, helperText = null, disabled = false, required = false, purpose = null, ...rest }) => {\n\tconst { t } = useTranslation();\n\tconst [os, fetch, loading] = useOperatingSystems();\n\tconst [idToOsMap, setIdToOsMap] = useState();\n\n\tconst [releasedOS, setReleasedOS] = useState([]);\n\tconst [betaOs, setBetaOS] = useState([]);\n\tconst [licenseOs, setLicenseOs] = useState([]);\n\n\tuseEffect(() => {\n\t\tconst params = { Ready: 'Y', Visible: own ? 'N' : 'Y', image_variation: [ICON_VARIATION] };\n\t\tif (purpose) params.Purpose = purpose;\n\n\t\tfetch(params, { results_per_page: 100 });\n\t}, [purpose]); // eslint-disable-line\n\n\tuseEffect(() => {\n\t\tif (!os) return;\n\t\tconst map = {};\n\t\tconst beta = [];\n\t\tconst license = [];\n\t\tconst nonBeta = [];\n\t\tos.data.forEach(s => {\n\t\t\tif (s.Catalog_Product__) license.push(s);\n\t\t\telse if (s.Beta === 'Y') beta.push(s);\n\t\t\telse nonBeta.push(s);\n\t\t\tmap[s.Shell_OS__] = s;\n\t\t});\n\t\tif (value === null) {\n\t\t\tconst first = nonBeta[0] || beta[0];\n\t\t\tif (first) {\n\t\t\t\tsetValue(first);\n\t\t\t}\n\t\t}\n\t\tsetBetaOS(beta);\n\t\tsetReleasedOS(nonBeta);\n\t\tsetLicenseOs(license);\n\t\tsetIdToOsMap(map);\n\t}, [os, setIdToOsMap, setBetaOS, setReleasedOS, setLicenseOs]);\n\n\treturn (\n\t\t setValue(idToOsMap[e.target.value] ?? 'none')}\n\t\t\tselect\n\t\t\tfullWidth\n\t\t\tdisabled={disabled || !os}\n\t\t\trequired={required}\n\t\t\tvariant='outlined'\n\t\t\tInputProps={loading ?\n\t\t\t\t{\n\t\t\t\t\tendAdornment:\n\t\t\t\t\t\t(\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t )\n\t\t\t\t} : undefined\n\t\t\t}\n\t\t\tSelectProps={{\n\t\t\t\tnative: true\n\t\t\t}}\n\t\t\t{...rest}\n\t\t>\n\t\t\t{(os && os.data.length < 1 && !loading) && {t('shell_os_filter_no_result_short')} }\n\t\t\t{(os && os.data.length > 0 && allowEmpty) &&\n\t\t\t\n\t\t\t\t{emptyText === null ? t('shell_os_selector_default') : emptyText}\n\t\t\t \n\t\t\t}\n\n\t\t\t{(releasedOS.length > 0 && !loading) &&\n\t\t\t\n\t\t\t\t{releasedOS.map(\n\t\t\t\t\tos => \n\t\t\t\t\t\t{os.Name}\n\t\t\t\t\t )}\n\t\t\t \n\t\t\t}\n\n\t\t\t{(licenseOs.length > 0 && !loading) &&\n\t\t\t\n\t\t\t\t{licenseOs.map(\n\t\t\t\t\tos => \n\t\t\t\t\t\t{os.Name}\n\t\t\t\t\t )}\n\t\t\t \n\t\t\t}\n\n\t\t\t{(betaOs.length > 0 && !loading) &&\n\t\t\t\n\t\t\t\t{betaOs.map(\n\t\t\t\t\tos => \n\t\t\t\t\t\t{os.Name}\n\t\t\t\t\t )}\n\t\t\t \n\t\t\t}\n\n\t\t \n\t);\n};\n\nexport default ShellOsSelector;\n\nShellOsSelector.propTypes = {\n\tallowEmpty: PropTypes.bool,\n\tdisabled: PropTypes.bool,\n\temptyText: PropTypes.any,\n\thelperText: PropTypes.string,\n\tlabel: PropTypes.string,\n\town: PropTypes.bool,\n\tpurpose: PropTypes.string,\n\trequired: PropTypes.bool,\n\tsetValue: PropTypes.func.isRequired,\n\tvalue: PropTypes.object\n};\n","import PropTypes from 'prop-types';\nimport React, { useEffect, useState } from 'react';\nimport { Grid } from '@material-ui/core';\nimport ShellOsSelector from '../../../core/input/ShellOsSelector';\nimport OSPurposeSelector, {\n\tSHELL_OS_PURPOSE_LIST,\n\tSHELL_OS_PURPOSE_LITE_LIST\n} from '../../../core/input/OSPurposeSelector';\nimport { useIsMode } from '../../../../hooks/useIsMode';\nimport { ADVANCED_MODE } from '../../../../context/ModeContext';\nimport { isShellKernel } from '../../../../utils/misc';\nimport OsItemShellKernel from './OSItemShellKernel';\n\nconst MobileOSSelector = ({ value, setValue, own = false, spacing = 2, initialSource = null }) => {\n\tconst [source, setSource] = useState(initialSource);\n\tconst isAdvanced = useIsMode(ADVANCED_MODE);\n\n\tuseEffect(() => {\n\t\tif (value !== null) {\n\t\t\tsetValue(null);\n\t\t}\n\t\t// eslint-disable-next-line\n\t}, [source]);\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t \n\t\t\t \n\t\t\t\n\t\t\t\t \n\t\t\t \n\t\t\t{(value && isShellKernel(value)) &&\n\t\t\t\n\t\t\t\t \n\t\t\t \n\t\t\t}\n\t\t \n\t);\n};\n\nexport default MobileOSSelector;\n\nMobileOSSelector.propTypes = {\n\tinitialSource: PropTypes.string,\n\town: PropTypes.bool,\n\tsetValue: PropTypes.func.isRequired,\n\tspacing: PropTypes.number,\n\tvalue: PropTypes.object,\n};\n","import PropTypes from 'prop-types';\nimport React from 'react';\nimport Panel from '../../../layout/Container/tab/Panel';\nimport { OS_OFFICIAL, OS_PRIVATE, OS_SHARE } from './SourceTabs';\nimport OsList from './OSList';\nimport InputSharedOS from './InputSharedOS';\nimport RichAlertTrans from '../../../core/feedback/RichAlertTrans';\nimport { Grid } from '@material-ui/core';\nimport MobileOSSelector from './MobileOSSelector';\n\nconst SourceDisplay = ({ shell, tab, value, setValue, setShowDetailsFor, disabled = false, mobile = false, spacing = 3 }) => {\n\treturn (\n\t\t<>\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t \n\n\t\t\t\t\t{mobile &&\n\t\t\t\t\t\n\t\t\t\t\t\t \n\t\t\t\t\t }\n\n\t\t\t\t\t{!mobile && \n\t\t\t\t\t\t \n\t\t\t\t\t }\n\t\t\t\t \n\t\t\t \n\t\t\t\n\t\t\t\t\n\t\t\t\t\t \n\n\t\t\t\t\t{mobile &&\n\t\t\t\t\t\n\t\t\t\t\t\t \n\t\t\t\t\t }\n\t\t\t\t\t{!mobile && \n\t\t\t\t\t\t \n\t\t\t\t\t }\n\t\t\t\t \n\t\t\t \n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t \n\t\t\t \n\t\t>\n\t);\n\n};\n\nexport default SourceDisplay;\n\nSourceDisplay.propTypes = {\n\tdisabled: PropTypes.bool,\n\tmobile: PropTypes.bool,\n\tsetShowDetailsFor: PropTypes.func.isRequired,\n\tsetValue: PropTypes.func.isRequired,\n\tshell: PropTypes.object.isRequired,\n\tspacing: PropTypes.number,\n\ttab: PropTypes.string.isRequired,\n\tvalue: PropTypes.any\n};\n","import PropTypes from 'prop-types';\nimport React from 'react';\nimport { useTranslation } from 'react-i18next';\nimport Dialog from '@material-ui/core/Dialog';\nimport DialogTitle from '@material-ui/core/DialogTitle';\nimport DialogContent from '@material-ui/core/DialogContent';\nimport Grid from '@material-ui/core/Grid';\nimport DialogActions from '@material-ui/core/DialogActions';\nimport Button from '../../../core/input/Button';\nimport { Typography } from '@material-ui/core';\nimport Avatar from '@material-ui/core/Avatar';\nimport { ICON_VARIATION } from '../../../../hooks/useOperatingSystems';\nimport defaultIcon from '../../../../assets/img/shells_icon_white.svg';\nimport OsItemLicense from './OSItemLicense';\nimport { isShellKernel } from '../../../../utils/misc';\nimport OsItemShellKernel from './OSItemShellKernel';\n\nconst OSDetailsDialog = ({ shell, os, setShowDetailsFor }) => {\n\tconst { t } = useTranslation();\n\n\tconst handleClose = () => {\n\t\tsetShowDetailsFor(null);\n\t};\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t{os.Name + (os.Beta === 'Y' ? ` (${t('shell_os_beta_mark')})` : '')}\n\t\t\t \n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t\t{isShellKernel(os) &&\n\t\t\t\t\t\n\t\t\t\t\t\t \n\t\t\t\t\t }\n\t\t\t\t\t{os.Short_Description &&\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t{os.Short_Description}\n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t\t}\n\n\t\t\t\t\t{os.Catalog_Product__ &&\n\t\t\t\t\t\n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t\t}\n\n\t\t\t\t\t{os.Description &&\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t{os.Description}\n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t\t}\n\t\t\t\t \n\t\t\t \n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{t('close_btn')}\n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default OSDetailsDialog;\n\nOSDetailsDialog.propTypes = {\n\tos: PropTypes.object.isRequired,\n\tsetShowDetailsFor: PropTypes.func.isRequired,\n\tshell: PropTypes.object.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React, { useState } from 'react';\nimport { Grid } from '@material-ui/core';\nimport SourceTabs, { OS_OFFICIAL } from './SourceTabs';\nimport SourceDisplay from './SourceDisplay';\nimport useMediaQuery from '@material-ui/core/useMediaQuery';\nimport OSDetailsDialog from './OSDetailsDialog';\n\n\nconst OSSelector = ({ shell, value, setValue, disabled = false, spacing = 3 }) => {\n\tconst [tab, setTab] = useState(OS_OFFICIAL);\n\tconst isMobile = useMediaQuery(theme => theme.breakpoints.down('xs'), { noSsr: true });\n\tconst [showDetailsFor, setShowDetailsFor] = useState(null);\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t \n\t\t\t \n\t\t\t\n\t\t\t\t \n\t\t\t \n\t\t\t{showDetailsFor &&\n\t\t\t\n\t\t\t}\n\t\t \n\t);\n};\n\nexport default OSSelector;\n\nOSSelector.propTypes = {\n\tdisabled: PropTypes.bool,\n\tsetValue: PropTypes.func.isRequired,\n\tshell: PropTypes.object.isRequired,\n\tspacing: PropTypes.number,\n\tvalue: PropTypes.any\n};\n","import PropTypes from 'prop-types';\nimport React, { useEffect, useState } from 'react';\nimport RichAlert from '../../../core/feedback/RichAlert';\nimport { Trans } from 'react-i18next';\nimport { getSSHKeychainRoute } from '../../../RouteController/Factory';\n\nconst SSHKeyWarning = ({ os, keychain }) => {\n\tconst [show, setShow] = useState(false);\n\n\tuseEffect(() => {\n\t\tif (!os || os.Purpose !== 'server') {\n\t\t\tsetShow(false);\n\t\t\treturn;\n\t\t}\n\n\t\tif (!keychain || keychain === 'none') {\n\t\t\tsetShow(true);\n\t\t\treturn;\n\t\t}\n\n\t\tsetShow(false);\n\n\t}, [setShow, os, keychain]);\n\n\tif (!show) return <>>;\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\tsample \n\t\t\t\tsample \n\t\t\t\tsample \n\t\t\t\t\n\t\t\t\t\tsample\n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default SSHKeyWarning;\n\nSSHKeyWarning.propTypes = {\n\tkeychain: PropTypes.string,\n\tos: PropTypes.object\n};\n","import React, { useEffect } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport TextField from '@material-ui/core/TextField';\nimport InputAdornment from '@material-ui/core/InputAdornment';\nimport CircularProgress from '@material-ui/core/CircularProgress';\nimport PropTypes from 'prop-types';\nimport { useKeychains } from '@karpeleslab/klb-react-services';\n\nconst ShellKeychainSelector = ({ value, setValue, label = null, helperText = null, disabled = false, required = false, ...rest }) => {\n\tconst { t } = useTranslation();\n\tconst [keychains, fetch, loading] = useKeychains();\n\n\tuseEffect(() => {\n\t\tfetch({}, { results_per_page: 100 });\n\t}, []); // eslint-disable-line\n\n\treturn (\n\t\t setValue(e.target.value)}\n\t\t\tselect\n\t\t\tfullWidth\n\t\t\tdisabled={disabled || !keychains}\n\t\t\trequired={required}\n\t\t\tvariant='outlined'\n\t\t\tInputProps={loading ?\n\t\t\t\t{\n\t\t\t\t\tendAdornment:\n\t\t\t\t\t\t(\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t )\n\t\t\t\t} : undefined\n\t\t\t}\n\t\t\tSelectProps={{\n\t\t\t\tnative: true\n\t\t\t}}\n\t\t\t{...rest}\n\t\t>\n\t\t\t{t('shell_keychain_selector_do_not_use')} \n\t\t\t{!loading && keychains && keychains.data.map(\n\t\t\t\tkeychain => {keychain.Label} \n\t\t\t)}\n\t\t \n\t);\n};\n\nexport default ShellKeychainSelector;\n\nShellKeychainSelector.propTypes = {\n\tdisabled: PropTypes.bool,\n\thelperText: PropTypes.string,\n\tlabel: PropTypes.string,\n\trequired: PropTypes.bool,\n\tsetValue: PropTypes.func.isRequired,\n\tvalue: PropTypes.string.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React from 'react';\nimport { Grid } from '@material-ui/core';\nimport RichAlertTrans from '../../../core/feedback/RichAlertTrans';\nimport RichAlert from '../../../core/feedback/RichAlert';\nimport { Trans, useTranslation } from 'react-i18next';\nimport Button from '../../../core/input/Button';\n\nconst SelectOsLicenseInfo = ({ os, loadingLicense, hasLicense, handleBuyLicense }) => {\n\tconst {t} = useTranslation();\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t{(loadingLicense || hasLicense) &&\n\t\t\t\t \n\t\t\t\t}\n\t\t\t\t{(!loadingLicense && !hasLicense) &&\n\t\t\t\t\n\t\t\t\t\t\t\t{t('buy_license_btn')}\n\t\t\t\t\t\t\n\t\t\t\t\t}\n\t\t\t\t>\n\t\t\t\t\t\n\t\t\t\t\t\tsample \n\t\t\t\t\t\tsample \n\t\t\t\t\t\tsample \n\t\t\t\t\t \n\t\t\t\t \n\t\t\t\t}\n\t\t\t \n\t\t \n\t);\n};\n\nexport default SelectOsLicenseInfo;\n\nSelectOsLicenseInfo.propTypes = {\n\thandleBuyLicense: PropTypes.func.isRequired,\n\thasLicense: PropTypes.bool.isRequired,\n\tloadingLicense: PropTypes.bool.isRequired,\n\tos: PropTypes.object.isRequired,\n};\n","export default __webpack_public_path__ + \"static/media/emptyCart.498b68fd.svg\";","import React from 'react';\nimport { Trans, useTranslation } from 'react-i18next';\nimport EmptyState from '../../../core/feedback/State/Empty';\nimport Graphic from '../../../../assets/img/emptyCart.svg';\n\nconst EmptyCart = () => {\n\tconst { t } = useTranslation();\n\n\treturn (\n\t\t\n\t\t\t\tsample \n\t\t\t\tsample \n\t\t\t}\n\t\t\tgraphic={Graphic}\n\t\t/>\n\t);\n};\n\nexport default EmptyCart;\n","import React from 'react';\nimport { useTranslation } from 'react-i18next';\nimport TableRow from '@material-ui/core/TableRow';\nimport TableCell from '@material-ui/core/TableCell';\nimport TableHead from '@material-ui/core/TableHead';\n\nconst CartHeader = () => {\n\tconst { t } = useTranslation();\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t{t('cart_item_name')} \n\t\t\t\t{t('cart_item_quantity')} \n\t\t\t\t{t('cart_item_price_raw')} \n\t\t\t\t{t('cart_item_vat_rate')} \n\t\t\t\t{t('cart_item_total')} \n\t\t\t\t{t('cart_item_action')} \n\t\t\t \n\t\t \n\t);\n};\n\nexport default CartHeader;\n","import PropTypes from 'prop-types';\nimport React from 'react';\nimport TableCell from '@material-ui/core/TableCell';\nimport TableRow from '@material-ui/core/TableRow';\nimport { IconButton } from '@material-ui/core';\nimport DeleteForeverOutlinedIcon from '@material-ui/icons/DeleteForeverOutlined';\nimport { useCatalogCartItemRemove } from '@karpeleslab/klb-react-services';\n\nconst CartItem = ({ cartItem, refreshCart }) => {\n\tconst [remove, removing] = useCatalogCartItemRemove(cartItem.key);\n\n\tconst handleDelete = () => {\n\t\tremove().then(refreshCart);\n\t};\n\n\treturn (\n\t\t\n\t\t\t{cartItem.data['Basic.Name']} \n\t\t\t{cartItem.quantity} \n\t\t\t{cartItem.price.raw.display} \n\t\t\t{`${cartItem.price.tax_rate}%`} \n\t\t\t{cartItem.price.tax.display} \n\t\t\t\n\t\t\t\t\n\t\t\t\t\t \n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default CartItem;\n\nCartItem.propTypes = {\n\tcartItem: PropTypes.object.isRequired,\n\trefreshCart: PropTypes.func.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React from 'react';\nimport CartItem from './CartItem';\n\nconst CartItems = ({ items, refreshCart }) => {\n\treturn (\n\t\t<>\n\t\t\t{items.map(product => )}\n\t\t>\n\t);\n};\n\nexport default CartItems;\n\nCartItems.propTypes = {\n\titems: PropTypes.array.isRequired,\n\trefreshCart: PropTypes.func.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React from 'react';\nimport { TableBody } from '@material-ui/core';\nimport Table from '@material-ui/core/Table';\nimport TableContainer from '@material-ui/core/TableContainer';\nimport { useTranslation } from 'react-i18next';\nimport TableRow from '@material-ui/core/TableRow';\nimport TableCell from '@material-ui/core/TableCell';\nimport TableHead from '@material-ui/core/TableHead';\nimport { Title } from '../../../../core/typography/Title';\n\nconst CartSubTotals = ({ subtotals }) => {\n\tconst { t } = useTranslation();\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t{t('cart_sub_totals')}\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t \n\t\t\t\t\n\n\t\t\t\t\t\n\t\t\t\t\t\t{t('cart_sub_total_cart')} \n\t\t\t\t\t\t{subtotals.regular.display} \n\t\t\t\t\t \n\n\t\t\t\t\t\n\t\t\t\t\t\t{t('cart_sub_total_shipping')} \n\t\t\t\t\t\t{subtotals.shipping.display} \n\t\t\t\t\t \n\n\t\t\t\t\t\n\t\t\t\t\t\t{t('cart_sub_total_discount')} \n\t\t\t\t\t\t{subtotals.discount.display} \n\t\t\t\t\t \n\n\t\t\t\t\t\n\t\t\t\t\t\t{t('cart_sub_total_other_tax')} \n\t\t\t\t\t\t{subtotals.tax.display} \n\t\t\t\t\t \n\t\t\t\t \n\t\t\t
\n\t\t \n\t);\n};\n\nexport default CartSubTotals;\n\nCartSubTotals.propTypes = {\n\tsubtotals: PropTypes.object.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React from 'react';\nimport { useTranslation } from 'react-i18next';\nimport TableContainer from '@material-ui/core/TableContainer';\nimport Table from '@material-ui/core/Table';\nimport TableHead from '@material-ui/core/TableHead';\nimport TableRow from '@material-ui/core/TableRow';\nimport TableCell from '@material-ui/core/TableCell';\nimport { TableBody } from '@material-ui/core';\nimport { Title } from '../../../../core/typography/Title';\n\nconst CartTotals = ({ cart }) => {\n\tconst { t } = useTranslation();\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t{t('cart_totals')}\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t \n\t\t\t\t\n\n\t\t\t\t\t\n\t\t\t\t\t\t{t('cart_total_before_discount')} \n\t\t\t\t\t\t{cart.total_no_coupon.display} \n\t\t\t\t\t \n\n\t\t\t\t\t\n\t\t\t\t\t\t{t('cart_total_after_discount')} \n\t\t\t\t\t\t{cart.total.display} \n\t\t\t\t\t \n\n\t\t\t\t\t\n\t\t\t\t\t\t{t('cart_total_vat_only')} \n\t\t\t\t\t\t{cart.total_vat_only.display} \n\t\t\t\t\t \n\n\t\t\t\t\t\n\t\t\t\t\t\t{t('cart_total_vat')} \n\t\t\t\t\t\t{cart.total_vat.display} \n\t\t\t\t\t \n\n\t\t\t\t \n\t\t\t
\n\t\t \n\t);\n};\n\nexport default CartTotals;\n\nCartTotals.propTypes = {\n\tcart: PropTypes.object.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React from 'react';\nimport Grid from '@material-ui/core/Grid';\nimport CartSubTotals from './Prices/CartSubTotals';\nimport CartTotals from './Prices/CartTotals';\n\nconst CartPrices = ({ cart }) => {\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t \n\n\t\t\t\n\t\t\t\t\n\t\t\t \n\t\t \n\t);\n};\n\nexport default CartPrices;\n\nCartPrices.propTypes = {\n\tcart: PropTypes.object.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React, { useState } from 'react';\nimport { Grid } from '@material-ui/core';\nimport TextField from '@material-ui/core/TextField';\nimport { useTranslation } from 'react-i18next';\nimport { useCatalogCartProcess } from '@karpeleslab/klb-react-services';\nimport AddShoppingCartIcon from '@material-ui/icons/AddShoppingCart';\nimport InputAdornment from '@material-ui/core/InputAdornment';\nimport Tooltip from '@material-ui/core/Tooltip';\nimport IconButton from '@material-ui/core/IconButton';\n\nconst CartAddCoupon = ({ refresh }) => {\n\tconst { t } = useTranslation();\n\tconst [coupon, setCoupon] = useState('');\n\tconst [processQuery, processingCart] = useCatalogCartProcess();\n\n\tconst handleAdd = () => {\n\t\tconst query = `coupon,coupon_code=${coupon.trim()}`;\n\t\tprocessQuery(query, { snackMessageToken: null })\n\t\t\t.then(cart => {\n\t\t\t\tsetCoupon('');\n\t\t\t\trefresh(cart);\n\t\t\t});\n\t};\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t setCoupon(e.target.value)}\n\t\t\t\t\tInputProps={\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tendAdornment:\n\t\t\t\t\t\t\t\t(\n\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t )\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\t\t\t\t/>\n\t\t\t \n\t\t \n\t);\n};\n\nexport default CartAddCoupon;\n\nCartAddCoupon.propTypes = {\n\trefresh: PropTypes.func.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React from 'react';\nimport TextField from '@material-ui/core/TextField';\nimport { useTranslation } from 'react-i18next';\nimport { useRest } from '@karpeleslab/react-klbfw-hooks';\nimport InputAdornment from '@material-ui/core/InputAdornment';\nimport CircularProgress from '@material-ui/core/CircularProgress';\nimport { getCountriesEndpoint } from '@karpeleslab/klb-react-services';\n\nconst CountrySelector = ({ value, setValue, label = null, helperText = null, disabled = false, required = false, ...rest }) => {\n\tconst { t } = useTranslation();\n\tconst [countries] = useRest(getCountriesEndpoint());\n\n\treturn (\n\t\t setValue(e.target.value)}\n\t\t\tselect\n\t\t\tfullWidth\n\t\t\tInputLabelProps={{ shrink: !!value }}\n\t\t\tdisabled={disabled || !countries}\n\t\t\trequired={required}\n\t\t\tvariant='outlined'\n\t\t\tInputProps={!countries ?\n\t\t\t\t{\n\t\t\t\t\tendAdornment:\n\t\t\t\t\t\t(\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t )\n\t\t\t\t} : undefined\n\t\t\t}\n\t\t\tSelectProps={{\n\t\t\t\tnative: true\n\t\t\t}}\n\t\t\t{...rest}\n\t\t>\n\t\t\t \n\t\t\t{countries && countries.data.map(\n\t\t\t\tcountry => {country.Name} \n\t\t\t)}\n\t\t \n\t);\n};\n\nexport default CountrySelector;\n\nCountrySelector.propTypes = {\n\tdisabled: PropTypes.bool,\n\thelperText: PropTypes.string,\n\tlabel: PropTypes.string,\n\trequired: PropTypes.bool,\n\tsetValue: PropTypes.func.isRequired,\n\tvalue: PropTypes.string.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React, { useEffect } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport Grid from '@material-ui/core/Grid';\nimport TextField from '@material-ui/core/TextField';\nimport CountrySelector from '../../../core/input/CountrySelector';\n\nconst Form = ({ data, setData, setIsValid, disabled = false }) => {\n\tconst { t } = useTranslation();\n\n\tconst createChangeHandler = (key, isEvent = true) => e => {\n\t\tsetData({ ...data, [key]: isEvent ? e.target.value : e });\n\t};\n\n\tconst getValue = (key, def = '') => {\n\t\tif (!(key in (data ?? {}))) return def;\n\t\treturn data[key];\n\t};\n\n\tuseEffect(() => {\n\t\tif (!('First_Name' in (data ?? {})) || !getValue('First_Name').trim()) setIsValid(false);\n\t\telse if (!('Last_Name' in (data ?? {})) || !getValue('Last_Name').trim()) setIsValid(false);\n\t\telse if (!('Zip' in (data ?? {})) || !getValue('Zip').trim()) setIsValid(false);\n\t\telse if (!('Country__' in (data ?? {})) || !getValue('Country__')) setIsValid(false);\n\t\telse setIsValid(true);\n\t}, [data, setIsValid]);\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t \n\t\t\t \n\t\t\t\n\t\t\t\t \n\t\t\t \n\t\t\t\n\t\t\t\t \n\t\t\t \n\t\t\t\n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default Form;\n\nForm.propTypes = {\n\tdata: PropTypes.object.isRequired,\n\tdisabled: PropTypes.bool,\n\tsetData: PropTypes.func.isRequired,\n\tsetIsValid: PropTypes.func.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React, { useContext, useEffect, useState } from 'react';\nimport { UserContext } from '../../../../context/UserContext';\nimport { Grid } from '@material-ui/core';\nimport Button from '../../../core/input/Button';\nimport { useTranslation } from 'react-i18next';\nimport {\n\tuseCatalogCartCreateOrder,\n\tuseUserLocationCreate,\n\tuseUserSetDefaultLocation\n} from '@karpeleslab/klb-react-services';\nimport Form from '../../User/Location/Form';\nimport { Title } from '../../../core/typography/Title';\n\n\nconst CreateOrder = ({ setOrder, setCreating, setDialogActions = null }) => {\n\tconst { t } = useTranslation();\n\n\tconst [userContext] = useContext(UserContext);\n\tconst [createOrder, creatingOrder] = useCatalogCartCreateOrder();\n\tconst [createLocation, creatingLocation] = useUserLocationCreate('@');\n\tconst [setDefaultLocation, settingDefaultLocation] = useUserSetDefaultLocation('@');\n\n\tconst [location, setLocation] = useState({});\n\tconst [locationValid, setLocationValid] = useState(false);\n\n\tuseEffect(() => {\n\t\tif (!setCreating) return;\n\t\tsetCreating(creatingOrder || creatingLocation || settingDefaultLocation);\n\t}, [setCreating, creatingOrder, creatingLocation, settingDefaultLocation]);\n\n\tuseEffect(() => {\n\t\tif (!setDialogActions) return;\n\t\tif (userContext.user.data.Default_Billing_User_Location__) {\n\t\t\tsetDialogActions((\n\t\t\t\t\n\t\t\t\t\t{t('create_order_btn')}\n\t\t\t\t \n\t\t\t));\n\t\t} else {\n\t\t\tsetDialogActions((\n\t\t\t\t\n\t\t\t\t\t{t('create_order_btn')}\n\t\t\t\t \n\t\t\t));\n\t\t}\n\n\t}, [setDialogActions, creatingLocation, settingDefaultLocation, creatingOrder, locationValid]);\n\n\tconst handleCreateOrder = () => {\n\t\tcreateOrder().then(setOrder);\n\t};\n\n\tconst handleCreateOrderWithLocation = e => {\n\t\te.preventDefault();\n\n\t\tcreateLocation(location, { snackMessageToken: null })\n\t\t\t.then(location => setDefaultLocation(location.User_Location__, 'Billing', { snackMessageToken: null }))\n\t\t\t.then(handleCreateOrder);\n\t};\n\n\tif (userContext.user.data.Default_Billing_User_Location__) {\n\t\t// Button is added to the dialog with useEffect above\n\t\tif (setDialogActions) return <>>;\n\n\t\treturn (\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t{t('create_order_btn')}\n\t\t\t\t\t \n\t\t\t\t \n\t\t\t \n\t\t);\n\t}\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{t('cart_billing_location_create')} \n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t \n\t\t\t\t \n\t\t\t\t{!setDialogActions && \n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t{t('create_order_btn')}\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t }\n\t\t\t \n\t\t \n\t);\n};\n\nexport default CreateOrder;\n\nCreateOrder.propTypes = {\n\tsetOrder: PropTypes.func.isRequired,\n\tsetCreating: PropTypes.func,\n\tsetDialogActions: PropTypes.func // Used when the component is used in a dialog in order to integrate the action into the dialog actions\n};\n","import PropTypes from 'prop-types';\nimport React, { useEffect } from 'react';\nimport { useCatalogCart, useCatalogCartProcess, useCatalogCartReset } from '@karpeleslab/klb-react-services';\nimport Loader from '../../layout/Loader/Loader';\nimport { Grid } from '@material-ui/core';\nimport EmptyCart from './Cart/EmptyCart';\nimport Table from '@material-ui/core/Table';\nimport TableBody from '@material-ui/core/TableBody';\nimport TableContainer from '@material-ui/core/TableContainer';\nimport { useTranslation } from 'react-i18next';\nimport CartHeader from './Cart/CartHeader';\nimport CartItems from './Cart/CartItems';\nimport CartPrices from './Cart/CartPrices';\nimport CartAddCoupon from './Cart/CartAddCoupon';\nimport { Title } from '../../core/typography/Title';\nimport CreateOrder from './Cart/CreateOrder';\n\nconst Cart = ({ request = null, setOrder, setCreating, setDialogActions = null }) => {\n\tconst [cart, refresh, loadingCart] = useCatalogCart();\n\tconst [processQuery, processingCart] = useCatalogCartProcess();\n\tconst [resetCart, resettingCart] = useCatalogCartReset();\n\tconst { t } = useTranslation();\n\n\tuseEffect(() => {\n\t\tif (!request) return;\n\n\t\tresetCart()\n\t\t\t.then(() => processQuery(request, { snackMessageToken: null }))\n\t\t\t.then(newCart => refresh(newCart));\n\n\t}, [request, refresh, resetCart]);\n\n\n\tif (!cart || loadingCart || processingCart || resettingCart) {\n\t\treturn ;\n\t}\n\n\tif (cart.data.products.length < 1) {\n\t\treturn ;\n\t}\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{t('cart_title')}\n\t\t\t\t \n\t\t\t \n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t
\n\t\t\t\t \n\t\t\t \n\n\t\t\t\n\t\t\t\t\n\t\t\t \n\n\t\t\t\n\t\t\t\t\n\t\t\t \n\t\t\t{setOrder &&\n\t\t\t\n\t\t\t\t \n\t\t\t \n\t\t\t}\n\t\t \n\t);\n};\n\nexport default Cart;\n\nCart.propTypes = {\n\trequest: PropTypes.string,\n\tsetCreating: PropTypes.func,\n\tsetOrder: PropTypes.func,\n\tsetDialogActions: PropTypes.func // Used when the component is used in a dialog in order to integrate the action into the dialog actions\n};\n","import PropTypes from 'prop-types';\nimport React, { useState } from 'react';\nimport Box from '@material-ui/core/Box';\nimport Dialog from '@material-ui/core/Dialog';\nimport DialogTitle from '@material-ui/core/DialogTitle';\nimport DialogContent from '@material-ui/core/DialogContent';\nimport Grid from '@material-ui/core/Grid';\nimport DialogActions from '@material-ui/core/DialogActions';\nimport Button from '../../../core/input/Button';\nimport { useTranslation } from 'react-i18next';\nimport Cart from '../../Cart/Cart';\nimport OrderWithPayment from './OrderWithPayment';\nimport useMediaQuery from '@material-ui/core/useMediaQuery';\n\nconst NewOrderDialog = ({ open, setOpen, request, onComplete, onClose }) => {\n\tconst { t } = useTranslation();\n\tconst [creating, setCreating] = useState(false);\n\tconst [order, setOrder] = useState(null);\n\tconst isMobile = useMediaQuery(theme => theme.breakpoints.down('xs'), { noSsr: true });\n\n\tconst [dialogActions, setDialogActions] = useState(null);\n\n\tconst handleClose = () => {\n\t\tsetOpen(false);\n\t\tif (onClose) onClose();\n\t};\n\n\tconst reset = () => {\n\t\tsetDialogActions(null);\n\t};\n\n\tconst onCompleteHandler = order => {\n\t\tonComplete(order);\n\t};\n\n\treturn (\n\t\t reset()}\n\t\t\tmaxWidth='lg'\n\t\t\tfullScreen={isMobile}\n\t\t\tfullWidth\n\t\t>\n\t\t\t\n\t\t\t\t{t('new_order_title')}\n\t\t\t \n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t{!order &&\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t\t}\n\t\t\t\t\t\t{order && \n\t\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t\t}\n\t\t\t\t\t \n\t\t\t\t \n\t\t\t \n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{t('close_btn')}\n\t\t\t\t \n\t\t\t\t{dialogActions}\n\t\t\t \n\t\t \n\t);\n};\n\nexport default NewOrderDialog;\n\nNewOrderDialog.propTypes = {\n\topen: PropTypes.bool.isRequired,\n\trequest: PropTypes.string.isRequired,\n\tsetOpen: PropTypes.func.isRequired,\n\tonComplete: PropTypes.func.isRequired,\n\tonClose: PropTypes.func\n};\n","import React from 'react';\nimport RichAlertTrans from '../../core/feedback/RichAlertTrans';\n\nconst ShellWindowsOsWarning = () => {\n\treturn (\n\t\t \n\t);\n};\n\nexport default ShellWindowsOsWarning;\n\nexport const isShellWindowsOSWarningNeeded = (shell, os) => {\n\t// Only for windows\n\tif(!os) return false;\n\tif (os.Family !== 'windows') return false;\n\n\t// Only if the shell has basic, lite, or none plan\n\treturn !(!!shell && !['lite', 'basic'].includes(shell.Catalog_Product['Description.AuthorCode']));\n};\n","import PropTypes from 'prop-types';\nimport React, { useEffect, useState } from 'react';\nimport DialogTitle from '@material-ui/core/DialogTitle';\nimport DialogContent from '@material-ui/core/DialogContent';\nimport DialogActions from '@material-ui/core/DialogActions';\nimport Button from '../../core/input/Button';\nimport Dialog from '@material-ui/core/Dialog';\nimport { Trans, useTranslation } from 'react-i18next';\nimport { Grid, Typography } from '@material-ui/core';\nimport { useShellSetInitialOS } from '@karpeleslab/klb-react-services';\nimport OSSelector from '../OperatingSystem/Selector/OSSelector';\nimport ModeCheck from '../../layout/Mode/ModeCheck';\nimport SSHKeyWarning from './Reinstall/SSHKeyWarning';\nimport ShellKeychainSelector from '../../core/input/ShellKeychainSelector';\nimport { useShellHasLicense } from '../../../hooks/useShellLicense';\nimport SelectOsLicenseInfo from './License/SelectOSLicenseInfo';\nimport NewOrderDialog from '../Order/order/NewOrderDialog';\nimport ShellWindowsOsWarning, { isShellWindowsOSWarningNeeded } from './ShellWindowsOSWarning';\n\nconst ShellSetInitialOSDialog = ({ open, setOpen, shell, setShell, onComplete }) => {\n\tconst { t } = useTranslation();\n\tconst [doSetOs, loading] = useShellSetInitialOS(shell.Shell__);\n\tconst [os, setOs] = useState(null);\n\tconst [keychain, setKeychain] = useState('none');\n\tconst [hasLicense, setHasLicense] = useState(false);\n\tconst [fetch, loadingLicense] = useShellHasLicense(shell.Shell__);\n\tconst [saveEnabled, setSaveEnabled] = useState(false);\n\n\t// Used when an order is needed\n\tconst [orderRequest, setOrderRequest] = useState(null);\n\tconst [showOrder, setShowOrder] = useState(false);\n\n\tuseEffect(() => {\n\t\tif (!os || !os.Catalog_Product__) {\n\t\t\tsetHasLicense(true);\n\t\t\treturn;\n\t\t}\n\n\t\t// Used to reset the state of the selected license\n\t\tsetHasLicense(false);\n\n\t\tfetch(os.Catalog_Product['Shell.LicenseType']).then(setHasLicense);\n\t}, [setHasLicense, os]);\n\n\tuseEffect(() => {\n\t\tif (!os || os === 'none') {\n\t\t\tsetSaveEnabled(false);\n\t\t\treturn;\n\t\t}\n\n\t\t// Check for license\n\t\tif (os.Catalog_Product) {\n\t\t\tif (loadingLicense || !hasLicense) {\n\t\t\t\tsetSaveEnabled(false);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// We need to require an keychain has been set only when the OS is a server\n\t\tif (os.Purpose !== 'server') {\n\t\t\tsetSaveEnabled(true);\n\t\t\treturn;\n\t\t}\n\n\t\tsetSaveEnabled(!!keychain && keychain !== 'none');\n\n\t}, [os, keychain, setSaveEnabled, loadingLicense, hasLicense]);\n\n\tconst handleClose = () => {\n\t\tsetOpen(false);\n\t};\n\n\tconst onOrderComplete = () => {\n\t\tsetShowOrder(false);\n\t\tsetOrderRequest(null);\n\n\t\tfetch(os.Catalog_Product['Shell.LicenseType']).then(setHasLicense);\n\t};\n\n\tconst handleBuyLicense = e => {\n\t\te.preventDefault();\n\t\tconst productId = os.Catalog_Product__;\n\t\tconst shellId = shell.Shell__;\n\n\t\tconst urlParams = `${productId},shell=${shellId}`;\n\n\t\tsetOrderRequest(urlParams);\n\t\tsetShowOrder(true);\n\t};\n\n\tconst handleConfirm = () => {\n\t\tconst k = keychain === 'none' ? null : keychain;\n\n\t\tdoSetOs(os.Shell_OS__, k)\n\t\t\t.then(shell => {\n\t\t\t\tsetShell(shell);\n\t\t\t\treturn shell;\n\t\t\t})\n\t\t\t.then(onComplete)\n\t\t\t.then(handleClose);\n\t};\n\n\treturn (\n\t\t<>\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\tsample \n\t\t\t\t\t\tsample \n\t\t\t\t\t \n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t{t('shell_os_selector_label')}\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t\t\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t \n\t\t\t\t\t\t\n\t\t\t\t\t\t{isShellWindowsOSWarningNeeded(shell, os) &&\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t{(os && os.Catalog_Product__) &&\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t }\n\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t{t('shell_initial_config_ssh_title')}\n\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t{t('close_btn')}\n\t\t\t\t\t \n\t\t\t\t\t\n\t\t\t\t\t\t{t('save_btn')}\n\t\t\t\t\t \n\t\t\t\t \n\t\t\t \n\t\t\t{orderRequest &&\n\t\t\t \n\t\t\t}\n\t\t>\n\t);\n};\n\nexport default ShellSetInitialOSDialog;\n\nShellSetInitialOSDialog.propTypes = {\n\tonComplete: PropTypes.func.isRequired,\n\topen: PropTypes.bool.isRequired,\n\tsetOpen: PropTypes.func.isRequired,\n\tsetShell: PropTypes.func.isRequired,\n\tshell: PropTypes.object.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React, { cloneElement, useState } from 'react';\nimport ShellSetInitialOSDialog from './ShellSetInitialOSDialog';\n\nconst ShellOpenWrapper = ({ shell, setShell, children, disabled = false, callback }) => {\n\tconst [showSelectOs, setShowSelectOs] = useState(false);\n\n\tconst openShell = s => {\n\t\tif (callback) callback(s);\n\t\telse window.open(`${process.env.REACT_APP_VIEW_SHELL_URL}/?id=${shell.Shell__}`);\n\t};\n\n\tconst onClickHandler = () => {\n\t\tif (disabled) return;\n\t\tif (shell.Shell_OS__)\n\t\t\topenShell(shell);\n\t\telse\n\t\t\tsetShowSelectOs(true);\n\n\t};\n\treturn (\n\t\t<>\n\t\t\t{cloneElement(children, { onClick: onClickHandler })}\n\t\t\t{shell && }\n\t\t>\n\t);\n};\n\nexport default ShellOpenWrapper;\n\nShellOpenWrapper.propTypes = {\n\tcallback: PropTypes.func,\n\tchildren: PropTypes.node.isRequired,\n\tdisabled: PropTypes.bool,\n\tsetShell: PropTypes.func.isRequired,\n\tshell: PropTypes.object.isRequired\n};\n","import React from 'react';\nimport makeStyles from '@material-ui/core/styles/makeStyles';\nimport PropTypes from 'prop-types';\n\nconst useStyles = makeStyles(() => {\n\tconst variants = [\n\t\t{ variant: '1x1', ratio: 1 },\n\t\t{ variant: '4x3', ratio: 1.3333 },\n\t];\n\n\tconst sizes = [\n\t\t{ size: 'small', height: 16 },\n\t\t{ size: 'medium', height: 32 },\n\t\t{ size: 'large', height: 48 },\n\t\t{ size: 'x-large', height: 64 }\n\t];\n\n\tlet c = {\n\t\t'wrapper': {\n\t\t\tposition: 'relative',\n\t\t}\n\t};\n\tvariants.forEach((v) => {\n\t\tsizes.forEach((s) => {\n\t\t\tc['flag-' + v.variant + '-' + s.size] = {\n\t\t\t\twidth: (s.height * v.ratio) + 'px',\n\t\t\t\theight: s.height + 'px',\n\t\t\t\tborder: '1px solid #cacaca;',\n\t\t\t\t'&.disabled': {\n\t\t\t\t\tfilter: 'grayscale(100%)'\n\t\t\t\t},\n\t\t\t\t'&.rounded': {\n\t\t\t\t\tborderRadius: '50%',\n\t\t\t\t}\n\t\t\t};\n\t\t\tc['wrapper-' + v.variant + '-' + s.size] = {\n\t\t\t\twidth: (s.height * v.ratio) + 'px',\n\t\t\t\theight: s.height + 'px',\n\t\t\t\t'&.rounded': {\n\t\t\t\t\toverflow: 'hidden'\n\t\t\t\t}\n\t\t\t};\n\t\t});\n\t});\n\n\treturn c;\n\n});\n\n\nconst Flag = React.forwardRef((props, ref) => {\n\tconst { code, ratio = '4x3', size = 'medium', disabled = false, rounded = false, alt = null } = props;\n\tconst classes = useStyles();\n\treturn (\n\t\t\n\t\t\t
\n\t\t
\n\t);\n});\n\nFlag.propTypes = {\n\tcode: PropTypes.string.isRequired,\n\talt: PropTypes.string,\n\tratio: PropTypes.oneOf(['4x3', '1x1']),\n\tsize: PropTypes.oneOf(['small', 'medium', 'large', 'x-large']),\n\tdisabled: PropTypes.bool,\n\trounded: PropTypes.bool,\n};\n\nFlag.displayName = 'Flag';\n\nexport default Flag;\n","import moment from 'moment';\n\nexport const formatShellExpireDate = (shell) => {\n\tif (!shell.Created || !shell.Expires.iso) {\n\t\treturn '';\n\t}\n\treturn moment(shell.Expires.iso).format('ll');\n};\n\n\nexport const isExpired = (shell) => {\n\tif (shell.Status === 'expired') return true;\n\treturn !!(shell.Expires && moment(parseInt(shell.Expires.unixms)) < moment());\n};\n\nexport const isShellValid = (shell) => {\n\tif (shell.Timer_Enabled && shell.Timer_Balance <= 0) return false;\n\treturn !isExpired(shell);\n};\n\nexport const isShellCanBeStarted = (shell) => {\n\treturn isShellValid(shell) && shell.State !== 'preparing';\n};\n\nexport const getPrice = (item, forceShowMonthly, isCustom, unit) => {\n\tlet p = item[forceShowMonthly ? 'Price.Monthly' : 'Price'];\n\tif (isCustom) {\n\t\tp = '$' + p.value_disp * unit;\n\t} else {\n\t\tp = p.display;\n\t}\n\n\treturn p;\n};\n\nexport const isCustomPlan = (plan) => {\n\treturn plan['Description.AuthorCode'] === 'custom';\n};\n\nexport const isYearly = (plan) => {\n\treturn plan['Basic.ServiceLifetime'] === '1y';\n};\n\nexport const isSamePlanType = (p1, p2) => {\n\treturn p1['Description.AuthorCode'] === p2['Description.AuthorCode'];\n};\n","export default __webpack_public_path__ + \"static/media/lp-plan-01.ef6cdff0.png\";","export default __webpack_public_path__ + \"static/media/lp-plan-02.c39f7a7c.png\";","export default __webpack_public_path__ + \"static/media/lp-plan-03.655f65c2.png\";","export default __webpack_public_path__ + \"static/media/lp-plan-04.adfcd1d7.png\";","export default __webpack_public_path__ + \"static/media/lp-plan-05.177aa524.png\";","import { useCallback, useEffect, useState } from 'react';\nimport { useCatalogProductsSearch } from '@karpeleslab/klb-react-services';\nimport GRAPHIC_SHELL_LITE from '../assets/img/plans/lp-plan-01.png';\nimport GRAPHIC_SHELL_BASIC from '../assets/img/plans/lp-plan-02.png';\nimport GRAPHIC_SHELL_PRO from '../assets/img/plans/lp-plan-03.png';\nimport GRAPHIC_SHELL_PLUS from '../assets/img/plans/lp-plan-04.png';\nimport GRAPHIC_SHELL_CUSTOM from '../assets/img/plans/lp-plan-05.png';\nimport { isYearly } from '../utils/shell';\n\nexport const CATALOG_PRODUCT_SHELL_IP = 'cpr-stzkrd-q5lr-cwdb-4dir-kwfpjn6m';\n\nexport const SHELL_REBOOT_ENABLE_STATES = ['running', 'paused'];\nexport const SHELL_START_ENABLE_STATES = ['paused', 'crashed', 'shutoff', 'shutdown', 'nostate', 'pmsuspended', 'unknown'];\nexport const SHELL_STOP_ENABLE_STATES = ['running', 'paused', 'crashed'];\n\nexport const UNIT_CPU = 0.25;\nexport const UNIT_RAM = 512;\nexport const UNIT_HDD = 10;\n\nexport const SHELL_OS_ICON_VARIATION = 'strip&scale_crop=285x285&format=png';\n\nexport const SHELL_PLANS_SEARCH_QUERY = {\n\tquery: {\n\t\t'Description.Type': 'shells_plan'\n\t},\n\tsort: 'Basic.Priority:asc'\n};\n\nexport const isShellYearly = (shell) => {\n\treturn isYearly(shell.Catalog_Product);\n};\n\nexport const getShellGraphic = type => {\n\tswitch (type) {\n\t\tcase 'lite':\n\t\t\treturn GRAPHIC_SHELL_LITE;\n\t\tcase 'basic':\n\t\t\treturn GRAPHIC_SHELL_BASIC;\n\t\tcase 'plus':\n\t\t\treturn GRAPHIC_SHELL_PLUS;\n\t\tcase 'pro':\n\t\t\treturn GRAPHIC_SHELL_PRO;\n\t\tcase 'custom':\n\t\t\treturn GRAPHIC_SHELL_CUSTOM;\n\t\tdefault :\n\t\t\treturn GRAPHIC_SHELL_LITE;\n\t}\n};\n\nexport const useShellPlans = () => {\n\tconst [plans, setPlans] = useState(null);\n\tconst [, fetchPlans] = useCatalogProductsSearch();\n\n\tconst refresh = useCallback(\n\t\tdata => {\n\t\t\tif (data) {\n\t\t\t\tsetPlans({ ...(plans ?? {}), data: data });\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\treturn fetchPlans(SHELL_PLANS_SEARCH_QUERY)\n\t\t\t\t.then(({ data }) => {\n\t\t\t\t\tsetPlans(data);\n\t\t\t\t})\n\t\t\t\t.catch(e => {\n\t\t\t\t\tsetPlans({ error: e });\n\t\t\t\t});\n\t\t}\n\t\t, [plans]); //eslint-disable-line\n\n\tuseEffect(() => {\n\t\trefresh();\n\t}, []); //eslint-disable-line\n\n\treturn [plans, refresh];\n};\n","import PropTypes from 'prop-types';\nimport React from 'react';\nimport { SHELL_STOP_ENABLE_STATES } from '../../../../hooks/useShells';\nimport PowerSettingsNewIcon from '@material-ui/icons/PowerSettingsNew';\nimport SettingsIcon from '@material-ui/icons/Settings';\nimport ReportIcon from '@material-ui/icons/Report';\nimport { isExpired, isShellValid } from '../../../../utils/shell';\nimport { useTheme } from '@material-ui/core';\nimport makeStyles from '@material-ui/core/styles/makeStyles';\nimport Tooltip from '@material-ui/core/Tooltip';\nimport { useTranslation } from 'react-i18next';\n\n\nconst useStyles = makeStyles(() => {\n\treturn {\n\t\tosIcon: {\n\t\t\t'&:hover':\n\t\t\t\t{\n\t\t\t\t\tcursor: 'pointer',\n\t\t\t\t\topacity: '0.7',\n\t\t\t\t}\n\t\t}\n\t};\n});\n\nconst ShellStateIcon = ({ shell, size = 'medium' }) => {\n\tconst classes = useStyles();\n\tconst theme = useTheme();\n\tconst { t } = useTranslation();\n\tlet component = null;\n\tlet title = '';\n\n\tif (!isShellValid(shell)) {\n\t\tcomponent = ;\n\n\t\ttitle = isExpired(shell) ? t('shell_expired_tooltip') : t('shell_time_allowance_tooltip');\n\t} else if (SHELL_STOP_ENABLE_STATES.includes(shell.State)) {\n\t\tcomponent = ;\n\t\ttitle = t(`shell_status_${shell.State}`);\n\t} else if (shell.State !== 'preparing') {\n\t\tcomponent = ;\n\t\ttitle = t('shell_status_shutdown');\n\t} else {\n\t\tcomponent = ;\n\t\ttitle = t('shell_preparing_tooltip');\n\n\t}\n\n\treturn (\n\t\t\n\t\t\t{component}\n\t\t );\n};\n\nexport default ShellStateIcon;\n\nShellStateIcon.propTypes = {\n\tshell: PropTypes.object.isRequired,\n\tsize: PropTypes.string\n};\n","import PropTypes from 'prop-types';\nimport React from 'react';\nimport makeStyles from '@material-ui/core/styles/makeStyles';\nimport ShellOpenWrapper from '../ShellOpenWrapper';\nimport Flag from '../../../core/data/Flag/Flag';\nimport { useHistory } from 'react-router';\nimport { getShellViewRoute } from '../../../RouteController/Factory';\nimport { isShellCanBeStarted } from '../../../../utils/shell';\nimport Grid from '@material-ui/core/Grid';\nimport defaultIcon from '../../../../assets/img/shells_icon_white.svg';\nimport ShellStateIcon from './ShellStateIcon';\nimport { useTranslation } from 'react-i18next';\nimport Tooltip from '@material-ui/core/Tooltip';\nimport { SHELL_OS_ICON_VARIATION } from '../../../../hooks/useShells';\nimport Img from '../../../core/data/Image/Img';\n\n\nconst useStyles = makeStyles(() => {\n\treturn {\n\t\tosIcon: {\n\t\t\t'&:hover':\n\t\t\t\t{\n\t\t\t\t\tcursor: 'pointer',\n\t\t\t\t\topacity: '0.7',\n\t\t\t\t}\n\t\t}\n\t};\n});\n\nconst ShellPicture = ({ shell, setShell, flagSize = 'medium', disabled = false, stateSize = undefined, ...rest }) => {\n\tconst classes = useStyles();\n\tconst { t } = useTranslation();\n\n\tconst history = useHistory();\n\n\tconst getPicture = () => {\n\t\tif (!shell || !shell.OS || !shell.OS.Media_Image)\n\t\t\treturn defaultIcon; // Todo, replace with an appropriate image\n\n\t\tif (SHELL_OS_ICON_VARIATION in shell.OS.Media_Image)\n\t\t\treturn shell.OS.Media_Image[SHELL_OS_ICON_VARIATION];\n\n\t\treturn shell.OS.Media_Image.Url;\n\t};\n\n\tconst onOSSet = shell => {\n\t\tif (shell.State === 'preparing') {\n\t\t\t// We need to force to go the shell page to display the message\n\t\t\thistory.push(getShellViewRoute(shell.Shell__));\n\t\t} else {\n\t\t\twindow.open(`${process.env.REACT_APP_VIEW_SHELL_URL}/?id=${shell.Shell__}`);\n\t\t}\n\t};\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t \n\n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t\t\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t \n\n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default ShellPicture;\n\nShellPicture.propTypes = {\n\tdisabled: PropTypes.bool,\n\tflagSize: PropTypes.string,\n\tsetShell: PropTypes.func,\n\tshell: PropTypes.object,\n\tstateSize: PropTypes.any\n};\n","import PropTypes from 'prop-types';\nimport React, { useEffect } from 'react';\nimport ShellOpenWrapper from '../ShellOpenWrapper';\nimport { IconButton } from '@material-ui/core';\nimport { PlayArrow } from '@material-ui/icons';\nimport Tooltip from '@material-ui/core/Tooltip';\nimport { useTranslation } from 'react-i18next';\nimport { useShellStart } from '@karpeleslab/klb-react-services';\nimport { SHELL_START_ENABLE_STATES } from '../../../../hooks/useShells';\n\nconst ShellActionStart = ({ setShell, shell, setLoading, disabled = false }) => {\n\tconst { t } = useTranslation();\n\tconst [start, starting] = useShellStart(shell.Shell__);\n\n\tuseEffect(() => {\n\t\tsetLoading(starting);\n\t}, [starting]);\n\n\tconst startHandler = s => {\n\t\tstart().then(() => setShell({ ...s, State: 'running' }));\n\t};\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default ShellActionStart;\n\nShellActionStart.propTypes = {\n\tdisabled: PropTypes.bool,\n\tsetLoading: PropTypes.func.isRequired,\n\tsetShell: PropTypes.func.isRequired,\n\tshell: PropTypes.object.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React from 'react';\nimport Dialog from '@material-ui/core/Dialog';\nimport DialogTitle from '@material-ui/core/DialogTitle';\nimport DialogContent from '@material-ui/core/DialogContent';\nimport DialogContentText from '@material-ui/core/DialogContentText';\nimport DialogActions from '@material-ui/core/DialogActions';\nimport { Trans, useTranslation } from 'react-i18next';\nimport RichAlert from '../../core/feedback/RichAlert';\nimport Button from '../../core/input/Button';\n\n\nconst ShellActionConfirmationDialog = ({ open, setOpen, actionName, action, loading }) => {\n\tconst { t } = useTranslation();\n\n\tconst handleClose = () => {\n\t\tsetOpen(false);\n\t};\n\n\tconst handleConfirm = () => {\n\t\taction(actionName)\n\t\t\t.finally(() => {\n\t\t\t\thandleClose();\n\t\t\t});\n\t};\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t{t(`shell_action_${actionName}_title`)}\n\t\t\t \n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\tsample\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t\tsample \n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t \n\t\t\t \n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{t('back_btn')}\n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t{t(`${actionName}_btn`)}\n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default ShellActionConfirmationDialog;\n\nShellActionConfirmationDialog.propTypes = {\n\taction: PropTypes.func,\n\tactionName: PropTypes.string,\n\tloading: PropTypes.bool.isRequired,\n\topen: PropTypes.bool.isRequired,\n\tsetOpen: PropTypes.func.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React, { useEffect, useState } from 'react';\nimport { IconButton } from '@material-ui/core';\nimport Tooltip from '@material-ui/core/Tooltip';\nimport { useTranslation } from 'react-i18next';\nimport { useShellStop } from '@karpeleslab/klb-react-services';\nimport StopIcon from '@material-ui/icons/Stop';\nimport ShellActionConfirmationDialog from '../ShellActionConfirmationDialog';\nimport { SHELL_STOP_ENABLE_STATES } from '../../../../hooks/useShells';\n\nconst ShellActionStop = ({ setShell, shell, setLoading, disabled = false }) => {\n\tconst { t } = useTranslation();\n\tconst [stop, stopping] = useShellStop(shell.Shell__);\n\tconst [showConfirm, setShowConfirm] = useState(false);\n\n\tuseEffect(() => {\n\t\tsetLoading(stopping);\n\t}, [stopping]);\n\n\tconst stopHandler = () => {\n\t\treturn stop().then(() => setShell({ ...shell, State: 'shutoff' }));\n\t};\n\n\treturn (\n\t\t<>\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t setShowConfirm(true)}\n\t\t\t\t\t>\n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t \n\t\t\t \n\t\t\t \n\t\t>\n\t);\n};\n\nexport default ShellActionStop;\n\nShellActionStop.propTypes = {\n\tdisabled: PropTypes.bool,\n\tsetLoading: PropTypes.func.isRequired,\n\tsetShell: PropTypes.func.isRequired,\n\tshell: PropTypes.object.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React, { useEffect, useState } from 'react';\nimport { IconButton } from '@material-ui/core';\nimport Tooltip from '@material-ui/core/Tooltip';\nimport { useTranslation } from 'react-i18next';\nimport { useShellReboot } from '@karpeleslab/klb-react-services';\nimport ShellActionConfirmationDialog from '../ShellActionConfirmationDialog';\nimport { SHELL_REBOOT_ENABLE_STATES } from '../../../../hooks/useShells';\nimport ReplayIcon from '@material-ui/icons/Replay';\n\nconst ShellActionReboot = ({ setShell, shell, setLoading, disabled = false }) => {\n\tconst { t } = useTranslation();\n\tconst [reboot, rebooting] = useShellReboot(shell.Shell__);\n\tconst [showConfirm, setShowConfirm] = useState(false);\n\n\tuseEffect(() => {\n\t\tsetLoading(rebooting);\n\t}, [rebooting]);\n\n\tconst rebootHandler = () => {\n\t\treturn reboot().then(() => setShell({ ...shell, State: 'running' }));\n\t};\n\n\treturn (\n\t\t<>\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t setShowConfirm(true)}\n\t\t\t\t\t>\n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t \n\t\t\t \n\t\t\t \n\t\t>\n\t);\n};\n\nexport default ShellActionReboot;\n\nShellActionReboot.propTypes = {\n\tdisabled: PropTypes.bool,\n\tsetLoading: PropTypes.func.isRequired,\n\tsetShell: PropTypes.func.isRequired,\n\tshell: PropTypes.object.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React, { useState } from 'react';\nimport ButtonGroup from '@material-ui/core/ButtonGroup';\nimport { useTranslation } from 'react-i18next';\nimport makeStyles from '@material-ui/core/styles/makeStyles';\nimport CircularProgress from '@material-ui/core/CircularProgress';\nimport ShellActionStart from './ShellActionStart';\nimport ShellActionStop from './ShellActionStop';\nimport ShellActionReboot from './ShellActionReboot';\n\n\nconst useStyles = makeStyles(theme => {\n\treturn {\n\t\tbuttonGroup: {\n\t\t\t'border': `solid 1px ${theme.palette.primary.main}`,\n\t\t\t'border-radius': '25px',\n\t\t},\n\t\tcontainer: {\n\t\t\tposition: 'relative'\n\t\t},\n\t\tloader: {\n\t\t\tposition: 'absolute',\n\t\t\ttop: 0,\n\t\t\tleft: 0,\n\t\t\tright: 0,\n\t\t\tbottom: 0,\n\t\t\tmargin: 'auto'\n\t\t}\n\t};\n});\n\nconst ShellAction = ({ shell, setShell, disabled = false }) => {\n\tconst { t } = useTranslation();\n\tconst classes = useStyles();\n\tconst [loading, setLoading] = useState(false);\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\n\t\t\t \n\t\t\t{loading && }\n\t\t \n\t);\n};\n\nexport default ShellAction;\n\nShellAction.propTypes = {\n\tdisabled: PropTypes.bool,\n\tsetShell: PropTypes.func.isRequired,\n\tshell: PropTypes.object.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React from 'react';\nimport { Grid } from '@material-ui/core';\nimport Typography from '@material-ui/core/Typography';\nimport LinearProgress from '@material-ui/core/LinearProgress';\nimport { useTranslation } from 'react-i18next';\nimport moment from 'moment';\nimport { useHumanTimeFormatter } from '../../../../hooks/useUtils';\nimport AllInclusiveOutlinedIcon from '@material-ui/icons/AllInclusiveOutlined';\n\nconst ShellUsage = ({ shell, light = false }) => {\n\tconst { t } = useTranslation();\n\n\tconst formatTime = useHumanTimeFormatter();\n\n\tif (!shell.Timer_Enabled)\n\t\treturn light ?\n\t\t\t'' :\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t \n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t{t('shell_unlimited_usage')}\n\t\t\t\t \n\t\t\t ;\n\n\n\treturn (\n\t\t(\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t{t('shell_timer_remaining', {\n\t\t\t\t\t\t\ttime: formatTime(shell.Timer_Balance)\n\t\t\t\t\t\t})}\n\t\t\t\t\t \n\t\t\t\t\t{!light && }\n\t\t\t\t\t{!light && \n\t\t\t\t\t\t{t('shell_timer_next_reset', {\n\t\t\t\t\t\t\tdate: shell.Timer_Next_Reset\n\t\t\t\t\t\t\t\t? moment(parseInt(shell.Timer_Next_Reset.unixms)).format('LL')\n\t\t\t\t\t\t\t\t: 'N/A'\n\t\t\t\t\t\t})}\n\t\t\t\t\t }\n\t\t\t\t \n\t\t\t \n\t\t)\n\t);\n};\n\nexport default ShellUsage;\n\nShellUsage.propTypes = {\n\tlight: PropTypes.bool,\n\tshell: PropTypes.object.isRequired\n};\n","import { useTranslation } from 'react-i18next';\n\nexport const useHumanTimeFormatter = () => {\n\tconst { t } = useTranslation();\n\treturn timeInSeconds => {\n\t\tconst secNum = parseInt(timeInSeconds, 10);\n\t\tlet hours = Math.floor((secNum ) / 3600);\n\t\tlet minutes = Math.floor((secNum - hours * 3600) / 60);\n\t\tlet seconds = secNum - hours * 3600 - minutes * 60;\n\n\t\tif (hours > 0)\n\t\t\treturn t('remaining_time_hours', { hours: hours, minutes: minutes });\n\t\tif (minutes > 0)\n\t\t\treturn t('remaining_time_minutes', {\n\t\t\t\tminutes: minutes,\n\t\t\t\tseconds: seconds\n\t\t\t});\n\t\tif (seconds > 0) return t('remaining_time_seconds', { seconds: seconds });\n\t\treturn t('remaining_time_none', { seconds: seconds });\n\t};\n};\n","import PropTypes from 'prop-types';\nimport React, { useState } from 'react';\nimport IconButton from '@material-ui/core/IconButton';\nimport MoreVertIcon from '@material-ui/icons/MoreVert';\nimport MoreHorizIcon from '@material-ui/icons/MoreHoriz';\nimport Menu from '@material-ui/core/Menu';\nimport MenuItem from '@material-ui/core/MenuItem';\nimport { NavLink } from 'react-router-dom';\nimport { getShellViewRoute } from '../../../../RouteController/Factory';\nimport ListItemIcon from '@material-ui/core/ListItemIcon';\nimport InfoOutlinedIcon from '@material-ui/icons/InfoOutlined';\nimport ListItemText from '@material-ui/core/ListItemText';\nimport { useTranslation } from 'react-i18next';\nimport AutorenewIcon from '@material-ui/icons/Autorenew';\nimport NewOrderDialog from '../../../Order/order/NewOrderDialog';\nimport useMediaQuery from '@material-ui/core/useMediaQuery';\n\nconst ActionMenu = ({ shell, refresh }) => {\n\tconst isMobile = useMediaQuery(theme => theme.breakpoints.down('sm'), { noSsr: true });\n\tconst needHorizontal = useMediaQuery('(max-width:1666px)', { noSsr: true });\n\n\n\tconst { t } = useTranslation();\n\tconst [menuAnchor, setMenuAnchor] = React.useState(null);\n\n\tconst [showOrder, setShowOrder] = useState(false);\n\n\tconst handleRenew = () => {\n\t\tsetShowOrder(true);\n\t};\n\n\tconst handleComplete = () => {\n\t\trefresh();\n\t\tcloseMenu();\n\t};\n\n\tconst openMenu = (event) => {\n\t\tsetMenuAnchor(event.currentTarget);\n\t};\n\n\tconst closeMenu = () => {\n\t\tsetMenuAnchor(null);\n\t};\n\n\treturn (\n\t\t<>\n\t\t\t\n\t\t\t\t{(!isMobile && needHorizontal) ? : }\n\t\t\t \n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t\t\n\t\t\t\t \n\t\t\t\t{!shell.User_Billing__ &&\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t\t \n\n\t\t\t\t \n\t\t\t\t}\n\t\t\t \n\t\t\t{\n\t\t\t\tshowOrder &&\n\t\t\t\t \n\t\t\t}\n\t\t>\n\t);\n};\n\nexport default ActionMenu;\n\nActionMenu.propTypes = {\n\trefresh: PropTypes.func.isRequired,\n\tshell: PropTypes.object.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React from 'react';\nimport { Grid } from '@material-ui/core';\nimport Button from '../../../../core/input/Button';\nimport VisibilityIcon from '@material-ui/icons/Visibility';\nimport { useTranslation } from 'react-i18next';\nimport ShellOpenWrapper from '../../ShellOpenWrapper';\nimport ActionMenu from './ActionMenu';\nimport { isShellCanBeStarted } from '../../../../../utils/shell';\n\nconst ShellTableAction = ({ shell, setShell, refresh, justify = 'flex-end', light = false }) => {\n\tconst { t } = useTranslation();\n\n\n\treturn (\n\t\t\n\t\t\t{!light && \n\t\t\t\t\n\t\t\t\t\t }\n\t\t\t\t\t>\n\t\t\t\t\t\t{t('view_btn')}\n\t\t\t\t\t\n\t\t\t\t \n\t\t\t }\n\n\t\t\t\n\t\t\t\t\n\t\t\t \n\t\t \n\t);\n};\n\nexport default ShellTableAction;\n\nShellTableAction.propTypes = {\n\tjustify: PropTypes.string,\n\tlight: PropTypes.bool,\n\tsetShell: PropTypes.func.isRequired,\n\trefresh: PropTypes.func.isRequired,\n\tshell: PropTypes.object.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React, { useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Grid } from '@material-ui/core';\nimport Button from '../../core/input/Button';\nimport { formatShellExpireDate } from '../../../utils/shell';\nimport NewOrderDialog from '../Order/order/NewOrderDialog';\nimport ListItemIcon from '@material-ui/core/ListItemIcon';\nimport AutorenewIcon from '@material-ui/icons/Autorenew';\nimport ListItemText from '@material-ui/core/ListItemText';\nimport MenuItem from '@material-ui/core/MenuItem';\n\nconst ShellExpireButton = ({ shell, refresh, light = false, inMenu = false, ...rest }) => {\n\tconst { t } = useTranslation();\n\tconst [showOrder, setShowOrder] = useState(false);\n\n\tif (shell.User_Billing__) {\n\t\treturn <>>;\n\t}\n\n\tconst handleRenew = e => {\n\t\tsetShowOrder(true);\n\t\tif (rest.onClick) rest.onClick(e);\n\t};\n\n\tconst handleComplete = () => {\n\t\trefresh();\n\t};\n\n\tif (inMenu) {\n\t\treturn (\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t \n\t\t\t\t \n\t\t\t\t \n\n\t\t\t\t{\n\t\t\t\t\tshowOrder &&\n\t\t\t\t\t \n\t\t\t\t}\n\t\t\t \n\t\t);\n\t}\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{\n\t\t\t\t\t\t!light ? t('shell_expire_renew_btn', { date: formatShellExpireDate(shell) }) : t('renew_btn')\n\t\t\t\t\t}\n\t\t\t\t \n\t\t\t \n\t\t\t{\n\t\t\t\tshowOrder &&\n\t\t\t\t \n\t\t\t}\n\t\t \n\t);\n};\n\nexport default ShellExpireButton;\n\nShellExpireButton.propTypes = {\n\tinMenu: PropTypes.bool,\n\tlight: PropTypes.bool,\n\trefresh: PropTypes.func.isRequired,\n\tshell: PropTypes.object.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React from 'react';\nimport RichAlert from '../../../core/feedback/RichAlert';\nimport { Trans } from 'react-i18next';\nimport moment from 'moment';\nimport { Grid } from '@material-ui/core';\nimport ShellExpireButton from '../ShellExpireButton';\nimport useMediaQuery from '@material-ui/core/useMediaQuery';\n\nconst ShellExpiredMessage = ({ shell, refresh, allowShortMode = false }) => {\n\tconst isMobile = useMediaQuery(theme => theme.breakpoints.down('sm'));\n\tconst isSmall = useMediaQuery(theme => theme.breakpoints.down('md'));\n\n\t// This is an edge case where the normal alert message wouldn't have space to be displayed\n\tif (!isMobile && isSmall && allowShortMode) {\n\t\treturn \n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\tsample \n\t\t\t\t\t\tsample \n\t\t\t\t\t \n\t\t\t\t \n\t\t\t \n\t\t\t{refresh ?\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t : undefined}\n\t\t ;\n\t}\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t : undefined}\n\t\t\t\t>\n\t\t\t\t\t\n\t\t\t\t\t\tsample \n\t\t\t\t\t\tsample \n\t\t\t\t\t \n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default ShellExpiredMessage;\n\nShellExpiredMessage.propTypes = {\n\tallowShortMode: PropTypes.bool,\n\trefresh: PropTypes.func,\n\tshell: PropTypes.object.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React, { useState } from 'react';\nimport { TableRow, Typography } from '@material-ui/core';\nimport useMediaQuery from '@material-ui/core/useMediaQuery';\nimport TableCell from '@material-ui/core/TableCell';\nimport ShellUsage from '../Subscription/ShellUsage';\nimport Grid from '@material-ui/core/Grid';\nimport ShellTableAction from './Action/ShellTableAction';\nimport ShellExpireButton from '../ShellExpireButton';\nimport Accordion from '@material-ui/core/Accordion';\nimport ExpandMoreIcon from '@material-ui/icons/ExpandMore';\nimport AccordionSummary from '@material-ui/core/AccordionSummary';\nimport AccordionDetails from '@material-ui/core/AccordionDetails';\nimport Chip from '@material-ui/core/Chip';\nimport ShellPicture from '../ShellPicture/ShellPicture';\nimport ShellAction from '../ShellAction/ShellAction';\nimport { useTranslation } from 'react-i18next';\nimport { formatShellExpireDate, isExpired } from '../../../../utils/shell';\nimport ShellExpiredMessage from '../Subscription/ShellExpiredMessage';\nimport ModeCheck from '../../../layout/Mode/ModeCheck';\n\nconst ShellListRow = ({ data, children, loading, idx, createSetShellHandler, refresh, ...rest }) => {\n\tconst isMobile = useMediaQuery(theme => theme.breakpoints.down('sm'), { noSsr: true });\n\tconst isXSmall = useMediaQuery('(max-width:433px)', { noSsr: true });\n\tconst [state, setState] = useState(JSON.parse(localStorage.getItem('shell-mobile-accordion-state') ?? '{}'));\n\tconst { t } = useTranslation();\n\n\tif (!isMobile || loading) {\n\t\treturn \n\t\t\t{children}\n\t\t ;\n\t}\n\n\tconst storeState = data => {\n\t\tlocalStorage.setItem('shell-mobile-accordion-state', JSON.stringify(data));\n\t\tsetState(data);\n\t};\n\n\tconst changeHandler = (e, expended) => {\n\t\tconst newState = {\n\t\t\t...JSON.parse(localStorage.getItem('shell-mobile-accordion-state') ?? '{}'),\n\t\t\t[data.Shell__]: expended\n\t\t};\n\t\tstoreState(newState);\n\t};\n\n\tconst isExpended = () => {\n\t\treturn data.Shell__ in state && state[data.Shell__] === true;\n\t};\n\n\treturn \n\t\t\n\t\t\t\n\t\t\t\t }\n\t\t\t\t\taria-controls={`panel${idx}a-content`}\n\t\t\t\t\tid={`panel${idx}a-header`}\n\t\t\t\t>\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t{data.Label} \n\n\t\t\t\t\t\t \n\t\t\t\t\t\t\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t \n\n\t\t\t\t\t \n\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t{isExpired(data) && }\n\t\t\t\t\t\t{!isExpired(data) && <>\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t \n\n\t\t\t\t\t\t\t{!data.User_Billing__ && \n\t\t\t\t\t\t\t\t{t('shell_expire_text', { date: formatShellExpireDate(data) })}\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t\t \n\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t \n\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t \n\n\t\t\t\t\t \n\t\t\t\t \n\t\t\t \n\t\t \n\t ;\n};\n\nexport default ShellListRow;\n\nShellListRow.propTypes = {\n\tchildren: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]).isRequired,\n\tcreateSetShellHandler: PropTypes.func,\n\trefresh: PropTypes.func,\n\tdata: PropTypes.object.isRequired,\n\tidx: PropTypes.number,\n\tloading: PropTypes.bool\n};\n","import withStyles from '@material-ui/core/styles/withStyles';\nimport Badge from '@material-ui/core/Badge';\nimport { Chip } from '@material-ui/core';\n\nexport const PlanBadge = withStyles(() => ({\n\tbadge: {\n\t\tbottom: '0',\n\t\tright: 'unset',\n\t\tleft: '50%',\n\t\ttransform: 'translate(-50%, -50%)',\n\t},\n}))(Badge);\n\n\nexport const PlanChip = withStyles(() => ({\n\troot: {\n\t\theight: '20px',\n\t},\n\tlabel: {\n\t\tfontSize: '0.75rem',\n\t\tfontWeight: '500',\n\t\tlineHeight: 1\n\t}\n}))(Chip);\n","import React, { useCallback } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport TableDefinition from '../../../core/data/table/TableDefinition';\nimport Table from '../../../core/data/table/Table';\nimport EmptyList from './EmptyList';\nimport ShellPicture from '../ShellPicture/ShellPicture';\nimport { Grid } from '@material-ui/core';\nimport ShellAction from '../ShellAction/ShellAction';\nimport ShellUsage from '../Subscription/ShellUsage';\nimport useMediaQuery from '@material-ui/core/useMediaQuery';\nimport ShellListRow from './ShellListRow';\nimport ShellTableAction from './Action/ShellTableAction';\nimport { formatShellExpireDate, isExpired } from '../../../../utils/shell';\nimport ShellExpiredMessage from '../Subscription/ShellExpiredMessage';\nimport { ADVANCED_MODE } from '../../../../context/ModeContext';\nimport { useIsMode } from '../../../../hooks/useIsMode';\nimport { useShells } from '@karpeleslab/klb-react-services';\nimport { useAutoRefresher } from '../../../../hooks/useAutoRefresher';\nimport { PlanChip } from '../ShellPicture/PlanBadge';\nimport { SHELL_OS_ICON_VARIATION } from '../../../../hooks/useShells';\n\nconst ShellsTable = () => {\n\tconst { t } = useTranslation();\n\tconst [shells, fetch, loading, setShell] = useShells();\n\n\tconst refresher = useCallback(() => {\n\t\tfetch(null, null, { silent: true });\n\t}, [fetch]);\n\n\n\tuseAutoRefresher(refresher);\n\n\tconst isMobile = useMediaQuery(theme => theme.breakpoints.down('sm'));\n\tconst isAdvanced = useIsMode(ADVANCED_MODE);\n\n\tconst createSetShellHandler = idx => shell => {\n\t\tsetShell(idx, shell);\n\t};\n\n\tconst tableDefStyle = {\n\t\twidth: isMobile ? '100%' : '150px',\n\t\t...(isMobile ? { borderBottom: 'unset', padding: '0px' } : {})\n\t};\n\n\treturn (\n\t\t}\n\t\t\tinitialFilters={\n\t\t\t\t{\n\t\t\t\t\tStatus: { '$in': ['valid', 'expired'] },\n\t\t\t\t\tsort: { Label: 'ASC', Created: 'ASC' },\n\t\t\t\t\timage_variation: [SHELL_OS_ICON_VARIATION]\n\t\t\t\t}\n\t\t\t}\n\t\t\tsearchKey='Label'\n\t\t\trowProps={{\n\t\t\t\trefresh: refresher,\n\t\t\t\tcreateSetShellHandler: createSetShellHandler\n\t\t\t}}\n\t\t\tRowComponent={ShellListRow}\n\t\t>\n\t\t\t\n\t\t\t\t{(shell, idx) => \n\t\t\t\t\t\n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t \n\t\t\t\t}\n\t\t\t \n\n\t\t\t{(!isMobile && isAdvanced) && \n\t\t\t\t{(shell, idx) =>\n\t\t\t\t\t \n\t\t\t\t}\n\t\t\t \n\t\t\t}\n\n\t\t\t{!isMobile && \n\t\t\t\t{(shell) => \n\t\t\t\t\t\n\t\t\t\t\t\t{shell.Label}\n\t\t\t\t\t \n\t\t\t\t\t\n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t \n\t\t\t\t}\n\t\t\t }\n\n\t\t\t{!isMobile &&\n\t\t\t\n\t\t\t\t{shell => {\n\t\t\t\t\tif (isExpired(shell))\n\t\t\t\t\t\treturn ;\n\t\t\t\t\telse\n\t\t\t\t\t\treturn \n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t{!shell.User_Billing__ && t('shell_expire_text', { date: formatShellExpireDate(shell) })}\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t ;\n\t\t\t\t}\n\t\t\t\t}\n\t\t\t }\n\n\t\t\t{!isMobile && \n\t\t\t\t{(shell, idx) => }\n\t\t\t \n\t\t\t}\n\t\t\n\t);\n};\n\nexport default ShellsTable;\n","import React from 'react';\nimport PageContainer from '../../components/layout/Container/PageContainer';\nimport { Grid } from '@material-ui/core';\nimport Toolbar from '../../components/core/typography/Toolbar';\nimport { useTranslation } from 'react-i18next';\nimport AddIcon from '@material-ui/icons/Add';\nimport Button from '../../components/core/input/Button';\nimport ShellsTable from '../../components/common/Shell/Table/ShellsTable';\nimport useMediaQuery from '@material-ui/core/useMediaQuery';\n\nconst ShellList = () => {\n\tconst { t } = useTranslation();\n\tconst isMobile = useMediaQuery(theme => theme.breakpoints.down('xs'));\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t }\n\t\t\t\t\t\t\tvariant='contained'\n\t\t\t\t\t\t\tcolor='primary'\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{t('order_new_shell_btn')}\n\t\t\t\t\t\t\n\t\t\t\t\t \n\t\t\t\t \n\n\t\t\t\t\n\t\t\t\t\t \n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default ShellList;\n","import PropTypes from 'prop-types';\nimport React from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Grid } from '@material-ui/core';\nimport List from '@material-ui/core/List';\nimport ListItem from '@material-ui/core/ListItem';\nimport ListItemText from '@material-ui/core/ListItemText';\nimport ListItemIcon from '@material-ui/core/ListItemIcon';\nimport PowerSettingsNewIcon from '@material-ui/icons/PowerSettingsNew';\nimport RoomIcon from '@material-ui/icons/Room';\nimport AlbumIcon from '@material-ui/icons/Album';\nimport PersonIcon from '@material-ui/icons/Person';\nimport { PlanChip } from './ShellPicture/PlanBadge';\nimport CardMembershipIcon from '@material-ui/icons/CardMembership';\n\nconst ShellInfo = ({ shell }) => {\n\tconst { t } = useTranslation();\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t{t('shell_plan')}\n\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t}/>\n\t\t\t\t\t \n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t
\n\t\t\t \n\t\t \n\t);\n};\n\nexport default ShellInfo;\n\nShellInfo.propTypes = {\n\tshell: PropTypes.object.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React, { useEffect, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport makeStyles from '@material-ui/core/styles/makeStyles';\nimport { getPrice } from '../../../../utils/shell';\n\nconst useStyles = makeStyles(() => ({\n\tprice: {\n\t\tfontSize: '17px',\n\t\tmargin: '0 0 5px',\n\t},\n}));\n\nconst ShellPlanListItemPrice = ({ item, unit, forceShowMonthly = false, isCustom = false, ...rest }) => {\n\tconst { t } = useTranslation();\n\tconst classes = useStyles();\n\tconst [price, setPrice] = useState(null);\n\n\tuseEffect(() => {\n\t\tsetPrice(getPrice(item, forceShowMonthly, isCustom, unit));\n\t}, [item, unit, isCustom, forceShowMonthly, setPrice]);\n\n\treturn (\n\t\t\n\t\t\t{price}\n\t\t\t{t('shell_price_by_month')} \n\t\t
\n\t);\n};\n\nexport default ShellPlanListItemPrice;\n\nShellPlanListItemPrice.propTypes = {\n\tforceShowMonthly: PropTypes.bool,\n\tisCustom: PropTypes.bool,\n\titem: PropTypes.object,\n\tunit: PropTypes.number\n};\n","import PropTypes from 'prop-types';\nimport React from 'react';\nimport ListItem from '@material-ui/core/ListItem';\nimport ListItemIcon from '@material-ui/core/ListItemIcon';\nimport ListItemText from '@material-ui/core/ListItemText';\nimport makeStyles from '@material-ui/core/styles/makeStyles';\nimport useMediaQuery from '@material-ui/core/useMediaQuery';\nimport ShellPlanListItemPrice from './ShellPlanListItemPrice';\nimport { isCustomPlan } from '../../../../utils/shell';\n\nconst useStyles = makeStyles(theme => ({\n\n\troot: {\n\t\tborder: '1px solid #B0E170',\n\t\tpadding: theme.spacing(2),\n\t\tmarginBottom: theme.spacing(1),\n\t\t// background: 'white',\n\t\tminHeight: '105px',\n\t},\n\tdisabled: {\n\t\tfilter: 'grayscale(1)'\n\t},\n\tselected: {\n\t\tbackground: '#B0E170!important',\n\t},\n\n\toldPrice: {\n\t\tcolor: theme.palette.secondary.main,\n\t\ttextDecoration: 'line-through',\n\t\tfontSize: '14px',\n\t\t'fontWeight': 400,\n\t},\n\tdiscountWrapper: {\n\t\tdisplay: 'flex',\n\t\ttextAlign: 'center',\n\t\tjustifyContent: 'center',\n\t\talignItems: 'center',\n\t\tflexWrap: 'wrap'\n\t},\n\tdiscount: {\n\t\tbackground: '#fddce0',\n\t\tpadding: '0 4px',\n\t\tborderRadius: '6px',\n\t\tfontSize: '12px',\n\t\tfontWeight: 400,\n\t\tmargin: 0,\n\t\tcolor: '#f64f64'\n\t}\n}));\n\n\nconst ShellPlanListItem = ({ plan, unit = 1, graphic, forceShowMonthly = false, ...rest }) => {\n\tconst classes = useStyles();\n\tconst isMobile = useMediaQuery(theme => theme.breakpoints.down('xs'));\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t \n\t\t\t \n\t\t\t\n\t\t\t\n\t\t\t\t \n\t\t\t
\n\t\t \n\t);\n};\n\nexport default ShellPlanListItem;\n\nShellPlanListItem.propTypes = {\n\tforceShowMonthly: PropTypes.bool,\n\tgraphic: PropTypes.string.isRequired,\n\tplan: PropTypes.object.isRequired,\n\tselected: PropTypes.bool,\n\tunit: PropTypes.number\n};\n","import { withStyles } from '@material-ui/core';\nimport Tooltip from '@material-ui/core/Tooltip';\n\nexport const ShellPlanCustomTooltip = withStyles(theme => ({\n\ttooltip: {\n\t\tbackgroundColor: '#f5f5f9',\n\t\tcolor: 'rgba(0, 0, 0, 0.87)',\n\t\tmaxWidth: 220,\n\t\tfontSize: theme.typography.pxToRem(12),\n\t\tborder: '1px solid #dadde9'\n\t}\n}))(Tooltip);\n","import PropTypes from 'prop-types';\nimport React, { useState } from 'react';\nimport makeStyles from '@material-ui/core/styles/makeStyles';\nimport { useTranslation } from 'react-i18next';\nimport Grid from '@material-ui/core/Grid';\n\nimport cpuImg from '../../../../assets/img/plans/chip.png';\nimport hddImg from '../../../../assets/img/plans/disk.png';\nimport ramImg from '../../../../assets/img/plans/memory.png';\nimport timeAllowanceImg from '../../../../assets/img/plans/hours.png';\nimport ClickAwayListener from '@material-ui/core/ClickAwayListener';\nimport { ShellPlanCustomTooltip } from './ShellPlanCustomTooltip';\nimport Typography from '@material-ui/core/Typography';\nimport { UNIT_CPU, UNIT_HDD, UNIT_RAM } from '../../../../hooks/useShells';\nimport HelpOutlineOutlinedIcon from '@material-ui/icons/HelpOutlineOutlined';\nimport * as NumericInput from 'react-numeric-input';\nimport { Box } from '@material-ui/core';\nimport { useTheme } from '@material-ui/styles';\nimport { isCustomPlan } from '../../../../utils/shell';\n\nconst useStyles = makeStyles((theme) => ({\n\troot: {\n\t\tcolor: theme.palette.type === 'light' ? '#03222D' : '#fff',\n\t\tfontWeight: 'bold',\n\t\ttextAlign: 'center',\n\t\tmarginBottom: '12px',\n\t\tbackground: 'rgba(0, 0, 0, .1)'\n\t},\n\ttooltipImageWrapper: {\n\t\tcolor: theme.palette.type === 'light' ? '#03222D' : '#fff',\n\t\tfontWeight: 'bold',\n\t\tbackground: 'transparent',\n\t\tposition: 'relative'\n\t},\n\ttooltipImage: {\n\t\tfontSize: '14px',\n\t\tmarginTop: '-8px',\n\t\tposition: 'absolute',\n\t\ttop: '50%',\n\t\tright: '-15px',\n\t\tcolor: '#B0E170'\n\t},\n}));\n\nconst ShellPlanDetails = ({ selected, nbUnit, setNbUnit, minUnits, disabled = false }) => {\n\tconst { t } = useTranslation();\n\tconst classes = useStyles();\n\tconst theme = useTheme();\n\n\tconst [tooltips, setTooltips] = useState({\n\t\tcpu: false,\n\t\thdd: false,\n\t\tram: false,\n\t\ttime: false\n\t});\n\n\tconst handleOpenTooltip = tooltip =>\n\t\tsetTooltips({ ...tooltips, [tooltip]: true });\n\tconst handleClickAway = tooltip =>\n\t\tsetTooltips({ ...tooltips, [tooltip]: false });\n\n\tconst buildVcpu = selected => {\n\t\tswitch (selected['Description.AuthorCode']) {\n\t\t\tcase 'custom':\n\t\t\t\treturn Math.ceil(UNIT_CPU * nbUnit);\n\t\t\tdefault:\n\t\t\t\treturn Math.ceil(selected['Shell.Size'] * UNIT_CPU);\n\t\t}\n\t};\n\n\tconst buildTimeAllowance = selected => {\n\t\treturn parseInt(selected['Shell.Timer_Allowance']) / 3600;\n\t};\n\n\tconst buildHdd = selected => {\n\t\tswitch (selected['Description.AuthorCode']) {\n\t\t\tcase 'custom':\n\t\t\t\treturn UNIT_HDD * nbUnit;\n\t\t\tdefault:\n\t\t\t\treturn selected['Shell.Size'] * UNIT_HDD;\n\t\t}\n\t};\n\n\tconst buildRam = selected => {\n\t\tswitch (selected['Description.AuthorCode']) {\n\t\t\tcase 'custom':\n\t\t\t\treturn UNIT_RAM * nbUnit;\n\t\t\tdefault:\n\t\t\t\treturn selected['Shell.Size'] * UNIT_RAM;\n\t\t}\n\t};\n\n\tconst onChangeHandler = event => {\n\t\tsetNbUnit(event);\n\t};\n\n\tconst getMinUnitsValue = () => {\n\t\t// Minimum unit is 8 or the current plan number of unit\n\t\tif (!selected) {\n\t\t\treturn 1;\n\t\t}\n\n\t\tif (minUnits !== undefined)\n\t\t\treturn minUnits < 8 ? 8 : minUnits;\n\n\t\treturn isCustomPlan(selected) ? 8 : 1;\n\t};\n\n\n\tconst buildOtherField = selected => {\n\t\tswitch (selected['Description.AuthorCode']) {\n\t\t\tcase 'custom':\n\t\t\t\treturn (\n\t\t\t\t\t<>\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t{t('custom_shell_title')}\n\t\t\t\t\t\t
\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t{t('order_choose_number_units')} \n\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t{t('order_choose_number_units_desc')}\n\t\t\t\t\t\t\t
\n\t\t\t\t\t\t \n\t\t\t\t\t>\n\t\t\t\t);\n\t\t\tdefault:\n\t\t\t\treturn (\n\t\t\t\t\t<>\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t{selected['Basic.Name']}\n\t\t\t\t\t\t
\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t{selected['Description.CatchPhrase']}\n\t\t\t\t\t\t\t
\n\t\t\t\t\t\t \n\t\t\t\t\t>\n\t\t\t\t);\n\t\t}\n\t};\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t{t('selected_plan_vm_custom_following_specs')}\n\t\t\t\t\t
\n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t\t handleOpenTooltip('cpu')}\n\t\t\t\t\t\t\tonMouseEnter={() => handleOpenTooltip('cpu')}\n\t\t\t\t\t\t\tonMouseLeave={() => handleClickAway('cpu')}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t handleClickAway('cpu')}>\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t{t('cpu_tooltip')}\n\t\t\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t\t\t{t('cpu_tooltip_desc')}\n\t\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\tVCPU \n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t \n\t\t\t\t\t\t\n\t\t\t\t\t\t\t{buildVcpu(selected)}\n\t\t\t\t\t\t \n\t\t\t\t\t\n\t\t\t\t \n\n\t\t\t\t handleOpenTooltip('hdd')}\n\t\t\t\t\tonMouseEnter={() => handleOpenTooltip('hdd')}\n\t\t\t\t\tonMouseLeave={() => handleClickAway('hdd')}\n\t\t\t\t>\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t\t\n\t\t\t\t\t\t\t handleClickAway('hdd')}>\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t{t('hdd_tooltip')}\n\t\t\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t\t\t{t('hdd_tooltip_desc')}\n\t\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\tSSD \n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t \n\t\t\t\t\t\t\n\t\t\t\t\t\t\t{buildHdd(selected)} GB\n\t\t\t\t\t\t \n\t\t\t\t\t\n\t\t\t\t\n\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t\t handleOpenTooltip('ram')}\n\t\t\t\t\t\t\tonMouseEnter={() => handleOpenTooltip('ram')}\n\t\t\t\t\t\t\tonMouseLeave={() => handleClickAway('ram')}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t handleClickAway('ram')}>\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t{t('ram_tooltip')}\n\t\t\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t\t\t{t('ram_tooltip_desc')}\n\t\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\tRAM \n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t \n\t\t\t\t\t\t\n\t\t\t\t\t\t\t{buildRam(selected)} MB\n\t\t\t\t\t\t \n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t{selected['Shell.Timer_Allowance'] && (\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t handleOpenTooltip('time')}\n\t\t\t\t\t\t\t\tonMouseEnter={() => handleOpenTooltip('time')}\n\t\t\t\t\t\t\t\tonMouseLeave={() => handleClickAway('time')}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t handleClickAway('time')}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t{t('time_allowance_tooltip')}\n\t\t\t\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t\t\t\t{t('time_allowance_tooltip_desc')}\n\t\t\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\tTime allowance \n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t{t('shell_time_allowance', {\n\t\t\t\t\t\t\t\t\ttime: buildTimeAllowance(selected)\n\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t)}\n\n\t\t\t\t\n\t\t\t\t\t{buildOtherField(selected)}\n\t\t\t\t \n\t\t\t\n\n\t\t \n\t);\n};\n\nexport default ShellPlanDetails;\n\nShellPlanDetails.propTypes = {\n\tdisabled: PropTypes.bool,\n\tminUnits: PropTypes.number.isRequired,\n\tnbUnit: PropTypes.number.isRequired,\n\tselected: PropTypes.object.isRequired,\n\tsetNbUnit: PropTypes.func.isRequired\n};\n","export default \"data:image/png;base64,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\"","export default \"data:image/png;base64,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\"","export default \"data:image/png;base64,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\"","export default \"data:image/png;base64,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\"","export default __webpack_public_path__ + \"static/media/maxPlans.ffd048ef.svg\";","import React from 'react';\nimport { Trans, useTranslation } from 'react-i18next';\nimport Graphic from '../../../../assets/img/plans/maxPlans.svg';\nimport Empty from '../../../core/feedback/State/Empty';\n\nconst MaxPlan = () => {\n\tconst { t } = useTranslation();\n\treturn (\n\t\t\n\t\t\t\t\tsample \n\t\t\t\t\tsample \n\t\t\t\t\n\t\t\t}\n\t\t\tgraphic={Graphic}\n\t\t\taction={\n\t\t\t\t{\n\t\t\t\t\tcomponent: 'a',\n\t\t\t\t\ttitle: t('footer_link_contact'),\n\t\t\t\t\trel: 'noopener noreferrer',\n\t\t\t\t\ttarget: '_blank',\n\t\t\t\t\thref: process.env.REACT_APP_ZENDESK\n\t\t\t\t}\n\t\t\t}\n\t\t/>);\n};\n\nexport default MaxPlan;\n","import PropTypes from 'prop-types';\nimport React, { useCallback, useEffect, useState } from 'react';\nimport DialogTitle from '@material-ui/core/DialogTitle';\nimport DialogActions from '@material-ui/core/DialogActions';\nimport Button from '../../../core/input/Button';\nimport Dialog from '@material-ui/core/Dialog';\nimport { useTranslation } from 'react-i18next';\nimport { getShellGraphic, isShellYearly, useShellPlans } from '../../../../hooks/useShells';\nimport Loader from '../../../layout/Loader/Loader';\nimport Grid from '@material-ui/core/Grid';\nimport Tab from '@material-ui/core/Tab';\nimport Tabs from '@material-ui/core/Tabs';\nimport Panel from '../../../layout/Container/tab/Panel';\nimport { List } from '@material-ui/core';\nimport ShellPlanListItem from './ShellPlanListItem';\nimport ShellPlanDetails from './ShellPlanDetails';\nimport useMediaQuery from '@material-ui/core/useMediaQuery';\nimport { isCustomPlan, isYearly } from '../../../../utils/shell';\nimport MaxPlan from './MaxPlan';\nimport NewOrderDialog from '../../Order/order/NewOrderDialog';\n\n\nconst MONTHLY_TAB = 1;\nconst YEARLY_TAB = 0;\n\nconst ShellPlanSelectionDialog = ({ open, setOpen, shell, refresh }) => {\n\tconst { t } = useTranslation();\n\tconst [plans, fetchPlans] = useShellPlans();\n\n\t// We will use slightly more RAM but it will be easier to change the UI is there is plans or not, and be less cpu intensive\n\tconst [monthlyPlans, setMonthlyPlans] = useState([]);\n\tconst [yearlyPlans, setYearlyPlans] = useState([]);\n\n\tconst [selectedTab, setSelectedTab] = useState(isShellYearly(shell) ? YEARLY_TAB : MONTHLY_TAB);\n\tconst [selectedPlan, setSelectedPlan] = useState(null);\n\n\tconst isMobile = useMediaQuery(theme => theme.breakpoints.down('xs'));\n\n\tconst [nbUnit, setNbUnit] = useState(Math.max(8, shell.Size));\n\tconst [selectedProduct, setSelectedProduct] = useState(null);\n\n\t// Related to the cart\n\tconst [showOrder, setShowOrder] = useState(false);\n\tconst [request, setRequest] = useState(null);\n\n\t// Calling refresh() will change the shell and will trigger the plans to refresh thus to reconstruct the available list\n\t// refresh() is called when an upgrade payment is completed (see handleComplete)\n\tuseEffect(() => {\n\t\tfetchPlans();\n\t}, [shell]);\n\n\tuseEffect(() => {\n\t\tif (!plans || !plans.data) return;\n\t\tconst filtered = plans.data.filter(p => p.Catalog_Product__ === selectedPlan);\n\t\tif (!filtered || filtered.length < 1) setSelectedProduct(null);\n\t\telse setSelectedProduct(filtered[0]);\n\t}, [setSelectedProduct, plans, selectedPlan]);\n\n\tuseEffect(() => {\n\t\tif (!plans || !plans.data) return;\n\n\t\tsetMonthlyPlans(plans.data.filter(p => !isYearly(p) && isShown(p)));\n\t\tsetYearlyPlans(plans.data.filter(p => isYearly(p) && isShown(p)));\n\n\t}, [plans, setMonthlyPlans, setYearlyPlans]);\n\n\tconst init = useCallback(() => {\n\t\tsetShowOrder(false);\n\t\tsetRequest(null);\n\t\tsetSelectedPlan(null);\n\t\tsetSelectedTab(isShellYearly(shell) ? YEARLY_TAB : MONTHLY_TAB);\n\t}, [shell, setSelectedTab, setSelectedPlan]);\n\n\tuseEffect(() => {\n\t\tinit();\n\t}, [init]);\n\n\tconst handleClose = () => {\n\t\tsetOpen(false);\n\t};\n\n\tconst handleTabChange = (event, newValue) => {\n\t\tsetSelectedTab(newValue);\n\t};\n\n\tconst createSelectHandler = product => () => {\n\t\tsetSelectedPlan(product);\n\t};\n\n\tconst isSelected = product => {\n\t\treturn product === selectedPlan;\n\t};\n\n\tconst isShown = plan => {\n\t\tif (isCustomPlan(plan)) return true;\n\n\t\tif (plan['Shell.Size'] < shell.Size) return false;\n\n\t\t// Special hardcoded rule, that prevent to be able to upgrade to lite yearly when we are in basic monthly\n\t\t// Technically we could do it (because basic and lite plan are the same),\n\t\t// but in term of UX/marketing we consider the lite plan as an inferior plan\n\t\tif (\n\t\t\tplan['Description.AuthorCode'] === 'lite' &&\n\t\t\tisYearly(plan) &&\n\t\t\t!isShellYearly(shell) &&\n\t\t\tshell.Catalog_Product['Description.AuthorCode'] === 'basic'\n\t\t)\n\t\t\treturn false;\n\n\t\treturn parseFloat(plan['Price.Price'].value) > parseFloat(shell.Catalog_Product['Price.Price'].value);\n\t};\n\n\tconst handleRenew = () => {\n\t\tconst productId = selectedPlan;\n\t\tconst shellId = shell.Shell__;\n\n\t\tconst isCustom = isCustomPlan(selectedProduct);\n\n\t\tconst urlParams = `${productId},shell=${shellId}${\n\t\t\tisCustom ? `,shell_size=${nbUnit}` : ''\n\t\t},mode=upgrade`;\n\n\t\tsetRequest(urlParams);\n\t\tsetShowOrder(true);\n\t};\n\n\tconst handleComplete = () => {\n\t\trefresh();\n\t\thandleClose();\n\t};\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t{t('renew_shell_title')}\n\t\t\t \n\t\t\t\n\t\t\t\t{!plans &&
}\n\t\t\t\t{plans &&
\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t{(yearlyPlans.length > 0) &&\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t{(!isShellYearly(shell) && monthlyPlans.length > 0) &&\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t{yearlyPlans.length < 1 && }\n\t\t\t\t\t\t\t\t\t{yearlyPlans.length > 0 && \n\t\t\t\t\t\t\t\t\t\t{yearlyPlans.map(plan =>\n\t\t\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t
}\n\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t{(!isShellYearly(shell) && monthlyPlans.length > 0) &&\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t{monthlyPlans.map(plan =>\n\t\t\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t }\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t!!selectedProduct && \n\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t \n\t\t\t\t\t \n\n\t\t\t\t }\n\t\t\t
\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{t('close_btn')}\n\t\t\t\t \n\t\t\t\t{(yearlyPlans.length > 0 || !isShellYearly(shell)) &&\n\t\t\t\t\n\t\t\t\t\t{t('select_plan_bt')}\n\t\t\t\t }\n\t\t\t \n\n\t\t\t{\n\t\t\t\t(showOrder && request) &&\n\t\t\t\t \n\t\t\t}\n\n\t\t \n\t);\n};\n\nexport default ShellPlanSelectionDialog;\n\nShellPlanSelectionDialog.propTypes = {\n\topen: PropTypes.bool.isRequired,\n\tsetOpen: PropTypes.func.isRequired,\n\trefresh: PropTypes.func.isRequired,\n\tshell: PropTypes.object.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React, { useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Grid } from '@material-ui/core';\nimport Button from '../../core/input/Button';\nimport PublishIcon from '@material-ui/icons/Publish';\nimport ShellPlanSelectionDialog from './Plan/ShellPlanSelectionDialog';\n\nconst ShellUpgradeButton = ({ shell, refresh }) => {\n\tconst { t } = useTranslation();\n\tconst [showDialog, setShowDialog] = useState(false);\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t }\n\t\t\t\t\tsize='small'\n\t\t\t\t\tcolor='primary'\n\t\t\t\t\tvariant='contained'\n\t\t\t\t\tonClick={() => setShowDialog(true)}\n\t\t\t\t>\n\t\t\t\t\t{t('upgrade_btn')}\n\t\t\t\t\n\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default ShellUpgradeButton;\n\nShellUpgradeButton.propTypes = {\n\tshell: PropTypes.object.isRequired,\n\trefresh: PropTypes.func.isRequired,\n};\n","import PropTypes from 'prop-types';\nimport React, { useEffect, useState } from 'react';\nimport RichAlertTrans from '../../core/feedback/RichAlertTrans';\n\nconst TIMER_VALUE = 15; // in seconds\n\nconst PreparingRefresh = ({ shell, refresh }) => {\n\t// We use this method instead of just at setTimeout so we can have the number of seconds left before refresh and display it\n\tconst [counter, setCounter] = useState(TIMER_VALUE);\n\n\tconst isPreparing = () => shell.State === 'preparing';\n\n\tuseEffect(() => {\n\t\tif (!isPreparing()) return;\n\n\t\tconst timer = setInterval(() => {\n\t\t\tsetCounter(prev => prev - 1);\n\t\t}, 1000);\n\t\treturn () => clearInterval(timer);\n\t\t// eslint-disable-next-line\n\t}, [shell, setCounter]);\n\n\tuseEffect(() => {\n\t\tif (counter > 0) return;\n\t\trefresh()\n\t\t\t.then(() => setCounter(TIMER_VALUE));\n\t\t// eslint-disable-next-line\n\t}, [counter]);\n\n\tif (!isPreparing()) return null;\n\n\treturn ;\n};\n\nexport default PreparingRefresh;\n\nPreparingRefresh.propTypes = {\n\trefresh: PropTypes.func.isRequired,\n\tshell: PropTypes.object.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React from 'react';\nimport DialogTitle from '@material-ui/core/DialogTitle';\nimport DialogContent from '@material-ui/core/DialogContent';\nimport DialogContentText from '@material-ui/core/DialogContentText';\nimport RichAlert from '../../../core/feedback/RichAlert';\nimport DialogActions from '@material-ui/core/DialogActions';\nimport Button from '../../../core/input/Button';\nimport Dialog from '@material-ui/core/Dialog';\nimport { Trans, useTranslation } from 'react-i18next';\nimport { useShellCancelSubscription } from '@karpeleslab/klb-react-services';\n\nconst ShellCancelDialog = ({ open, setOpen, shell, setShell }) => {\n\tconst { t } = useTranslation();\n\tconst [cancel, cancelling] = useShellCancelSubscription(shell.Shell__);\n\n\tconst handleClose = () => {\n\t\tsetOpen(false);\n\t};\n\n\tconst handleCancel = () => {\n\t\tcancel()\n\t\t\t.then(setShell)\n\t\t\t.then(handleClose);\n\t};\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t{t('confirm_cancel_shell_title')}\n\t\t\t \n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\tsample \n\t\t\t\t\t\t\tsample \n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t \n\t\t\t \n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{t('close_btn')}\n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t{t('cancel_subscription_btn')}\n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default ShellCancelDialog;\n\nShellCancelDialog.propTypes = {\n\topen: PropTypes.bool.isRequired,\n\tsetOpen: PropTypes.func.isRequired,\n\tsetShell: PropTypes.func.isRequired,\n\tshell: PropTypes.object.isRequired\n};\n","import { useCallback, useEffect, useState } from 'react';\nimport {\n\tgetOrderPaymentMethodInfoEndpoint,\n\tuseUserBillingMethods,\n\tuseUserBillings\n} from '@karpeleslab/klb-react-services';\nimport { useRest } from '@karpeleslab/react-klbfw-hooks';\n\nexport const useFirstUserBilling = userId => {\n\tconst [, fetch] = useUserBillings(userId);\n\tconst [billing, setBilling] = useState(null);\n\n\tconst refresh = useCallback(\n\t\tdata => {\n\t\t\tif (data) {\n\t\t\t\tsetBilling({ ...(billing ?? {}), data: data });\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tfetch()\n\t\t\t\t.then(d => (d.data && d.data.length > 0) ? setBilling({ data: d.data[0] }) : setBilling({ data: null }))\n\t\t\t\t.catch(e => {\n\t\t\t\t\tsetBilling({ error: e });\n\t\t\t\t});\n\t\t}\n\t\t, [billing]); //eslint-disable-line\n\n\tuseEffect(() => {\n\t\trefresh();\n\t}, []); //eslint-disable-line\n\n\n\treturn [billing, refresh];\n};\n\nexport const useFirstPaymentMethod = billingId => {\n\tconst [, fetch] = useUserBillingMethods(billingId);\n\tconst [method, setMethod] = useState(null);\n\n\tconst refresh = useCallback(\n\t\tdata => {\n\t\t\tif (data) {\n\t\t\t\tsetMethod({ ...(method ?? {}), data: data });\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tfetch()\n\t\t\t\t.then(d => (d.data && d.data.length > 0) ? setMethod({ data: d.data[0] }) : setMethod({ data: null }))\n\t\t\t\t.catch(e => {\n\t\t\t\t\tsetMethod({ error: e });\n\t\t\t\t});\n\t\t}\n\t\t, [method]); //eslint-disable-line\n\n\tuseEffect(() => {\n\t\trefresh();\n\t}, []); //eslint-disable-line\n\n\n\treturn [method, refresh];\n};\n\nexport const usePaymentMethodInfo = method => {\n\treturn useRest(getOrderPaymentMethodInfoEndpoint(), { method: method });\n};\n","import PropTypes from 'prop-types';\nimport React, {useContext, useEffect, useState} from 'react';\nimport DialogContent from '@material-ui/core/DialogContent';\nimport DialogActions from '@material-ui/core/DialogActions';\nimport { useShellCreateAndSetBilling } from '@karpeleslab/klb-react-services';\nimport { Grid } from '@material-ui/core';\nimport Form from '../../../User/Location/Form';\nimport { Title } from '../../../../core/typography/Title';\nimport { useTranslation } from 'react-i18next';\nimport Stripe from '../../../../core/input/Stripe/Stripe';\nimport Alert from '@material-ui/lab/Alert';\nimport Button from '../../../../core/input/Button';\nimport {UserContext} \t\t\t\t from '../../../../../context/UserContext';\n\nconst AutoRenewCreate = ({ shell, setShell, handleClose }) => {\n\tconst { t } = useTranslation();\n\n\tconst [create] = useShellCreateAndSetBilling(shell.Shell__);\n\tconst [saveEnabled, setSaveEnabled] = useState(false);\n\tconst [creating, setCreating] = useState(false);\n\n\tconst [locationFormValid, setLocationFormValid] = useState(false);\n\tconst [locationData, setLocationData] = useState({});\n\n\tconst [stripe, setStripe] = useState(null);\n\tconst [stripeIntent, setStripeIntent] = useState(null);\n\tconst [stripeElements, setStripeElements] = useState(null);\n\tconst [stripeValid, setStripeValid] = useState(false);\n\tconst [error, setError] = useState(null);\n\tconst [userContext] = useContext(UserContext);\n\n\n\tconst onStripeChange = e => {\n\t\tsetStripeValid(e.complete === true);\n\t};\n\n\tconst handleCreate = async () => {\n\t\tif (!stripe || !stripeElements)\n\t\t\treturn; // stripe not loaded yet\n\n\t\tsetCreating(true);\n\t\t\n\t\tconst result = await stripe.confirmSetup({\n\t\t\telements: stripeElements,\n\t\t\tredirect: 'if_required',\n\t\t\tconfirmParams: {\n\t\t\t\tpayment_method_data: {\n\t\t\t\t\tbilling_details: {\n\t\t\t\t\t\tname: `${locationData.First_Name} ${locationData.Last_Name}`,\n\t\t\t\t\t\temail: userContext.user.data.Email,\n\t\t\t\t\t\taddress: {\n\t\t\t\t\t\t\tcountry: locationData.Country__,\n\t\t\t\t\t\t\tpostal_code: locationData.Zip,\n\t\t\t\t\t\t\tstate: locationData.Province ? locationData.Province : '',\n\t\t\t\t\t\t\tcity: locationData.City ? locationData.City : '',\n\t\t\t\t\t\t\tline1: locationData.Address ? locationData.Address : '',\n\t\t\t\t\t\t\tline2: locationData.Address2 ? locationData.Address2 : '',\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}\n\t\t});\n\n\t\tif (result.error) {\n\t\t\tif (result.error.type === 'card_error' || result.error.type === 'validation_error') {\n\t\t\t\tsetError(result.error.message);\n\t\t\t} else {\n\t\t\t\tsetError(t('unexpected_error'));\n\t\t\t}\n\n\t\t\tsetCreating(false);\n\t\t\treturn;\n\t\t}\n\n\t\tcreate(locationData, {\n\t\t\tbillingLabel: 'Shells',\n\t\t\tbillingMethod: 'Stripe',\n\t\t\tbillingMethodData: { stripe_intent: stripeIntent.stripe_intent }\n\t\t})\n\t\t\t.then(setShell)\n\t\t\t.then(handleClose)\n\t\t\t.finally(() => setCreating(false));\n\t};\n\n\tuseEffect(() => {\n\t\tsetSaveEnabled(locationFormValid && stripeValid);\n\t}, [locationFormValid, stripeValid, setSaveEnabled]);\n\n\treturn (\n\t\t<>\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t{t('billing_user_location_create_title')} \n\t\t\t\t\t \n\t\t\t\t\t\n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t\t\n\t\t\t\t\t\t{t('billing_method_create_title')} \n\t\t\t\t\t \n\n\t\t\t\t\t{error && \n\t\t\t\t\t\t\n\t\t\t\t\t\t\t{error}\n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t\t}\n\n\t\t\t\t\t\n\t\t\t\t\t\t \n\t\t\t\t\t \n\n\t\t\t\t \n\t\t\t \n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{t('close_btn')}\n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t{t('activate_auto_renew_btn')}\n\t\t\t\t \n\t\t\t \n\n\t\t>\n\t);\n};\n\nexport default AutoRenewCreate;\n\nAutoRenewCreate.propTypes = {\n\thandleClose: PropTypes.func.isRequired,\n\tsetShell: PropTypes.func.isRequired,\n\tshell: PropTypes.object.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React from 'react';\nimport Grid from '@material-ui/core/Grid';\nimport { useTranslation } from 'react-i18next';\n\nconst PaymentMethod = ({ method }) => {\n\tconst { t } = useTranslation();\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t{t('payment_method_name', { name: method.Name })}\n\t\t\t \n\n\t\t\t\n\t\t\t\t{t('payment_method_expiration', { expiration: method.Expiration })}\n\t\t\t \n\t\t \n\t);\n};\n\nexport default PaymentMethod;\n\nPaymentMethod.propTypes = {\n\tmethod: PropTypes.object.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React from 'react';\nimport { useFirstPaymentMethod } from '../../../../../hooks/useUserBilling';\nimport DialogContent from '@material-ui/core/DialogContent';\nimport Button from '../../../../core/input/Button';\nimport DialogActions from '@material-ui/core/DialogActions';\nimport { useTranslation } from 'react-i18next';\nimport { useShellSetBilling } from '@karpeleslab/klb-react-services';\nimport { Grid } from '@material-ui/core';\nimport PaymentMethod from '../../../User/Billing/PaymentMethod';\nimport Alert from '@material-ui/lab/Alert';\nimport Loader from '../../../../layout/Loader/Loader';\nimport Typography from '@material-ui/core/Typography';\n\nconst AutoRenewSet = ({ billing, shell, setShell, handleClose }) => {\n\tconst { t } = useTranslation();\n\tconst [method] = useFirstPaymentMethod(billing.User_Billing__);\n\tconst [activate, activating] = useShellSetBilling(shell.Shell__);\n\n\tconst handleActivate = () => {\n\t\tactivate(billing.User_Billing__)\n\t\t\t.then(setShell)\n\t\t\t.then(handleClose);\n\t};\n\n\treturn (\n\t\t<>\n\t\t\t\n\t\t\t\t{(!method || !method.data) && }\n\t\t\t\t{(method && method.data) && \n\t\t\t\t\t\n\t\t\t\t\t\t{t('activate_auto_renew_billing')} \n\t\t\t\t\t \n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t \n\t\t\t\t}\n\t\t\t \n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{t('close_btn')}\n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t{t('activate_auto_renew_btn')}\n\t\t\t\t \n\t\t\t \n\t\t>\n\t);\n};\n\nexport default AutoRenewSet;\n\nAutoRenewSet.propTypes = {\n\tbilling: PropTypes.object.isRequired,\n\thandleClose: PropTypes.func.isRequired,\n\tsetShell: PropTypes.func.isRequired,\n\tshell: PropTypes.object.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React from 'react';\nimport DialogTitle from '@material-ui/core/DialogTitle';\nimport DialogContent from '@material-ui/core/DialogContent';\nimport DialogContentText from '@material-ui/core/DialogContentText';\nimport Dialog from '@material-ui/core/Dialog';\nimport { useTranslation } from 'react-i18next';\nimport RichAlertTrans from '../../../../core/feedback/RichAlertTrans';\nimport { useFirstUserBilling } from '../../../../../hooks/useUserBilling';\nimport Loader from '../../../../layout/Loader/Loader';\nimport AutoRenewCreate from './AutoRenewCreate';\nimport { isExpired } from '../../../../../utils/shell';\nimport AutoRenewSet from './AutoRenewSet';\n\nconst ShellSetAutoRenewDialog = ({ open, setOpen, shell, setShell }) => {\n\tconst { t } = useTranslation();\n\tconst [billing, refresh] = useFirstUserBilling('@');\n\n\tconst handleClose = () => {\n\t\tsetOpen(false);\n\t};\n\n\treturn (\n\t\t {\n\t\t\t\trefresh();\n\t\t\t}}\n\t\t>\n\t\t\t\n\t\t\t\t{t('activate_auto_renew_title')}\n\t\t\t \n\t\t\t\n\t\t\t\t\n\t\t\t\t\t \n\t\t\t\t \n\n\t\t\t\t{(!!billing && isExpired(shell)) &&\n\t\t\t\t\n\t\t\t\t\t \n\t\t\t\t \n\t\t\t\t}\n\n\t\t\t \n\t\t\t{!billing && }\n\t\t\t{(billing && !!billing.data) && }\n\t\t\t{(billing && !billing.data) && }\n\t\t \n\t);\n};\n\nexport default ShellSetAutoRenewDialog;\n\nShellSetAutoRenewDialog.propTypes = {\n\topen: PropTypes.bool.isRequired,\n\tsetOpen: PropTypes.func.isRequired,\n\tsetShell: PropTypes.func.isRequired,\n\tshell: PropTypes.object.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React, { useEffect, useState } from 'react';\nimport { Grid } from '@material-ui/core';\nimport TextField from '@material-ui/core/TextField';\nimport Button from '../../core/input/Button';\nimport { useTranslation } from 'react-i18next';\nimport ShellCancelDialog from './Subscription/ShellCancelDialog';\nimport { useShellUpdate } from '@karpeleslab/klb-react-services';\nimport ShellSetAutoRenewDialog from './Subscription/AutoRenewDialog/ShellSetAutoRenewlDialog';\nimport useMediaQuery from '@material-ui/core/useMediaQuery';\n\nconst ShellUpdateForm = ({ shell, refresh }) => {\n\tconst { t } = useTranslation();\n\n\tconst [label, setLabel] = useState(shell.Label);\n\tconst [saveEnabled, setSaveEnabled] = useState(false);\n\tconst [showCancel, setShowCancel] = useState(false);\n\tconst [showAutoRenew, setShowAutoRenew] = useState(false);\n\n\tconst [update, updating] = useShellUpdate(shell.Shell__);\n\n\tconst isMobile = useMediaQuery(theme => theme.breakpoints.down('xs'));\n\n\tuseEffect(() => {\n\t\tsetLabel(shell.Label);\n\t}, [setLabel, shell]);\n\n\tuseEffect(() => {\n\t\tsetSaveEnabled(label.trim() && label.trim() !== shell.Label);\n\t}, [shell, label, setSaveEnabled]);\n\n\tconst saveHandler = () => {\n\t\tupdate({ Label: label.trim() })\n\t\t\t.then(d => refresh(d));\n\t};\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t setLabel(e.target.value)}\n\t\t\t\t/>\n\t\t\t \n\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{shell.User_Billing__ &&\n\t\t\t\t\t\n\t\t\t\t\t\t setShowCancel(true)}\n\t\t\t\t\t\t\tloading={updating}\n\t\t\t\t\t\t\tdisabled={updating}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{t('cancel_subscription_btn')}\n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t\t}\n\t\t\t\t\t{!shell.User_Billing__ &&\n\t\t\t\t\t\n\t\t\t\t\t\t setShowAutoRenew(true)}\n\t\t\t\t\t\t\tloading={updating}\n\t\t\t\t\t\t\tdisabled={updating}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{t('auto_renew_subscription_btn')}\n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t{t('save_btn')}\n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t \n\t\t\t \n\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default ShellUpdateForm;\n\nShellUpdateForm.propTypes = {\n\trefresh: PropTypes.func.isRequired,\n\tshell: PropTypes.object.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React, { useState } from 'react';\nimport { useTwoStepValidation } from '@karpeleslab/klb-react-services';\nimport DialogTitle from '@material-ui/core/DialogTitle';\nimport DialogContent from '@material-ui/core/DialogContent';\nimport DialogContentText from '@material-ui/core/DialogContentText';\nimport Grid from '@material-ui/core/Grid';\nimport DialogActions from '@material-ui/core/DialogActions';\nimport Button from '../../../core/input/Button';\nimport Dialog from '@material-ui/core/Dialog';\nimport { useTranslation } from 'react-i18next';\nimport RichAlertTrans from '../../../core/feedback/RichAlertTrans';\nimport TextField from '@material-ui/core/TextField';\n\nconst TwoStepDialog = ({ open, setOpen, session, onComplete, extra = null, snackMessageToken = null }) => {\n\tconst [validate, validating] = useTwoStepValidation();\n\tconst [code, setCode] = useState('');\n\tconst { t } = useTranslation();\n\n\tconst reset = () => setCode('');\n\tconst handleClose = () => setOpen(false);\n\n\tconst handleValidate = (e) => {\n\t\te.preventDefault();\n\n\t\tconst p = {};\n\t\tif (snackMessageToken) p['snackMessageToken'] = snackMessageToken;\n\t\tvalidate(session, code, p).then(d => {\n\t\t\tif (onComplete) onComplete(d);\n\t\t});\n\t};\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{t('dialog_two_step_title')}\n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t\t\n\t\t\t\t\t\t{extra && \n\t\t\t\t\t\t }\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t setCode(e.target.value)}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t{t('close_btn')}\n\t\t\t\t\t \n\t\t\t\t\t\n\t\t\t\t\t\t{t('confirm_btn')}\n\t\t\t\t\t \n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default TwoStepDialog;\n\nTwoStepDialog.propTypes = {\n\tonComplete: PropTypes.func,\n\topen: PropTypes.bool.isRequired,\n\tsetOpen: PropTypes.func.isRequired,\n\tsnackMessageToken: PropTypes.string,\n\tsession: PropTypes.string.isRequired,\n\textra: PropTypes.oneOfType([\n\t\tPropTypes.arrayOf(PropTypes.node),\n\t\tPropTypes.node\n\t])\n};\n","import PropTypes from 'prop-types';\nimport React, { useCallback, useState } from 'react';\nimport { Grid } from '@material-ui/core';\nimport { Title } from '../../../core/typography/Title';\nimport { useTranslation } from 'react-i18next';\nimport { useHistory } from 'react-router';\nimport { getShellsRoute } from '../../../RouteController/Factory';\nimport RichAlertTrans from '../../../core/feedback/RichAlertTrans';\nimport TextField from '@material-ui/core/TextField';\nimport Button from '../../../core/input/Button';\nimport useMediaQuery from '@material-ui/core/useMediaQuery';\nimport { useShellTransfer } from '@karpeleslab/klb-react-services';\nimport TwoStepDialog from '../../Account/TwoStep/TwoStepDialog';\n\nconst ShellTransfer = ({ shell }) => {\n\tconst { t } = useTranslation();\n\n\tconst [transfer, transferring] = useShellTransfer(shell.Shell__);\n\n\tconst [showTwoStep, setShowTwoStep] = useState(false);\n\tconst [session, setSession] = useState();\n\tconst [email, setEmail] = useState();\n\tconst history = useHistory();\n\tconst isMobile = useMediaQuery(theme => theme.breakpoints.down('xs'));\n\n\tconst onComplete = useCallback(() => {\n\t\thistory.push(getShellsRoute());\n\t}, []);\n\n\tconst handleSubmit = e => {\n\t\te.preventDefault();\n\t\ttransfer(email).then((session) => {\n\t\t\tsetSession(session);\n\t\t\tsetShowTwoStep(true);\n\t\t});\n\t};\n\n\treturn (\n\t\t<>\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t{t('shell_transfer_title')} \n\t\t\t\t\t \n\t\t\t\t\t\n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t\t\n\t\t\t\t\t\t setEmail(e.target.value)}\n\t\t\t\t\t\t/>\n\t\t\t\t\t \n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t{t('transfer_btn')}\n\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t \n\t\t\t\t\t\t \n\n\t\t\t\t\t \n\n\n\t\t\t\t \n\t\t\t \n\t\t\t }\n\t\t\t/>\n\t\t>\n\t);\n};\n\nexport default ShellTransfer;\n\nShellTransfer.propTypes = {\n\tshell: PropTypes.object.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React from 'react';\nimport ShellUpdateForm from '../../../components/common/Shell/ShellUpdateForm';\nimport Panel from '../../../components/layout/Container/tab/Panel';\nimport { Grid } from '@material-ui/core';\nimport ModeCheck from '../../../components/layout/Mode/ModeCheck';\nimport ShellTransfer from '../../../components/common/Shell/Transfer/ShellTransfer';\n\nconst SettingsTab = ({ currentTab, shell, refresh }) => {\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t \n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default SettingsTab;\nexport const SHELL_TAB_SETTINGS = 0;\n\nSettingsTab.propTypes = {\n\tcurrentTab: PropTypes.number.isRequired,\n\trefresh: PropTypes.func.isRequired,\n\tshell: PropTypes.object.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React from 'react';\nimport { Grid } from '@material-ui/core';\nimport PublicIcon from '@material-ui/icons/Public';\nimport DnsIcon from '@material-ui/icons/Dns';\nimport { Trans, useTranslation } from 'react-i18next';\nimport PersonIcon from '@material-ui/icons/Person';\nimport { Title } from '../../core/typography/Title';\nimport TextWithIcon from '../../core/typography/TextWithIcon';\nimport VpnKeyIcon from '@material-ui/icons/VpnKey';\nimport { Link } from 'react-router-dom';\nimport { getSSHKeychainEditRoute } from '../../RouteController/Factory';\n\nconst ShellConnection = ({ shell }) => {\n\tconst { t } = useTranslation();\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t{t('shell_connection')} \n\t\t\t \n\t\t\t\n\t\t\t\t }\n\t\t\t\t/>\n\t\t\t \n\t\t\t\n\t\t\t\t }\n\t\t\t\t/>\n\n\t\t\t \n\t\t\t\n\t\t\t\t }\n\t\t\t\t/>\n\t\t\t \n\t\t\t{shell.Keychain__ &&\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\t\tsample\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\tsample\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t}\n\t\t\t\t\tstartIcon={ }\n\t\t\t\t/>\n\t\t\t \n\t\t\t}\n\t\t \n\t);\n};\n\nexport default ShellConnection;\n\nShellConnection.propTypes = {\n\tshell: PropTypes.object.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React from 'react';\nimport Dialog from '@material-ui/core/Dialog';\nimport DialogContentText from '@material-ui/core/DialogContentText';\nimport DialogContent from '@material-ui/core/DialogContent';\nimport { useTranslation } from 'react-i18next';\nimport DialogTitle from '@material-ui/core/DialogTitle';\nimport DialogActions from '@material-ui/core/DialogActions';\n\nimport RichAlert from '../../core/feedback/RichAlert';\nimport Button from '../../core/input/Button';\nimport { useShellDeleteIp } from '@karpeleslab/klb-react-services';\n\nconst DeleteIpDialog = ({ shell, shellIp, open, setOpen, setShell }) => {\n\tconst { t } = useTranslation();\n\tconst [deleteIp, deleting] = useShellDeleteIp(shell.Shell__);\n\n\tconst handleClose = () => {\n\t\tsetOpen(false);\n\t};\n\n\tconst handleDelete = e => {\n\t\te.preventDefault();\n\n\t\tdeleteIp(shellIp)\n\t\t\t.then(d => setShell(d))\n\t\t\t.then(handleClose);\n\t};\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t{t('dialog_delete_ip_title')}\n\t\t\t \n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{t('dialog_delete_ip_desc')} \n\t\t\t\t \n\t\t\t \n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{t('close_btn')}\n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t{t('delete_btn')}\n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default DeleteIpDialog;\n\nDeleteIpDialog.propTypes = {\n\topen: PropTypes.bool.isRequired,\n\tsetShell: PropTypes.func.isRequired,\n\tsetOpen: PropTypes.func.isRequired,\n\tshell: PropTypes.object.isRequired,\n\tshellIp: PropTypes.object\n};\n","import React from 'react';\nimport { useTranslation } from 'react-i18next';\n\nimport Grid from '@material-ui/core/Grid';\nimport SetStatus from './../SetStatus/SetStatus';\n\nexport default function NotFound() {\n\tconst { t } = useTranslation();\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{t('error_content_not_found_title')} \n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t{t('error_content_not_found_description')}
\n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n}\n","import PropTypes from 'prop-types';\nimport React, { useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Typography } from '@material-ui/core';\nimport Box from '@material-ui/core/Box';\nimport { CATALOG_PRODUCT_SHELL_IP } from '../../../hooks/useShells';\nimport Loader from '../../layout/Loader/Loader';\nimport NotFound from '../../core/utils/NotFound/NotFound';\nimport Grid from '@material-ui/core/Grid';\nimport Button from '../../core/input/Button';\nimport { useCatalogProduct } from '@karpeleslab/klb-react-services';\nimport NewOrderDialog from '../Order/order/NewOrderDialog';\n\nconst ShellIpPlan = ({ shell, refresh }) => {\n\tconst { t } = useTranslation();\n\tconst [plan] = useCatalogProduct(CATALOG_PRODUCT_SHELL_IP);\n\tconst [showOrder, setShowOrder] = useState(false);\n\n\tif (!plan) return ;\n\tif (!plan.data) return ;\n\n\tconst handleComplete = () => {\n\t\trefresh();\n\t};\n\n\tconst handleOrderCreate = () => {\n\t\tsetShowOrder(true);\n\t};\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t{plan.data['Basic.Name']} \n\t\t\t\t\t\t \n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t{plan.data['Price.Price'].display}\n\t\t\t\t\t\t\t\t/mo \n\t\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t{t('add_ip_btn')}\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t \n\t\t\t \n\t\t\t{\n\t\t\t\tshowOrder &&\n\t\t\t\t \n\t\t\t}\n\t\t \n\t);\n};\n\n\nexport default ShellIpPlan;\n\nShellIpPlan.propTypes = {\n\tshell: PropTypes.object.isRequired,\n\trefresh: PropTypes.func.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React, { useState } from 'react';\nimport { Trans, useTranslation } from 'react-i18next';\nimport TableContainer from '@material-ui/core/TableContainer';\nimport Table from '@material-ui/core/Table';\nimport TableHead from '@material-ui/core/TableHead';\nimport TableCell from '@material-ui/core/TableCell';\nimport TableRow from '@material-ui/core/TableRow';\nimport TableBody from '@material-ui/core/TableBody';\nimport DeleteIcon from '@material-ui/icons/DeleteForever';\nimport Button from '../../core/input/Button';\nimport DeleteIpDialog from './DeleteIpDialog';\nimport { Grid } from '@material-ui/core';\nimport RichAlert from '../../core/feedback/RichAlert';\nimport ShellIpPlan from './ShellIpPlan';\nimport useMediaQuery from '@material-ui/core/useMediaQuery';\nimport IconButton from '@material-ui/core/IconButton';\nimport { Title } from '../../core/typography/Title';\n\nconst ShellIpTable = ({ shell, setShell }) => {\n\tconst { t } = useTranslation();\n\tconst [selected, setSelected] = useState(null);\n\tconst [showDeleteIp, setShowDeleteIp] = useState(false);\n\tconst isMobile = useMediaQuery(theme => theme.breakpoints.down('xs'));\n\n\tif (shell.IPs.length < 1) {\n\t\treturn \n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\tsample \n\t\t\t\t\t\tsample \n\t\t\t\t\t \n\t\t\t\t \n\t\t\t \n\t\t\t\n\t\t\t\t\n\t\t\t \n\t\t ;\n\t}\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t{t('shell_ips')} \n\t\t\t \n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t {t('tablecell_ip_address')} \n\t\t\t\t\t\t\t\t{t('tablecell_ip_address_type')} \n\t\t\t\t\t\t\t\t{t('tablecell_actions')} \n\t\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t\t\n\t\t\t\t\t\t\t{shell.IPs.map(ip => (\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t{ip.IP} \n\t\t\t\t\t\t\t\t\t{ip.Type} \n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t{(isMobile && ip.Type !== 'anycast') && {\n\t\t\t\t\t\t\t\t\t\t\t\tsetSelected(ip);\n\t\t\t\t\t\t\t\t\t\t\t\tsetShowDeleteIp(true);\n\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\tvariant='outlined'\n\t\t\t\t\t\t\t\t\t\t\tsize='small'\n\t\t\t\t\t\t\t\t\t\t\tcolor='secondary'\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t\t }\n\n\t\t\t\t\t\t\t\t\t\t{(!isMobile && ip.Type !== 'anycast') && {\n\t\t\t\t\t\t\t\t\t\t\t\tsetSelected(ip);\n\t\t\t\t\t\t\t\t\t\t\t\tsetShowDeleteIp(true);\n\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\tvariant='outlined'\n\t\t\t\t\t\t\t\t\t\t\tsize='small'\n\t\t\t\t\t\t\t\t\t\t\tcolor='secondary'\n\t\t\t\t\t\t\t\t\t\t\tstartIcon={ }\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{t('delete_btn')}\n\t\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t \n\t\t\t\t\t
\n\t\t\t\t\t \n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default ShellIpTable;\n\nShellIpTable.propTypes = {\n\tsetShell: PropTypes.func.isRequired,\n\tshell: PropTypes.object.isRequired\n};\n","export default __webpack_public_path__ + \"static/media/shell_licenses_empty_state.9aef65f9.svg\";","import React from 'react';\nimport { Trans, useTranslation } from 'react-i18next';\nimport EmptyState from '../../../../core/feedback/State/Empty';\nimport Graphic from '../../../../../assets/img/shell_licenses_empty_state.svg';\n\nconst Empty = () => {\n\tconst { t } = useTranslation();\n\n\treturn (\n\t\t\n\t\t\t\tsample \n\t\t\t\tsample \n\t\t\t}\n\t\t\tgraphic={Graphic}\n\t\t/>\n\t);\n};\n\nexport default Empty;\n","import PropTypes from 'prop-types';\nimport React from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { useShellLicenses } from '@karpeleslab/klb-react-services';\nimport Table from '../../../../core/data/table/Table';\nimport TableDefinition from '../../../../core/data/table/TableDefinition';\nimport Empty from './Empty';\n\nconst ShellLicenseTable = ({ shell }) => {\n\tconst { t } = useTranslation();\n\tconst [licenses, fetch, loading] = useShellLicenses(shell.Shell__);\n\n\treturn (\n\t\t}\n\t\t\tpaperProps={{ elevation: 0 }}\n\t\t>\n\t\t\t\n\t\t\t\t{license => license.Catalog_Product['Basic.Name']}\n\t\t\t \n\t\t\n\t);\n};\n\nexport default ShellLicenseTable;\n\nShellLicenseTable.propTypes = {\n\tshell: PropTypes.object.isRequired\n};\n","import React from 'react';\nimport { Grid } from '@material-ui/core';\nimport ShellConnection from '../../../components/common/Shell/ShellConnection';\nimport ModeCheck from '../../../components/layout/Mode/ModeCheck';\nimport ShellIpTable from '../../../components/common/Shell/ShellIpTable';\nimport { Title } from '../../../components/core/typography/Title';\nimport ShellLicenseTable from '../../../components/common/Shell/License/Table/ShellLicenseTable';\nimport Panel from '../../../components/layout/Container/tab/Panel';\nimport { useTranslation } from 'react-i18next';\nimport PropTypes from 'prop-types';\n\nconst AdministrationTab = ({ currentTab, shell, refresh }) => {\n\tconst { t } = useTranslation();\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t \n\t\t\t\t \n\t\t\t\t{t('shell_license_table')} \n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default AdministrationTab;\nexport const SHELL_TAB_ADMINISTRATION = 1;\n\nAdministrationTab.propTypes = {\n\tcurrentTab: PropTypes.number.isRequired,\n\trefresh: PropTypes.func.isRequired,\n\tshell: PropTypes.object.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React from 'react';\nimport Dialog from '@material-ui/core/Dialog';\nimport DialogContentText from '@material-ui/core/DialogContentText';\nimport DialogContent from '@material-ui/core/DialogContent';\nimport { Trans, useTranslation } from 'react-i18next';\nimport DialogTitle from '@material-ui/core/DialogTitle';\nimport DialogActions from '@material-ui/core/DialogActions';\nimport RichAlert from '../../../core/feedback/RichAlert';\nimport Button from '../../../core/input/Button';\nimport { useShellVolumeSnapshotRestore } from '@karpeleslab/klb-react-services';\nimport moment from 'moment';\n\nconst SnapshotRestoreDialog = ({ open, setOpen, snapshot, shell, setShell, refresh, refreshing }) => {\n\tconst { t } = useTranslation();\n\tconst [restore, restoring] = useShellVolumeSnapshotRestore(shell.Shell__);\n\n\tconst handleClose = () => {\n\t\tsetOpen(false);\n\t};\n\n\tconst handleRestore = e => {\n\t\te.preventDefault();\n\t\trestore(snapshot.Shell_Volume_Snapshot__)\n\t\t\t.then(shell => setShell(shell))\n\t\t\t.then(() => refresh())\n\t\t\t.then(handleClose);\n\t};\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t{t('dialog_restore_snapshot_title')}\n\t\t\t \n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\tsample\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t\tsample \n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t \n\t\t\t \n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{t('close_btn')}\n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t{t('restore_btn')}\n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default SnapshotRestoreDialog;\n\nSnapshotRestoreDialog.propTypes = {\n\topen: PropTypes.bool.isRequired,\n\trefresh: PropTypes.func.isRequired,\n\trefreshing: PropTypes.bool.isRequired,\n\tsetOpen: PropTypes.func.isRequired,\n\tsetShell: PropTypes.func.isRequired,\n\tshell: PropTypes.object.isRequired,\n\tsnapshot: PropTypes.object\n};\n","import PropTypes from 'prop-types';\nimport React from 'react';\nimport Grid from '@material-ui/core/Grid';\nimport { useTranslation } from 'react-i18next';\nimport DateUtil from '../../../core/data/Date/DateUtil';\nimport RestoreIcon from '@material-ui/icons/Restore';\nimport Button from '../../../core/input/Button';\nimport moment from 'moment';\n\nconst SnapshotTableMobileRow = ({ snapshot, onRestore }) => {\n\tconst { t } = useTranslation();\n\n\treturn (\n\t\t\n\t\t\t{snapshot.Snapshot_Id} \n\t\t\t{t(`shell_snapshot_type_${snapshot.Type}`)} \n\t\t\t{t('tablecell_snapshot_date')} \n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t\t{snapshot.Created && moment(parseInt(snapshot.Created.unixms)).fromNow()}\n\t\t\t\t \n\t\t\t \n\t\t\t{t('tablecell_snapshot_os')} \n\t\t\t{snapshot.Shell_Volume.Shell_OS.Name} \n\t\t\t{t('tablecell_snapshot_datacenter')} \n\t\t\t{\n\t\t\t\tsnapshot.Shell_Volume.Shell_Datacenter ? `${snapshot.Shell_Volume.Shell_Datacenter.Location} - ${snapshot.Shell_Volume.Shell_Datacenter.Name}` : ''\n\t\t\t}\n\t\t\t \n\t\t\t\n\t\t\t\t onRestore(snapshot)}\n\t\t\t\t\tstartIcon={ }\n\t\t\t\t>\n\t\t\t\t\t{t('restore_btn')}\n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default SnapshotTableMobileRow;\n\nSnapshotTableMobileRow.propTypes = {\n\tonRestore: PropTypes.func.isRequired,\n\tsnapshot: PropTypes.object.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React, { useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Typography } from '@material-ui/core';\nimport TableDefinition from '../../../core/data/table/TableDefinition';\nimport DateUtil from '../../../core/data/Date/DateUtil';\nimport Button from '../../../core/input/Button';\nimport Table from '../../../core/data/table/Table';\nimport RestoreIcon from '@material-ui/icons/Restore';\nimport moment from 'moment';\nimport Grid from '@material-ui/core/Grid';\nimport SnapshotRestoreDialog from './SnapshotRestoreDialog';\nimport useMediaQuery from '@material-ui/core/useMediaQuery';\nimport SnapshotTableMobileRow from './SnapshotTableMobileRow';\nimport { useShellVolumeSnapshots } from '@karpeleslab/klb-react-services';\n\nconst SnapshotsTable = ({ shell, setShell }) => {\n\tconst { t } = useTranslation();\n\tconst [snapshots, fetch, loading] = useShellVolumeSnapshots(shell.Shell__);\n\tconst isMobile = useMediaQuery(theme => theme.breakpoints.down('xs'));\n\n\tconst [selected, setSelected] = useState(null);\n\tconst [showRestore, setShowRestore] = useState(false);\n\n\tconst onRestore = snapshot => {\n\t\tsetSelected(snapshot);\n\t\tsetShowRestore(true);\n\t};\n\n\treturn <>\n\t\t\n\t\t\t\n\t\t\t\t{snapshot => {\n\t\t\t\t\tif (!isMobile) return snapshot.Snapshot_Id;\n\t\t\t\t\treturn ;\n\t\t\t\t}}\n\t\t\t \n\n\t\t\t{!isMobile && \n\t\t\t\t{snapshot => t(`shell_snapshot_type_${snapshot.Type}`)}\n\t\t\t }\n\n\t\t\t{!isMobile && \n\t\t\t\t{snapshot => snapshot.Shell_Volume.Shell_OS.Name}\n\t\t\t }\n\n\t\t\t{!isMobile && \n\t\t\t\t{snapshot => snapshot.Shell_Volume.Shell_Datacenter ? `${snapshot.Shell_Volume.Shell_Datacenter.Location} - ${snapshot.Shell_Volume.Shell_Datacenter.Name}` : '-'}\n\t\t\t }\n\n\t\t\t{!isMobile && \n\t\t\t\t{snapshot =>\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t\t{snapshot.Created && (\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t{moment(parseInt(snapshot.Created.unixms)).fromNow()}\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t)}\n\t\t\t\t\t \n\n\t\t\t\t}\n\t\t\t }\n\n\t\t\t{!isMobile && \n\t\t\t\t{snapshot =>\n\t\t\t\t\t onRestore(snapshot)}\n\t\t\t\t\t\tstartIcon={ }\n\t\t\t\t\t>\n\t\t\t\t\t\t{t('restore_btn')}\n\t\t\t\t\t \n\t\t\t\t}\n\t\t\t \n\t\t\t}\n\t\t
\n\t\t \n\t>;\n\n};\n\nexport default SnapshotsTable;\n\nSnapshotsTable.propTypes = {\n\tsetShell: PropTypes.func.isRequired,\n\tshell: PropTypes.object.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React from 'react';\nimport Panel from '../../../components/layout/Container/tab/Panel';\nimport { Grid } from '@material-ui/core';\nimport RichAlert from '../../../components/core/feedback/RichAlert';\nimport { Trans } from 'react-i18next';\nimport SnapshotsTable from '../../../components/common/Shell/Snapshots/SnapshotsTable';\n\nconst SnapshotsTab = ({ currentTab, shell, refresh }) => {\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\tsample \n\t\t\t\t\t\t\tsample \n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default SnapshotsTab;\nexport const SHELL_TAB_SNAPSHOTS = 2;\n\nSnapshotsTab.propTypes = {\n\tcurrentTab: PropTypes.number.isRequired,\n\trefresh: PropTypes.func.isRequired,\n\tshell: PropTypes.object.isRequired\n};\n","import React from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { useRest } from '@karpeleslab/react-klbfw-hooks';\nimport TextField from '@material-ui/core/TextField';\nimport InputAdornment from '@material-ui/core/InputAdornment';\nimport CircularProgress from '@material-ui/core/CircularProgress';\nimport PropTypes from 'prop-types';\nimport { getShellDatacentersListEndpoint } from '@karpeleslab/klb-react-services';\n\nconst ShellDatacenterSelector = ({ value, setValue, label = null, allowEmpty = false, helperText = null, disabled = false, required = false, ...rest }) => {\n\tconst { t } = useTranslation();\n\tconst [datacenter] = useRest(getShellDatacentersListEndpoint(), { results_per_page: 100 });\n\n\treturn (\n\t\t setValue(e.target.value)}\n\t\t\tselect\n\t\t\tfullWidth\n\t\t\tInputLabelProps={{ shrink: !!value }}\n\t\t\tdisabled={disabled || !datacenter}\n\t\t\trequired={required}\n\t\t\tvariant='outlined'\n\t\t\tInputProps={!datacenter ?\n\t\t\t\t{\n\t\t\t\t\tendAdornment:\n\t\t\t\t\t\t(\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t )\n\t\t\t\t} : undefined\n\t\t\t}\n\t\t\tSelectProps={{\n\t\t\t\tnative: true\n\t\t\t}}\n\t\t\t{...rest}\n\t\t>\n\t\t\t{allowEmpty &&\n\t\t\t\n\n\t\t\t \n\t\t\t}\n\t\t\t{datacenter && datacenter.data.map(\n\t\t\t\td => \n\t\t\t\t\t{`${d.Location} - ${d.Name}`}\n\t\t\t\t \n\t\t\t)}\n\t\t \n\t);\n};\n\nexport default ShellDatacenterSelector;\n\nShellDatacenterSelector.propTypes = {\n\tallowEmpty: PropTypes.bool,\n\tdisabled: PropTypes.bool,\n\thelperText: PropTypes.string,\n\tlabel: PropTypes.string,\n\trequired: PropTypes.bool,\n\tsetValue: PropTypes.func.isRequired,\n\tvalue: PropTypes.string.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React, { useEffect, useState } from 'react';\nimport { Grid } from '@material-ui/core';\nimport { Trans, useTranslation } from 'react-i18next';\nimport { Title } from '../../../core/typography/Title';\nimport FormControlLabel from '@material-ui/core/FormControlLabel';\nimport Checkbox from '@material-ui/core/Checkbox';\nimport ShellKeychainSelector from '../../../core/input/ShellKeychainSelector';\nimport Button from '../../../core/input/Button';\nimport RichAlert from '../../../core/feedback/RichAlert';\nimport ShellDatacenterSelector from '../../../core/input/ShellDatacenterSelector';\nimport Link from '../../Links/Link';\nimport ModeCheck from '../../../layout/Mode/ModeCheck';\nimport OSSelector from '../../OperatingSystem/Selector/OSSelector';\nimport SSHKeyWarning from './SSHKeyWarning';\nimport { useShellHasLicense } from '../../../../hooks/useShellLicense';\nimport SelectOsLicenseInfo from '../License/SelectOSLicenseInfo';\nimport NewOrderDialog from '../../Order/order/NewOrderDialog';\nimport ShellWindowsOsWarning, { isShellWindowsOSWarningNeeded } from '../ShellWindowsOSWarning';\n\nconst StepSettings = ({ data, setData, shell, next }) => {\n\tconst { t } = useTranslation();\n\tconst [nextEnabled, setNextEnabled] = useState(false);\n\tconst [changeOSToggle, setChangeOSToggle] = useState(false);\n\n\t// Related to OS license\n\tconst [hasLicense, setHasLicense] = useState(false);\n\tconst [fetchLicense, loadingLicense] = useShellHasLicense(shell.Shell__);\n\n\t// Used when an order is needed\n\tconst [orderRequest, setOrderRequest] = useState(null);\n\tconst [showOrder, setShowOrder] = useState(false);\n\n\tconst createChangeHandler = (key, property = 'value') => e => {\n\t\tsetData({ ...data, [key]: (property ? e.target[property] : e) });\n\t};\n\n\tconst getValue = (key, def = '') => {\n\t\tif (!(key in (data ?? {}))) return def;\n\t\treturn data[key];\n\t};\n\n\tuseEffect(() => {\n\t\tconst os = getValue('os', null);\n\t\tif (!os || !os.Catalog_Product__) {\n\t\t\tsetHasLicense(true);\n\t\t\treturn;\n\t\t}\n\n\t\t// Used to reset the state of the selected license\n\t\tsetHasLicense(false);\n\n\t\tfetchLicense(os.Catalog_Product['Shell.LicenseType']).then(setHasLicense);\n\t}, [setHasLicense, data, fetchLicense]);\n\n\tuseEffect(() => {\n\n\t\t// We must select an OS\n\t\tif (!getValue('os', null)) {\n\t\t\tsetNextEnabled(false);\n\t\t\treturn;\n\t\t}\n\n\t\tconst os = getValue('os');\n\n\t\t// Check for license\n\t\tif (os.Catalog_Product) {\n\t\t\tif (loadingLicense || !hasLicense) {\n\t\t\t\tsetNextEnabled(false);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tif (os.Purpose === 'server') {\n\t\t\tconst keychain = getValue('keychain', 'none');\n\t\t\tif (!keychain || keychain === 'none') {\n\t\t\t\tsetNextEnabled(false);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tif (getValue('os').Shell_OS__ !== (shell.Shell_OS__) ||\n\t\t\tgetValue('datacenter', 'none') !== (shell.Shell_Datacenter__ ?? 'datacenter') ||\n\t\t\tgetValue('keychain', 'none') !== (shell.Keychain__ ?? 'none') ||\n\t\t\tgetValue('erase', false)\n\t\t) {\n\t\t\tsetNextEnabled(true);\n\t\t\treturn;\n\t\t}\n\n\t\tsetNextEnabled(false);\n\n\t}, [data, setNextEnabled, loadingLicense, hasLicense]);\n\n\tconst onOrderComplete = () => {\n\t\tsetShowOrder(false);\n\t\tsetOrderRequest(null);\n\n\t\tconst os = getValue('os', null);\n\t\tif (!os) return;\n\t\tfetchLicense(os.Catalog_Product['Shell.LicenseType']).then(setHasLicense);\n\t};\n\n\tconst handleBuyLicense = e => {\n\t\te.preventDefault();\n\t\tconst os = getValue('os', null);\n\t\tif (!os) return;\n\t\tconst productId = os.Catalog_Product__;\n\t\tconst shellId = shell.Shell__;\n\n\t\tconst urlParams = `${productId},shell=${shellId}`;\n\n\t\tsetOrderRequest(urlParams);\n\t\tsetShowOrder(true);\n\t};\n\n\tconst erase = getValue('erase', false) ||\n\t\t(\n\t\t\tgetValue('os') ?\n\t\t\t\tgetValue('os', {}).Shell_OS__ !== shell.Shell_OS__ :\n\t\t\t\tfalse\n\t\t) ||\n\t\tgetValue('datacenter') !== (shell.Shell_Datacenter__ ?? 'datacenter') ||\n\t\tgetValue('keychain') !== (shell.Keychain__ ?? 'none');\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t{t('shell_reinstall_erase')} \n\t\t\t \n\t\t\t{erase &&\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\tsample \n\t\t\t\t\t\tsample \n\t\t\t\t\t \n\t\t\t\t \n\t\t\t \n\t\t\t}\n\t\t\t\n\t\t\t\t \n\t\t\t\t\t}\n\t\t\t\t\tlabel={t('shell_reinstall_erase_text')}\n\t\t\t\t/>\n\t\t\t \n\t\t\t\n\t\t\t\t{t('shell_reinstall_os')} \n\t\t\t \n\t\t\t\n\t\t\t\t{(!changeOSToggle && shell.Shell_OS__ !== null) &&\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t{shell.OS.Name}\n\t\t\t\t\t \n\t\t\t\t\t\n\t\t\t\t\t\t setChangeOSToggle(true)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{t('change_btn')}\n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t \n\t\t\t\t}\n\t\t\t\t{(changeOSToggle || shell.Shell_OS__ === null) &&\n\t\t\t\t \n\t\t\t\t}\n\t\t\t \n\n\t\t\t{(getValue('os', null) && getValue('os', null).Catalog_Product__) &&\n\t\t\t\n\t\t\t\t \n\t\t\t }\n\n\t\t\t{isShellWindowsOSWarningNeeded(shell, getValue('os', null)) &&\n\t\t\t\n\t\t\t\t \n\t\t\t \n\t\t\t}\n\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{t('shell_reinstall_keychain')} \n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t \n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t \n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t{t('shell_reinstall_datacenter')} \n\t\t\t\t \n\t\t\t\t{shell.IPs.length > 0 &&\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\tsample \n\t\t\t\t\t\t\tsample \n\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\tsample\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t \n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t\t 0}\n\t\t\t\t\t\tvalue={getValue('datacenter')}\n\t\t\t\t\t\tsetValue={createChangeHandler('datacenter', null)}\n\t\t\t\t\t/>\n\t\t\t\t \n\t\t\t \n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t{t('next_btn')}\n\t\t\t\t\t \n\t\t\t\t \n\t\t\t \n\n\t\t\t{orderRequest &&\n\t\t\t \n\t\t\t}\n\t\t \n\t);\n};\n\nexport default StepSettings;\n\nStepSettings.propTypes = {\n\tdata: PropTypes.object.isRequired,\n\tnext: PropTypes.func.isRequired,\n\tsetData: PropTypes.func.isRequired,\n\tshell: PropTypes.object.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React, { useEffect, useState } from 'react';\nimport Loader from '../../../layout/Loader/Loader';\nimport { Grid } from '@material-ui/core';\nimport { Title } from '../../../core/typography/Title';\nimport { useTranslation } from 'react-i18next';\nimport RichAlert from '../../../core/feedback/RichAlert';\nimport TextField from '@material-ui/core/TextField';\nimport Button from '../../../core/input/Button';\nimport { useSetSnackbar } from '../../../../hooks/useSnackbar';\nimport { useShellReconfigure, useTwoStepValidation } from '@karpeleslab/klb-react-services';\n\nconst StepValidation = ({ shell, data, onComplete, onFail }) => {\n\tconst { t } = useTranslation();\n\tconst [twoStepInfo, setTwoStepInfo] = useState();\n\tconst [reconfigure, reconfiguring] = useShellReconfigure(shell.Shell__);\n\tconst [validate, validating] = useTwoStepValidation();\n\tconst [code, setCode] = useState('');\n\tconst setSnackbar = useSetSnackbar();\n\n\tuseEffect(() => {\n\t\tconst hasKeychainChanged = shell.Keychain__ !== (data.keychain === 'none' ? null : data.keychain);\n\t\treconfigure({\n\t\t\terase: (data.erase ?? false) ||\n\t\t\t\tdata.os.Shell_OS__ !== shell.Shell_OS__ ||\n\t\t\t\thasKeychainChanged,\n\t\t\tShell_OS__: !data.os ? null : data.os.Shell_OS__,\n\t\t\tShell_Datacenter__: data.datacenter === 'none' ? null : data.datacenter,\n\t\t\tKeychain__: data.keychain === 'none' ? '' : (data.keychain ?? null),\n\t\t}).then(session => {\n\t\t\tif (session && session.done) {\n\t\t\t\tsetSnackbar(t('shell_reinstall_done'), 'success');\n\t\t\t\tonComplete(shell);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tsetTwoStepInfo(session);\n\t\t}).catch(onFail);\n\t}, [setTwoStepInfo]);// eslint-disable-line\n\n\tconst handleCodeSubmit = () => {\n\t\tvalidate(twoStepInfo, code)\n\t\t\t.then(newShell => {\n\t\t\t\tsetSnackbar(t('shell_reinstall_done'), 'success');\n\t\t\t\tonComplete(newShell);\n\t\t\t});\n\t};\n\n\tif (reconfiguring || !twoStepInfo || validating)\n\t\treturn ;\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t{t('shell_reinstall_validation_title')} \n\t\t\t \n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{t('shell_reinstall_validation_desc')}\n\t\t\t\t \n\t\t\t \n\t\t\t\n\t\t\t\t setCode(e.target.value)}\n\t\t\t\t/>\n\t\t\t \n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t{t('confirm_btn')}\n\t\t\t\t\t \n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\n\nexport default StepValidation;\n\nStepValidation.propTypes = {\n\tdata: PropTypes.object.isRequired,\n\tonComplete: PropTypes.func.isRequired,\n\tonFail: PropTypes.func.isRequired,\n\tshell: PropTypes.object.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React, { useState } from 'react';\nimport { Grid } from '@material-ui/core';\nimport { useTranslation } from 'react-i18next';\nimport Stepper from '@material-ui/core/Stepper';\nimport Step from '@material-ui/core/Step';\nimport StepLabel from '@material-ui/core/StepLabel';\nimport StepSettings from './StepSettings';\nimport StepValidation from './StepValidation';\n\nconst getDefaultState = s => {\n\treturn {\n\t\tkeepPassword: true,\n\t\tos: s.OS ?? null,\n\t\tdatacenter: s.Shell_Datacenter__ ?? 'none',\n\t\tkeychain: s.Keychain__ ?? 'none',\n\t\terase: false,\n\t};\n};\n\nconst ShellReinstallWizard = ({ shell, setShell }) => {\n\tconst { t } = useTranslation();\n\tconst [stepIndex, setStepIndex] = useState(0);\n\n\tconst [data, setData] = useState(getDefaultState(shell));\n\n\tconst next = () => {\n\t\tsetStepIndex(stepIndex + 1);\n\t};\n\n\tconst onFail = () => {\n\t\tsetStepIndex(0);\n\t};\n\n\tconst onComplete = s => {\n\t\tsetData(getDefaultState(s));\n\t\tsetStepIndex(0);\n\t\tsetShell(s);\n\t\twindow.scrollTo(0, 0); // This will display clearly the warning 'preparing' state message\n\t};\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t{t('shell_reinstall_step_settings')} \n\t\t\t\t\t \n\t\t\t\t\t\n\t\t\t\t\t\t{t('shell_reinstall_step_validation')} \n\t\t\t\t\t \n\t\t\t\t \n\t\t\t \n\t\t\t\n\t\t\t\t{stepIndex === 0 && }\n\t\t\t\t{stepIndex === 1 && }\n\t\t\t \n\t\t \n\t);\n};\n\nexport default ShellReinstallWizard;\n\nShellReinstallWizard.propTypes = {\n\tsetShell: PropTypes.func.isRequired,\n\tshell: PropTypes.object.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React from 'react';\nimport Panel from '../../../components/layout/Container/tab/Panel';\nimport { Grid } from '@material-ui/core';\nimport RichAlert from '../../../components/core/feedback/RichAlert';\nimport { Trans } from 'react-i18next';\nimport ShellReinstallWizard from '../../../components/common/Shell/Reinstall/ShellReinstallWizard';\n\nconst ReinstallTab = ({ currentTab, shell, refresh }) => {\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\tsample \n\t\t\t\t\t\t\tsample \n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default ReinstallTab;\nexport const SHELL_TAB_REINSTALL = 3;\n\nReinstallTab.propTypes = {\n\tcurrentTab: PropTypes.number.isRequired,\n\trefresh: PropTypes.func.isRequired,\n\tshell: PropTypes.object.isRequired\n};\n","import React, { useEffect } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport TextField from '@material-ui/core/TextField';\nimport InputAdornment from '@material-ui/core/InputAdornment';\nimport CircularProgress from '@material-ui/core/CircularProgress';\nimport PropTypes from 'prop-types';\nimport { useShellISOs } from '@karpeleslab/klb-react-services';\n\nconst ShellISOSelector = ({ value, setValue, label = null, allowEmpty = false, helperText = null, disabled = false, required = false, ...rest }) => {\n\tconst { t } = useTranslation();\n\tconst [isos, fetch, loading] = useShellISOs();\n\n\tuseEffect(() => {\n\t\tfetch({ Status: 'valid' }, { results_per_page: 100 });\n\t}, [fetch]);\n\n\treturn (\n\t\t setValue(e.target.value)}\n\t\t\tselect\n\t\t\tfullWidth\n\t\t\tInputLabelProps={{ shrink: !!value }}\n\t\t\tdisabled={disabled || !isos}\n\t\t\trequired={required}\n\t\t\tvariant='outlined'\n\t\t\tInputProps={loading ?\n\t\t\t\t{\n\t\t\t\t\tendAdornment:\n\t\t\t\t\t\t(\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t )\n\t\t\t\t} : undefined\n\t\t\t}\n\t\t\tSelectProps={{\n\t\t\t\tnative: true\n\t\t\t}}\n\t\t\t{...rest}\n\t\t>\n\t\t\t{allowEmpty &&\n\t\t\t\n\n\t\t\t \n\t\t\t}\n\t\t\t{isos && isos.data.map(\n\t\t\t\td => \n\t\t\t\t\t{d.Filename}\n\t\t\t\t \n\t\t\t)}\n\t\t \n\t);\n};\n\nexport default ShellISOSelector;\n\nShellISOSelector.propTypes = {\n\tallowEmpty: PropTypes.bool,\n\tdisabled: PropTypes.bool,\n\thelperText: PropTypes.string,\n\tlabel: PropTypes.string,\n\trequired: PropTypes.bool,\n\tsetValue: PropTypes.func.isRequired,\n\tvalue: PropTypes.string.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React, { useEffect, useState } from 'react';\nimport Dialog from '@material-ui/core/Dialog';\nimport DialogTitle from '@material-ui/core/DialogTitle';\nimport DialogContent from '@material-ui/core/DialogContent';\nimport Grid from '@material-ui/core/Grid';\nimport DialogActions from '@material-ui/core/DialogActions';\nimport Button from '../../core/input/Button';\nimport { useTranslation } from 'react-i18next';\nimport { useShellMountISO } from '@karpeleslab/klb-react-services';\nimport ShellISOSelector from '../../core/input/ShellISOSelector';\n\n\nconst IsoMountDialog = ({ open, setOpen, shellId, refresh }) => {\n\tconst { t } = useTranslation();\n\tconst [selected, setSelected] = useState(null);\n\tconst [saveEnabled, setSaveEnabled] = useState(false);\n\n\tconst [mount, mounting] = useShellMountISO(selected);\n\n\tuseEffect(() => {\n\t\tsetSaveEnabled(!!selected);\n\t}, [selected, setSaveEnabled]);\n\n\tconst handleClose = () => {\n\t\tsetOpen(false);\n\t};\n\n\tconst handleSave = (e) => {\n\t\te.preventDefault();\n\t\tmount(shellId)\n\t\t\t.then(() => refresh())\n\t\t\t.then(handleClose);\n\t};\n\n\tconst reset = () => {\n\t\tsetSelected(null);\n\t};\n\n\treturn (\n\t\t reset()}\n\t\t\tmaxWidth='lg'\n\t\t\tfullWidth\n\t\t>\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{t('dialog_mount_iso_title')}\n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t{t('close_btn')}\n\t\t\t\t\t \n\t\t\t\t\t\n\t\t\t\t\t\t{t('mount_btn')}\n\t\t\t\t\t \n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default IsoMountDialog;\n\nIsoMountDialog.propTypes = {\n\topen: PropTypes.bool.isRequired,\n\trefresh: PropTypes.func.isRequired,\n\tsetOpen: PropTypes.func.isRequired,\n\tshellId: PropTypes.string.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React from 'react';\nimport Dialog from '@material-ui/core/Dialog';\nimport DialogTitle from '@material-ui/core/DialogTitle';\nimport DialogContent from '@material-ui/core/DialogContent';\nimport DialogActions from '@material-ui/core/DialogActions';\nimport Button from '../../core/input/Button';\nimport { useTranslation } from 'react-i18next';\nimport { useShellISOMountUnmount } from '@karpeleslab/klb-react-services';\nimport DeleteIcon from '@material-ui/icons/Delete';\nimport RichAlertTrans from '../../core/feedback/RichAlertTrans';\nimport DialogContentText from '@material-ui/core/DialogContentText';\n\n\nconst IsoUnmountDialog = ({ open, setOpen, mount, refresh }) => {\n\tconst { t } = useTranslation();\n\tconst [unmount, unmounting] = useShellISOMountUnmount(mount.Shell_ISO_Mount__);\n\n\tconst handleClose = () => {\n\t\tsetOpen(false);\n\t};\n\n\tconst handleUnmount = (e) => {\n\t\te.preventDefault();\n\t\tunmount()\n\t\t\t.then(() => refresh())\n\t\t\t.then(handleClose);\n\t};\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t{t('dialog_unmount_iso_title')}\n\t\t\t \n\t\t\t\n\t\t\t\t\n\t\t\t\t\t \n\t\t\t\t \n\t\t\t \n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{t('close_btn')}\n\t\t\t\t \n\t\t\t\t }\n\t\t\t\t>\n\t\t\t\t\t{t('unmount_btn')}\n\t\t\t\t\n\t\t\t \n\t\t \n\t);\n};\n\nexport default IsoUnmountDialog;\n\nIsoUnmountDialog.propTypes = {\n\topen: PropTypes.bool.isRequired,\n\trefresh: PropTypes.func.isRequired,\n\tsetOpen: PropTypes.func.isRequired,\n\tmount: PropTypes.object.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React, { useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { useShellISOMounts } from '@karpeleslab/klb-react-services';\nimport TableDefinition from '../../core/data/table/TableDefinition';\nimport Grid from '@material-ui/core/Grid';\nimport Button from '../../core/input/Button';\nimport { Link } from 'react-router-dom';\nimport { getISORoute, getShellViewRoute } from '../../RouteController/Factory';\nimport DeleteIcon from '@material-ui/icons/Delete';\nimport Table from '../../core/data/table/Table';\nimport AddIcon from '@material-ui/icons/Add';\nimport IsoMountDialog from './ISOMountDialog';\nimport IsoUnmountDialog from './ISOUnmountDialog';\n\nconst IsoMountTable = ({ filterId, forShells = false }) => {\n\tconst { t } = useTranslation();\n\tconst [mount, fetch, loading] = useShellISOMounts();\n\tconst [showCreate, setShowCreate] = useState(false);\n\tconst [showDelete, setShowDelete] = useState(false);\n\tconst [selected, setSelected] = useState(null);\n\n\tconst initialFilters = forShells ? { Shell__: filterId } : { Shell_ISO__: filterId };\n\n\treturn (\n\t\t<>\n\t\t\t setShowCreate(true)}\n\t\t\t\t\t\tsize='small'\n\t\t\t\t\t\tvariant='contained'\n\t\t\t\t\t\tcolor='primary'\n\t\t\t\t\t\tstartIcon={ }\n\t\t\t\t\t>\n\t\t\t\t\t\t{t('mount_new_iso_btn')}\n\t\t\t\t\t)\n\t\t\t\t]}\n\t\t\t\tinitialFilters={initialFilters}\n\t\t\t\ttitle={t(forShells ? 'shell_mounted_iso' : 'iso_mounted_title')}\n\t\t\t\tfetch={fetch}\n\t\t\t\tdata={mount}\n\t\t\t\tsearch={false}\n\t\t\t\tloading={loading}\n\t\t\t\tpaperProps={{ elevation: 0 }}\n\t\t\t\ttoolbarProps={{ style: { paddingLeft: 0 } }}\n\t\t\t>\n\t\t\t\t\n\t\t\t\t\t{mount => !forShells ?\n\t\t\t\t\t\t {mount.Shell.Label}\n\t\t\t\t\t\t:\n\t\t\t\t\t\t {mount.Shell_ISO.Filename}\n\t\t\t\t\t}\n\t\t\t\t \n\n\t\t\t\t\n\t\t\t\t\t{mount =>\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t {\n\t\t\t\t\t\t\t\t\t\tsetSelected(mount);\n\t\t\t\t\t\t\t\t\t\tsetShowDelete(true);\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\tvariant='outlined'\n\t\t\t\t\t\t\t\t\tsize='small'\n\t\t\t\t\t\t\t\t\tcolor='secondary'\n\t\t\t\t\t\t\t\t\tstartIcon={ }\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{t('unmount_btn')}\n\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t}\n\t\t\t\t \n\t\t\t
\n\t\t\t{forShells && \n\t\t\t}\n\t\t\t{selected && }\n\t\t>\n\t);\n};\n\nexport default IsoMountTable;\n\nIsoMountTable.propTypes = {\n\tfilterId: PropTypes.string.isRequired,\n\tforShells: PropTypes.bool\n};\n","import PropTypes from 'prop-types';\nimport React from 'react';\nimport { Grid } from '@material-ui/core';\nimport IsoMountTable from '../../ISO/IsoMountTable';\n\nconst ShellIso = ({ shell }) => {\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t \n\t\t \n\t);\n};\n\nexport default ShellIso;\n\nShellIso.propTypes = {\n\tshell: PropTypes.object.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React from 'react';\nimport Panel from '../../../components/layout/Container/tab/Panel';\nimport { Grid } from '@material-ui/core';\nimport RichAlertTrans from '../../../components/core/feedback/RichAlertTrans';\nimport ShellIso from '../../../components/common/Shell/ISO/ShellISO';\nimport ModeCheck from '../../../components/layout/Mode/ModeCheck';\n\nconst ISOTab = ({ currentTab, shell }) => {\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t \n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default ISOTab;\nexport const SHELL_TAB_ISO = 4;\n\nISOTab.propTypes = {\n\tcurrentTab: PropTypes.number.isRequired,\n\trefresh: PropTypes.func.isRequired,\n\tshell: PropTypes.object.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React, { useEffect, useState } from 'react';\nimport InputAdornment from '@material-ui/core/InputAdornment';\nimport TextField from '@material-ui/core/TextField';\nimport FileCopyIcon from '@material-ui/icons/FileCopy';\nimport { copyToClipboard } from '../../../utils/misc';\nimport IconButton from '@material-ui/core/IconButton';\nimport CheckIcon from '@material-ui/icons/Check';\nimport { useTranslation } from 'react-i18next';\nimport Tooltip from '@material-ui/core/Tooltip';\nimport { Typography } from '@material-ui/core';\n\nconst ClipboardCopyTextField = ({ value, ...rest }) => {\n\tconst [copied, setCopied] = useState(false);\n\tconst { t } = useTranslation();\n\n\tuseEffect(() => {\n\t\tlet timer = null;\n\t\tif (copied) {\n\t\t\ttimer = setTimeout(() => {\n\t\t\t\tsetCopied(false);\n\t\t\t}, 1000);\n\t\t}\n\t\treturn () => {\n\t\t\tif (timer) clearTimeout(timer);\n\t\t};\n\t}, [copied]);\n\n\tconst handleCopy = () => {\n\t\tif (copied) return;\n\t\tcopyToClipboard(value);\n\t\tsetCopied(true);\n\t};\n\n\treturn (\n\t\t\n\n\t\t\t\t\t\t\t{!copied && \n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t }\n\n\t\t\t\t\t\t\t{copied && <>\n\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t{t('clipboard_copy_confirm')}\n\t\t\t\t\t\t\t\t \n\n\t\t\t\t\t\t\t>}\n\t\t\t\t\t\t)\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\t{...rest}\n\t\t/>\n\t);\n};\n\nexport default ClipboardCopyTextField;\n\nClipboardCopyTextField.propTypes = {\n\tvalue: PropTypes.string\n};\n","import PropTypes from 'prop-types';\nimport React, { useState } from 'react';\nimport DialogTitle from '@material-ui/core/DialogTitle';\nimport DialogContent from '@material-ui/core/DialogContent';\nimport DialogContentText from '@material-ui/core/DialogContentText';\nimport Grid from '@material-ui/core/Grid';\nimport DialogActions from '@material-ui/core/DialogActions';\nimport Button from '../../core/input/Button';\nimport Dialog from '@material-ui/core/Dialog';\nimport { useTranslation } from 'react-i18next';\nimport BugReportIcon from '@material-ui/icons/BugReport';\nimport ClipboardCopyTextField from '../../core/input/ClipboardCopyTextField';\nimport { useMetaObjectLinkAccess } from '@karpeleslab/klb-react-services';\nimport RichAlertTrans from '../../core/feedback/RichAlertTrans';\n\nconst DebugDialog = ({ open, setOpen, shell }) => {\n\tconst { t } = useTranslation();\n\n\tconst [getShareLink, loadingLink] = useMetaObjectLinkAccess(shell.Shell__);\n\tconst [link, setLink] = useState();\n\n\tconst handleClose = () => {\n\t\tsetOpen(false);\n\t};\n\n\tconst handleGet = () => {\n\t\tgetShareLink('A', '+24 hour').then(setLink);\n\t};\n\n\treturn (\n\t\t\n\n\t\t\t\n\t\t\t\t{t('shell_debug')}\n\t\t\t \n\t\t\t\n\t\t\t\t\n\t\t\t\t\t \n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t{!link && }\n\t\t\t\t\t\t\tloading={loadingLink}\n\t\t\t\t\t\t\tonClick={handleGet}\n\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{t('shell_debug_btn')}\n\t\t\t\t\t\t\n\t\t\t\t\t\t}\n\t\t\t\t\t\t{link &&\n\t\t\t\t\t\t \n\t\t\t\t\t\t}\n\t\t\t\t\t \n\t\t\t\t \n\t\t\t \n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{t('close_btn')}\n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default DebugDialog;\n\nDebugDialog.propTypes = {\n\topen: PropTypes.bool.isRequired,\n\tsetOpen: PropTypes.func.isRequired,\n\tshell: PropTypes.object.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React, { useState } from 'react';\nimport Button from '../../core/input/Button';\nimport { useTranslation } from 'react-i18next';\nimport BugReportIcon from '@material-ui/icons/BugReport';\nimport DebugDialog from './DebugDialog';\n\nconst ShellDebugButton = ({ shell, ...rest }) => {\n\tconst { t } = useTranslation();\n\tconst [show, setShow] = useState(false);\n\n\treturn (\n\t\t<>\n\t\t\t }\n\t\t\t\tonClick={() => setShow(true)}\n\t\t\t\t{...rest}\n\t\t\t>\n\t\t\t\t{t('shell_debug_btn')}\n\t\t\t\n\t\t\t\n\t\t>\n\t);\n};\n\nexport default ShellDebugButton;\n\nShellDebugButton.propTypes = {\n\tshell: PropTypes.object.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React from 'react';\nimport Panel from '../../../components/layout/Container/tab/Panel';\nimport { Grid } from '@material-ui/core';\nimport { Title } from '../../../components/core/typography/Title';\nimport ShellDebugButton from '../../../components/common/Shell/ShellDebugButton';\nimport { useTranslation } from 'react-i18next';\nimport ClipboardCopyTextField from '../../../components/core/input/ClipboardCopyTextField';\nimport RichAlertTrans from '../../../components/core/feedback/RichAlertTrans';\nimport useMediaQuery from '@material-ui/core/useMediaQuery';\n\nconst SupportTab = ({ currentTab, shell }) => {\n\tconst { t } = useTranslation();\n\tconst isMobile = useMediaQuery(theme => theme.breakpoints.down('sm'), { noSsr: true });\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t{t('shell_debug_title')} \n\t\t\t\t\n\t\t\t\t\t \n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t \n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t \n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default SupportTab;\nexport const SHELL_TAB_SUPPORT = 5;\n\nSupportTab.propTypes = {\n\tcurrentTab: PropTypes.number.isRequired,\n\tshell: PropTypes.object.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React, { useEffect } from 'react';\nimport Tab from '@material-ui/core/Tab';\nimport { SHELL_TAB_SETTINGS } from './SettingsTab';\nimport { SHELL_TAB_ADMINISTRATION } from './AdministrationTab';\nimport { isExpired } from '../../../utils/shell';\nimport { SHELL_TAB_SNAPSHOTS } from './SnapshotsTab';\nimport { SHELL_TAB_REINSTALL } from './ReinstallTab';\nimport { SHELL_TAB_ISO } from './ISOTab';\nimport Tabs from '@material-ui/core/Tabs';\nimport { getShellViewRoute } from '../../../components/RouteController/Factory';\nimport queryString from 'query-string';\nimport { useHistory, useLocation } from 'react-router';\nimport useMediaQuery from '@material-ui/core/useMediaQuery';\nimport { useTranslation } from 'react-i18next';\nimport { useIsMode } from '../../../hooks/useIsMode';\nimport { ADVANCED_MODE } from '../../../context/ModeContext';\nimport { SHELL_TAB_SUPPORT } from './SupportTab';\n\nconst ShellTabs = ({ shell, value, setValue }) => {\n\tconst history = useHistory();\n\tconst location = useLocation();\n\tconst { t } = useTranslation();\n\n\tconst isMobile = useMediaQuery('(max-width:608px)', { noSsr: true });\n\tconst isAdvanced = useIsMode(ADVANCED_MODE);\n\n\tconst handleTabChange = (event, newValue) => {\n\t\thistory.push(`${getShellViewRoute(shell.Shell__)}?t=${newValue}`);\n\t};\n\n\tuseEffect(() => {\n\t\tconst currentParams = queryString.parse(location.search);\n\t\tconst index = parseInt(currentParams.t ?? 0) ?? 0;\n\n\t\tsetValue(index);\n\t}, [location]); //eslint-disable-line\n\n\tuseEffect(() => {\n\t\t// Reinstall tab disabled when shell is expired\n\t\tconst currentParams = queryString.parse(location.search);\n\t\tconst index = parseInt(currentParams.t ?? 0) ?? 0;\n\n\t\tif (index === SHELL_TAB_REINSTALL && isExpired(shell)) {\n\t\t\thistory.push(`${getShellViewRoute(shell.Shell__)}?t=${SHELL_TAB_SETTINGS}`);\n\t\t}\n\t}, [shell, location]);\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\n\t\t\t \n\t\t\t \n\t\t\t{(isAdvanced && 0) &&\n\t\t\t\n\t\t\t}\n\t\t\t\n\t\t \n\t);\n};\n\nexport default ShellTabs;\n\nShellTabs.propTypes = {\n\tsetValue: PropTypes.func.isRequired,\n\tshell: PropTypes.object.isRequired,\n\tvalue: PropTypes.number.isRequired\n};\n","import React, { useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { useParams } from 'react-router';\nimport PageLoader from '../../components/layout/Loader/PageLoader';\nimport PageNotFound from '../System/PageNotFound';\nimport PageContainer from '../../components/layout/Container/PageContainer';\nimport { Box, Grid } from '@material-ui/core';\nimport PageTitle from '../../components/core/typography/PageTitle';\nimport { getShellsRoute } from '../../components/RouteController/Factory';\nimport ShellPicture from '../../components/common/Shell/ShellPicture/ShellPicture';\nimport ShellAction from '../../components/common/Shell/ShellAction/ShellAction';\nimport ShellUsage from '../../components/common/Shell/Subscription/ShellUsage';\nimport ShellExpireButton from '../../components/common/Shell/ShellExpireButton';\nimport ShellInfo from '../../components/common/Shell/ShellInfo';\nimport ShellUpgradeButton from '../../components/common/Shell/ShellUpgradeButton';\nimport useMediaQuery from '@material-ui/core/useMediaQuery';\nimport PreparingRefresh from '../../components/common/Shell/PreparingRefresh';\nimport { isExpired } from '../../utils/shell';\nimport ShellExpiredMessage from '../../components/common/Shell/Subscription/ShellExpiredMessage';\nimport ModeCheck from '../../components/layout/Mode/ModeCheck';\nimport { useShell } from '@karpeleslab/klb-react-services';\nimport { useAutoRefresher } from '../../hooks/useAutoRefresher';\nimport { SHELL_OS_ICON_VARIATION } from '../../hooks/useShells';\nimport SettingsTab from './Shell/SettingsTab';\nimport AdministrationTab from './Shell/AdministrationTab';\nimport SnapshotsTab from './Shell/SnapshotsTab';\nimport ReinstallTab from './Shell/ReinstallTab';\nimport ISOTab from './Shell/ISOTab';\nimport ShellTabs from './Shell/ShellTabs';\nimport SupportTab from './Shell/SupportTab';\nimport ShellWindowsOsWarning, { isShellWindowsOSWarningNeeded } from '../../components/common/Shell/ShellWindowsOSWarning';\n\nconst Shell = () => {\n\tconst { t } = useTranslation();\n\tconst { shellId } = useParams();\n\tconst [params] = useState({ image_variation: [SHELL_OS_ICON_VARIATION] });\n\tconst [shell, refresh] = useShell(shellId, params);\n\tuseAutoRefresher(refresh);\n\n\tconst [tabIndex, setTabIndex] = useState(0);\n\n\tconst isMobile = useMediaQuery('(max-width:608px)', { noSsr: true });\n\tconst isSmall = useMediaQuery(theme => theme.breakpoints.down('md'), { noSsr: true });\n\n\tif (!shell) return ;\n\tif (!shell.data) return ;\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t \n\t\t\t\t \n\n\t\t\t\t{isExpired(shell.data) &&\n\n\t\t\t\t\n\t\t\t\t\t \n\t\t\t\t \n\t\t\t\t}\n\n\t\t\t\t{isShellWindowsOSWarningNeeded(shell.data, shell.data.OS) &&\n\t\t\t\t\n\t\t\t\t\t \n\t\t\t\t \n\t\t\t\t}\n\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t \n\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t \n\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t \n\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t{!isExpired(shell.data) &&\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t \n\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t \n\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default Shell;\n","import React from 'react';\nimport { Grid, Typography } from '@material-ui/core';\nimport { useTranslation } from 'react-i18next';\nimport Box from '@material-ui/core/Box';\nimport Link from './Link';\n\nconst SolutionsForYou = () => {\n\tconst { t } = useTranslation();\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{t('footer_nav_why_shells_header_1')} \n\t\t\t\t \n\t\t\t \n\t\t\t\n\t\t\t\t \n\t\t\t\t\t{t('footer_nav_solutions_for_you_t12')}\n\t\t\t\t\n\t\t\t \n\t\t\t\n\t\t\t\t \n\t\t\t\t\t{t('footer_nav_solutions_for_you_t13')}\n\t\t\t\t\n\t\t\t \n\t\t\t\n\t\t\t\t \n\t\t\t\t\t{t('footer_nav_solutions_for_you_t14')}\n\t\t\t\t\n\t\t\t \n\t\t\t\n\t\t\t\t \n\t\t\t\t\t{t('footer_nav_solutions_for_you_t15')}\n\t\t\t\t\n\t\t\t \n\t\t\t\n\t\t\t\t \n\t\t\t\t\t{t('footer_nav_solutions_for_you_t16')}\n\t\t\t\t\n\t\t\t \n\t\t\t\n\t\t\t\t \n\t\t\t\t\t{t('footer_nav_solutions_for_you_t17')}\n\t\t\t\t\n\t\t\t \n\t\t\t\n\t\t\t\t \n\t\t\t\t\t{t('footer_nav_solutions_for_you_t2')}\n\t\t\t\t\n\t\t\t \n\t\t\t\n\t\t\t\t \n\t\t\t\t\t{t('footer_nav_solutions_for_you_t3')}\n\t\t\t\t\n\t\t\t \n\t\t\t\n\t\t\t\t \n\t\t\t\t\t{t('footer_nav_solutions_for_you_t4')}\n\t\t\t\t\n\t\t\t \n\t\t\t\n\t\t\t\t \n\t\t\t\t\t{t('footer_nav_solutions_for_you_t8')}\n\t\t\t\t\n\t\t\t \n\t\t\t\n\t\t\t\t \n\t\t\t\t\t{t('footer_nav_solutions_for_you_t10')}\n\t\t\t\t\n\t\t\t \n\t\t\t\n\t\t\t\t \n\t\t\t\t\t{t('footer_nav_solutions_for_you_t0')}\n\t\t\t\t\n\t\t\t \n\t\t \n\t);\n};\n\nexport default SolutionsForYou;\n","import React from 'react';\nimport { Grid, Typography } from '@material-ui/core';\nimport { useTranslation } from 'react-i18next';\nimport Box from '@material-ui/core/Box';\nimport Link from './Link';\n\nconst SolutionsForThem = () => {\n\tconst { t } = useTranslation();\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{t('footer_nav_why_shells_header_2')} \n\t\t\t\t \n\t\t\t \n\t\t\t\n\t\t\t\t \n\t\t\t\t\t{t('footer_nav_solutions_for_business_t9')}\n\t\t\t\t\n\t\t\t \n\t\t\t\n\t\t\t\t \n\t\t\t\t\t{t('footer_nav_solutions_for_business_t18')}\n\t\t\t\t\n\t\t\t \n\t\t\t\n\t\t\t\t \n\t\t\t\t\t{t('footer_nav_solutions_for_business_t19')}\n\t\t\t\t\n\t\t\t \n\t\t \n\t);\n};\n\nexport default SolutionsForThem;","import React from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Grid, Typography } from '@material-ui/core';\nimport Box from '@material-ui/core/Box';\nimport Link from './Link';\n\nconst CommunityHelp = () => {\n\tconst { t } = useTranslation();\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{t('footer_nav_com')} \n\t\t\t\t \n\t\t\t \n\t\t\t\n\t\t\t\t \n\t\t\t\t\t{t('footer_nav_com_t3')}\n\t\t\t\t\n\t\t\t \n\t\t\t\n\t\t\t\t \n\t\t\t\t\t{t('footer_nav_com_t4')}\n\t\t\t\t\n\t\t\t \n\t\t\t\n\t\t\t\t \n\t\t\t\t\t{t('support_title')}\n\t\t\t\t\n\t\t\t \n\t\t \n\t);\n};\n\nexport default CommunityHelp;\n","import React from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Grid, Typography } from '@material-ui/core';\nimport Box from '@material-ui/core/Box';\nimport Link from './Link';\n\nconst Legal = () => {\n\tconst { t } = useTranslation();\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{t('footer_nav_legal')} \n\t\t\t\t \n\t\t\t \n\t\t\t\n\t\t\t\t \n\t\t\t\t\t{t('footer_terms_conditions')}\n\t\t\t\t\n\t\t\t \n\t\t\t\n\t\t\t\t \n\t\t\t\t\t{t('footer_privacy_policy')}\n\t\t\t\t\n\t\t\t \n\t\t \n\t);\n};\n\nexport default Legal;\n","import React from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Grid, Typography } from '@material-ui/core';\nimport Box from '@material-ui/core/Box';\nimport Link from './Link';\n\nconst Navigation = () => {\n\tconst { t } = useTranslation();\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{t('footer_nav_nav')} \n\t\t\t\t \n\t\t\t \n\t\t\t\n\t\t\t\t \n\t\t\t\t\t{t('footer_link_os')}\n\t\t\t\t\n\t\t\t \n\t\t\t\n\t\t\t\t \n\t\t\t\t\t{t('footer_link_download')}\n\t\t\t\t\n\t\t\t \n\t\t\t\n\t\t\t\t \n\t\t\t\t\t{t('footer_link_affiliates')}\n\t\t\t\t\n\t\t\t \n\t\t\t\n\t\t\t\t \n\t\t\t\t\t{t('footer_link_contact')}\n\t\t\t\t\n\t\t\t \n\t\t\t\n\t\t\t\t \n\t\t\t\t\t{t('footer_link_network')}\n\t\t\t\t\n\t\t\t \n\t\t \n\t);\n};\n\nexport default Navigation;\n","import React from 'react';\nimport { Grid, Typography } from '@material-ui/core';\nimport { useTranslation } from 'react-i18next';\nimport Box from '@material-ui/core/Box';\nimport Link from './Link';\n\nconst About = () => {\n\tconst { t } = useTranslation();\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{t('footer_nav_about')} \n\t\t\t\t \n\t\t\t \n\t\t\t\n\t\t\t\t \n\t\t\t\t\t{t('footer_nav_about_t0')}\n\t\t\t\t\n\t\t\t \n\t\t\t\n\t\t\t\t \n\t\t\t\t\t{t('footer_nav_about_t1')}\n\t\t\t\t\n\t\t\t \n\t\t\t\n\t\t\t\t \n\t\t\t\t\t{t('footer_link_careers')}\n\t\t\t\t\n\t\t\t \n\t\t \n\t);\n};\n\nexport default About;","import React from 'react';\nimport { Grid } from '@material-ui/core';\nimport PageTitle from '../../components/core/typography/PageTitle';\nimport PageContainer from '../../components/layout/Container/PageContainer';\nimport { useTranslation } from 'react-i18next';\nimport SolutionsForYou from '../../components/common/Links/SolutionsForYou';\nimport SolutionsForThem from '../../components/common/Links/SolutionsForThem';\nimport CommunityHelp from '../../components/common/Links/CommunityHelp';\nimport Legal from '../../components/common/Links/Legal';\nimport Navigation from '../../components/common/Links/Navigation';\nimport About from '../../components/common/Links/About';\n\nconst Links = () => {\n\tconst { t } = useTranslation();\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t\t\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t\t\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t \n\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t\t\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t{t('footer_copyright', { year: (new Date()).getFullYear() })}\n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default Links;\n","import React from 'react';\nimport { useTranslation } from 'react-i18next';\nimport TableDefinition from '../../core/data/table/TableDefinition';\nimport Table from '../../core/data/table/Table';\nimport Button from '../../core/input/Button';\nimport VisibilityIcon from '@material-ui/icons/Visibility';\nimport { Link } from 'react-router-dom';\nimport { getCustomOsEditRoute } from '../../RouteController/Factory';\nimport Grid from '@material-ui/core/Grid';\nimport { ICON_VARIATION } from '../../../hooks/useOperatingSystems';\nimport DateUtil from '../../core/data/Date/DateUtil';\nimport { useOperatingSystems } from '@karpeleslab/klb-react-services';\nimport Avatar from '@material-ui/core/Avatar';\nimport defaultIcon from '../../../assets/img/shells_icon_white.svg';\nimport useMediaQuery from '@material-ui/core/useMediaQuery';\n\nconst OperatingSystemTable = () => {\n\tconst { t } = useTranslation();\n\tconst [os, fetch, loading] = useOperatingSystems();\n\tconst isMobile = useMediaQuery(theme => theme.breakpoints.down('sm'));\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t{os => }\n\t\t\t \n\t\t\t \n\n\t\t\t\n\t\t\t\t{os => t(`custom_os_public_${os.Public.toLowerCase()}`)}\n\t\t\t \n\n\t\t\t{!isMobile && \n\t\t\t\t{os => t(`custom_os_family_${os.Family.toLowerCase()}`)}\n\t\t\t }\n\n\t\t\t{!isMobile && \n\t\t\t\t{os => }\n\t\t\t }\n\n\t\t\t\n\t\t\t\t{os =>\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t }\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{t('view_btn')}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t}\n\t\t\t \n\n\n\t\t
\n\t);\n};\n\nexport default OperatingSystemTable;\n","import PropTypes from 'prop-types';\nimport React, { useEffect, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport TextField from '@material-ui/core/TextField';\nimport InputAdornment from '@material-ui/core/InputAdornment';\nimport CircularProgress from '@material-ui/core/CircularProgress';\nimport { useShells } from '@karpeleslab/klb-react-services';\n\nconst ShellSelector = ({ value, setValue, idOnly = true, volumeRequired = false, ...rest }) => {\n\tconst { t } = useTranslation();\n\tconst [shells, fetch, loading] = useShells();\n\tconst [idToShellMap, setIdToShellMap] = useState();\n\n\tuseEffect(() => {\n\t\tfetch({}, { result_per_page: 100, page_no: 1 });\n\t}, []); // eslint-disable-line\n\n\tuseEffect(() => {\n\t\tif (idOnly || !shells) return;\n\t\tconst map = {};\n\t\tshells.data.forEach(s => map[s.Shell__] = s);\n\t\tsetIdToShellMap(map);\n\t}, [shells, setIdToShellMap, idOnly]);\n\n\treturn (\n\t\t setValue(idOnly ? e.target.value : idToShellMap[e.target.value])}\n\t\t\tselect\n\t\t\tfullWidth\n\t\t\tInputLabelProps={{ shrink: !!value }}\n\t\t\tvariant='outlined'\n\t\t\tInputProps={loading ?\n\t\t\t\t{\n\t\t\t\t\tendAdornment:\n\t\t\t\t\t\t(\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t )\n\t\t\t\t} : undefined\n\t\t\t}\n\t\t\tSelectProps={{\n\t\t\t\tnative: true,\n\t\t\t}}\n\t\t\t{...rest}\n\t\t>\n\t\t\t \n\n\t\t\t{(shells && !loading) && shells.data.map(\n\t\t\t\tshell => \n\t\t\t\t\t{shell.Label}\n\t\t\t\t \n\t\t\t)}\n\t\t \n\t);\n};\n\nexport default ShellSelector;\n\nShellSelector.propTypes = {\n\tidOnly: PropTypes.bool,\n\tsetValue: PropTypes.func.isRequired,\n\tvalue: PropTypes.string,\n\tvolumeRequired: PropTypes.bool\n};\n","import React from 'react';\nimport { useTranslation } from 'react-i18next';\nimport TextField from '@material-ui/core/TextField';\nimport PropTypes from 'prop-types';\n\nconst OSFamilySelector = ({ value, setValue, disabled = false, required = false, ...rest }) => {\n\tconst { t } = useTranslation();\n\n\treturn (\n\t\t setValue(e.target.value)}\n\t\t\tselect\n\t\t\tfullWidth\n\t\t\tInputLabelProps={{ shrink: !!value }}\n\t\t\tdisabled={disabled}\n\t\t\trequired={required}\n\t\t\tvariant='outlined'\n\t\t\tSelectProps={{\n\t\t\t\tnative: true\n\t\t\t}}\n\t\t\t{...rest}\n\t\t>\n\t\t\t \n\t\t\t{t('custom_os_family_linux')} \n\t\t\t{t('custom_os_family_windows')} \n\t\t\t{t('custom_os_family_macos')} \n\t\t\t{t('custom_os_family_android')} \n\t\t \n\t);\n};\n\nexport default OSFamilySelector;\n\nOSFamilySelector.propTypes = {\n\tdisabled: PropTypes.bool,\n\trequired: PropTypes.bool,\n\tsetValue: PropTypes.func.isRequired,\n\tvalue: PropTypes.string\n};\n","import React from 'react';\nimport { useTranslation } from 'react-i18next';\nimport TextField from '@material-ui/core/TextField';\nimport PropTypes from 'prop-types';\n\nconst OSBootSelector = ({ value, setValue, disabled = false, required = false, ...rest }) => {\n\tconst { t } = useTranslation();\n\n\treturn (\n\t\t setValue(e.target.value)}\n\t\t\tselect\n\t\t\tfullWidth\n\t\t\tInputLabelProps={{ shrink: !!value }}\n\t\t\tdisabled={disabled}\n\t\t\trequired={required}\n\t\t\tvariant='outlined'\n\t\t\tSelectProps={{\n\t\t\t\tnative: true\n\t\t\t}}\n\t\t\t{...rest}\n\t\t>\n\t\t\t \n\t\t\t{t('custom_os_family_guest-linux')} \n\t\t\t{t('custom_os_family_bios')} \n\t\t\t{t('custom_os_family_efi')} \n\t\t \n\t);\n};\n\nexport default OSBootSelector;\n\nOSBootSelector.propTypes = {\n\tdisabled: PropTypes.bool,\n\trequired: PropTypes.bool,\n\tsetValue: PropTypes.func.isRequired,\n\tvalue: PropTypes.string\n};\n","import React from 'react';\nimport { useTranslation } from 'react-i18next';\nimport TextField from '@material-ui/core/TextField';\nimport PropTypes from 'prop-types';\n\nconst OSPublicSelector = ({ value, setValue, disabled = false, required = false, ...rest }) => {\n\tconst { t } = useTranslation();\n\n\treturn (\n\t\t setValue(e.target.value)}\n\t\t\tselect\n\t\t\tfullWidth\n\t\t\tInputLabelProps={{ shrink: !!value }}\n\t\t\tdisabled={disabled}\n\t\t\trequired={required}\n\t\t\tvariant='outlined'\n\t\t\tSelectProps={{\n\t\t\t\tnative: true\n\t\t\t}}\n\t\t\t{...rest}\n\t\t>\n\t\t\t \n\t\t\t{t('custom_os_public_y')} \n\t\t\t{t('custom_os_public_n')} \n\t\t \n\t);\n};\n\nexport default OSPublicSelector;\n\nOSPublicSelector.propTypes = {\n\tdisabled: PropTypes.bool,\n\trequired: PropTypes.bool,\n\tsetValue: PropTypes.func.isRequired,\n\tvalue: PropTypes.string\n};\n","import React from 'react';\nimport { useTranslation } from 'react-i18next';\nimport TextField from '@material-ui/core/TextField';\nimport PropTypes from 'prop-types';\n\nconst OSBetaSelector = ({ value, setValue, disabled = false, required = false, ...rest }) => {\n\tconst { t } = useTranslation();\n\n\treturn (\n\t\t setValue(e.target.value)}\n\t\t\tselect\n\t\t\tfullWidth\n\t\t\tInputLabelProps={{ shrink: !!value }}\n\t\t\tdisabled={disabled}\n\t\t\trequired={required}\n\t\t\tvariant='outlined'\n\t\t\tSelectProps={{\n\t\t\t\tnative: true\n\t\t\t}}\n\t\t\t{...rest}\n\t\t>\n\t\t\t{t('custom_os_beta_y')} \n\t\t\t{t('custom_os_beta_n')} \n\t\t \n\t);\n};\n\nexport default OSBetaSelector;\n\nOSBetaSelector.propTypes = {\n\tdisabled: PropTypes.bool,\n\trequired: PropTypes.bool,\n\tsetValue: PropTypes.func.isRequired,\n\tvalue: PropTypes.string\n};\n","import React from 'react';\nimport { useTranslation } from 'react-i18next';\nimport TextField from '@material-ui/core/TextField';\nimport PropTypes from 'prop-types';\n\nconst OSCPUSelector = ({ value, setValue, disabled = false, required = false, ...rest }) => {\n\tconst { t } = useTranslation();\n\n\treturn (\n\t\t setValue(e.target.value)}\n\t\t\tselect\n\t\t\tfullWidth\n\t\t\tInputLabelProps={{ shrink: !!value }}\n\t\t\tdisabled={disabled}\n\t\t\trequired={required}\n\t\t\tvariant='outlined'\n\t\t\tSelectProps={{\n\t\t\t\tnative: true\n\t\t\t}}\n\t\t\t{...rest}\n\t\t>\n\t\t\t \n\t\t\t{t('custom_os_cpu_x86_64')} \n\t\t\t{t('custom_os_cpu_arm64')} \n\t\t \n\t);\n};\n\nexport default OSCPUSelector;\n\nOSCPUSelector.propTypes = {\n\tdisabled: PropTypes.bool,\n\trequired: PropTypes.bool,\n\tsetValue: PropTypes.func.isRequired,\n\tvalue: PropTypes.string\n};\n","import PropTypes from 'prop-types';\nimport React, { useCallback, useEffect, useState } from 'react';\nimport { Avatar, Grid } from '@material-ui/core';\nimport { useTranslation } from 'react-i18next';\nimport uuid from '../../../utils/uuid';\nimport FormControl from '@material-ui/core/FormControl';\nimport InputLabel from '@material-ui/core/InputLabel';\nimport Input from '@material-ui/core/Input';\nimport FormHelperText from '@material-ui/core/FormHelperText';\nimport Button from './Button';\nimport defaultPicture from '../../../assets/img/shells_icon_white.svg';\nimport { useSetSnackbar } from '../../../hooks/useSnackbar';\n\nconst Picture = ({ value, setValue, defaultValue, label, disabled, pictureEditedChanged, square = false, required = false, reverseDisplay = false, helperText, minWidth = null, minHeight = null, previewStyle = {} }) => {\n\tconst { t } = useTranslation();\n\tconst setSnackbar = useSetSnackbar();\n\tconst [pictureSrc, setPictureSrc] = useState(defaultPicture);\n\tconst [pictureEdited, _setPictureEdited] = useState(false);\n\tconst [pictureKey, setPictureKey] = useState(uuid());\n\n\t// eslint-disable-next-line no-undef\n\tconst setPictureEdited = useCallback((v) => {\n\t\t_setPictureEdited(v);\n\t\tif (pictureEditedChanged)\n\t\t\tpictureEditedChanged(v);\n\t}, [_setPictureEdited, pictureEditedChanged]);\n\n\t// Update img src tag\n\tuseEffect(() => {\n\t\tconst isSame = value === defaultValue || (value && 'Media_Image__' in value && defaultValue && value.Media_Image__ === defaultValue.Media_Image__);\n\n\t\tif (value === null || 'Media_Image__' in value) {\n\t\t\tif (defaultValue && 'Url' in defaultValue)\n\t\t\t\tsetPictureSrc(defaultValue.Url);\n\t\t\telse {\n\t\t\t\tif (!defaultValue && value && 'Url' in value) {\n\t\t\t\t\tsetPictureSrc(value.Url);\n\t\t\t\t} else\n\t\t\t\t\tsetPictureSrc(defaultPicture);\n\t\t\t}\n\n\t\t\tif (isSame) {\n\t\t\t\tsetPictureEdited(false);\n\t\t\t\tsetPictureKey(uuid());\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\tconst fr = new FileReader();\n\t\tfr.onload = function () {\n\t\t\tconst img = new Image();\n\n\t\t\timg.onload = function () {\n\t\t\t\tlet error = null;\n\t\t\t\tif ((minWidth && minHeight) && (img.width < minWidth || img.height < minHeight)) {\n\t\t\t\t\terror = ['picture_chooser_invalid_size', { minHeight: minHeight, minWidth: minWidth }];\n\t\t\t\t} else if (minWidth && img.width < minWidth) {\n\t\t\t\t\terror = ['picture_chooser_invalid_size_width', { minWidth: minWidth }];\n\t\t\t\t} else if (minHeight && img.height < minHeight) {\n\t\t\t\t\terror = ['picture_chooser_invalid_size_height', { minHeight: minHeight }];\n\t\t\t\t} else if (square && img.width !== img.height) {\n\t\t\t\t\terror = ['picture_chooser_invalid_square'];\n\t\t\t\t}\n\n\t\t\t\tif (error) {\n\t\t\t\t\tsetSnackbar(t(...error), 'error');\n\t\t\t\t\tonRevertPicture();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tsetPictureSrc(fr.result);\n\t\t\t};\n\n\t\t\timg.src = fr.result; // is the data URL because called with readAsDataURL\n\n\t\t};\n\t\tfr.readAsDataURL(value);\n\n\t\t// eslint-disable-next-line\n\t}, [value, defaultValue, setPictureEdited, minWidth, minHeight]);\n\n\tconst onPictureChange = (e) => {\n\t\tif (e.target.files.length < 1) {\n\t\t\tsetValue(defaultValue);\n\t\t} else {\n\t\t\tsetValue(e.target.files[0]);\n\t\t}\n\n\t\tsetPictureEdited(true);\n\t};\n\n\tconst onRevertPicture = () => {\n\t\tsetValue(defaultValue);\n\t\tsetPictureEdited(false);\n\t\tsetPictureKey(uuid());\n\t};\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t \n\t\t\t \n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{label} \n\t\t\t\t\t \n\t\t\t\t\t{helperText && {helperText} }\n\t\t\t\t \n\t\t\t\t{pictureEdited &&\n\t\t\t\t\n\t\t\t\t\t{t('cancel_edit_picture')}\n\t\t\t\t }\n\t\t\t \n\t\t \n\t);\n};\n\nexport default Picture;\n\nPicture.propTypes = {\n\tdefaultValue: PropTypes.any,\n\tdisabled: PropTypes.any,\n\thelperText: PropTypes.any,\n\tlabel: PropTypes.any,\n\tminHeight: PropTypes.number,\n\tminWidth: PropTypes.number,\n\tpictureEditedChanged: PropTypes.any,\n\tpreviewStyle: PropTypes.object,\n\trequired: PropTypes.bool,\n\treverseDisplay: PropTypes.bool,\n\tsetValue: PropTypes.func.isRequired,\n\tsquare: PropTypes.bool,\n\tvalue: PropTypes.any\n};\n","import PropTypes from 'prop-types';\nimport { useTranslation } from 'react-i18next';\nimport React, { useEffect } from 'react';\nimport Grid from '@material-ui/core/Grid';\nimport TextField from '@material-ui/core/TextField';\nimport OSFamilySelector from '../../core/input/OSFamilySelector';\nimport OSBootSelector from '../../core/input/OSBootSelector';\nimport OSPublicSelector from '../../core/input/OSPublicSelector';\nimport OSBetaSelector from '../../core/input/OSBetaSelector';\nimport OSCPUSelector from '../../core/input/OSCPUSelector';\nimport Picture from '../../core/input/Picture';\nimport OSPurposeSelector from '../../core/input/OSPurposeSelector';\n\nconst Form = ({ data, setData, setIsValid, disabled = false }) => {\n\tconst { t } = useTranslation();\n\n\tconst createChangeHandler = (key, property = 'value') => e => {\n\t\tsetData({ ...data, [key]: (property ? e.target[property] : e) });\n\t};\n\n\tconst getValue = (key, def = '') => {\n\t\tif (!(key in (data ?? {}))) return def;\n\t\treturn data[key];\n\t};\n\n\tuseEffect(() => {\n\t\tif (!('Name' in data ?? {}) || !data['Name'].trim()) setIsValid(false);\n\t\telse if (!('CPU' in data ?? {}) || !data['CPU']) setIsValid(false);\n\t\telse if (!('Boot' in data ?? {}) || !data['Boot']) setIsValid(false);\n\t\telse if (!('Family' in data ?? {}) || !data['Family']) setIsValid(false);\n\t\telse if ((!('Public' in data ?? {}) || !data['Public'])) setIsValid(false);\n\t\telse setIsValid(true);\n\t}, [data, setIsValid]);\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t \n\t\t\t \n\t\t\t\n\t\t\t\t \n\t\t\t \n\t\t\t\n\t\t\t\t \n\t\t\t \n\t\t\t\n\t\t\t\t \n\t\t\t \n\t\t\t\n\t\t\t\t \n\t\t\t \n\t\t\t\n\t\t\t\t \n\t\t\t \n\t\t\t\n\t\t\t\t \n\t\t\t \n\t\t\t\n\t\t\t\t \n\t\t\t \n\t\t\t\n\t\t\t\t \n\t\t\t \n\t\t\t\n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default Form;\n\nForm.propTypes = {\n\tdata: PropTypes.object.isRequired,\n\tdisabled: PropTypes.bool,\n\tsetData: PropTypes.func.isRequired,\n\tsetIsValid: PropTypes.func.isRequired\n};\n","import Progress from '@material-ui/core/LinearProgress';\nimport withStyles from '@material-ui/core/styles/withStyles';\n\nexport default withStyles(() => ({\n\troot: {\n\t\twidth: '100%',\n\t\theight: 10,\n\t},\n}))(Progress);\n","import PropTypes from 'prop-types';\nimport React, {\n\tuseEffect,\n\tuseState\n} from 'react';\nimport Dialog from '@material-ui/core/Dialog';\nimport DialogTitle from '@material-ui/core/DialogTitle';\nimport DialogContent from '@material-ui/core/DialogContent';\nimport DialogContentText from '@material-ui/core/DialogContentText';\nimport Grid from '@material-ui/core/Grid';\nimport DialogActions from '@material-ui/core/DialogActions';\nimport Button from '../../core/input/Button';\nimport {\n\tTrans,\n\tuseTranslation\n} from 'react-i18next';\nimport { getCustomOsEditRoute } from '../../RouteController/Factory';\nimport { useHistory } from 'react-router-dom';\nimport uuid from '../../../utils/uuid';\nimport FormControl from '@material-ui/core/FormControl';\nimport InputLabel from '@material-ui/core/InputLabel';\nimport Input from '@material-ui/core/Input';\nimport FormHelperText from '@material-ui/core/FormHelperText';\nimport { getLocale } from '@karpeleslab/klbfw';\nimport RichAlertTrans from '../../core/feedback/RichAlertTrans';\nimport Tab from '@material-ui/core/Tab';\nimport Tabs from '@material-ui/core/Tabs';\nimport useMediaQuery from '@material-ui/core/useMediaQuery';\nimport Panel from '../../layout/Container/tab/Panel';\nimport ShellSelector from '../../core/input/ShellSelector';\nimport Form from './Form';\nimport {\n\tuseOperatingSystemCreateEmpty,\n\tuseOperatingSystemCreateFromFile,\n\tuseOperatingSystemCreateFromShell\n} from '@karpeleslab/klb-react-services';\nimport LinearProgress from '../../core/feedback/LinearProgress';\nimport RichAlert from '../../core/feedback/RichAlert';\nimport { fileExtensionIs } from '../../../utils/misc';\n\nconst FROM_SHELL_TAB = 0;\nconst FROM_FILE_TAB = 1;\nconst EMPTY_OS_TAB = 2;\n\nconst INITIAL_DATA = { Purpose: 'unknown', Beta: 'Y' };\n\nconst CreateDialog = ({ open, setOpen }) => {\n\tconst { t } = useTranslation();\n\tconst history = useHistory();\n\n\tconst [createFromFile, creatingFromFile, progress] = useOperatingSystemCreateFromFile();\n\tconst [createFromShell, creatingFromShell] = useOperatingSystemCreateFromShell();\n\tconst [createEmpty, creatingEmpty] = useOperatingSystemCreateEmpty();\n\n\tconst [tab, setTab] = useState(FROM_SHELL_TAB);\n\n\tconst [file, setFile] = useState(null);\n\tconst [fileKey, setFileKey] = useState(uuid());\n\tconst [shell, setShell] = useState();\n\t// This will control, the input to display it red if the file is not a .shells,\n\t// We default to true, because when there is no selected file we don't want to have the 'red' error outline to the input\n\tconst [isFileValid, setIsFileValid] = useState(true);\n\n\tconst [data, setData] = useState(INITIAL_DATA);\n\n\tconst [isValid, setIsValid] = useState(false);\n\tconst [saveEnabled, setSaveEnabled] = useState(false);\n\n\tconst isMobile = useMediaQuery(theme => theme.breakpoints.down('xs'));\n\n\tconst handleTabChange = (event, newValue) => {\n\t\tsetTab(newValue);\n\t};\n\n\tconst reset = () => {\n\t\tsetTab(FROM_SHELL_TAB);\n\t\tsetShell(undefined);\n\t\tsetFileKey(uuid());\n\t\tsetFile(null);\n\t\tsetData(INITIAL_DATA);\n\t\tsetIsFileValid(true);\n\t};\n\n\tconst handleClose = () => {\n\t\tsetOpen(false);\n\t};\n\n\tconst handleFile = e => {\n\t\tif (e.target.files.length > 0)\n\t\t\tsetFile(e.target.files[0]);\n\t};\n\n\tuseEffect(() => {\n\t\tif (!file) setIsFileValid(true); // No file so we default to true\n\t\telse setIsFileValid(fileExtensionIs(file, 'shells'));\n\t}, [file, setIsFileValid]);\n\n\tconst handleCreate = e => {\n\t\te.preventDefault();\n\t\tlet promise;\n\n\t\tconst names = { [getLocale()]: data['Name'].trim() };\n\t\tconst descriptions = { [getLocale()]: (data['Description'] ?? '').trim() };\n\t\tconst shortDescriptions = { [getLocale()]: (data['Short_Description'] ?? '').trim() };\n\t\tconst family = data.Family;\n\t\tconst boot = data.Boot;\n\t\tconst cpu = data.CPU;\n\t\tconst icon = data['New_Media_Image'] ?? null;\n\t\tconst isPublic = data['Public'] ?? 'N';\n\t\tconst purpose = data['Purpose'] ?? 'unknown';\n\t\tconst beta = data['Beta'] ?? 'Y';\n\n\t\tif (tab === FROM_FILE_TAB) {\n\t\t\tpromise = createFromFile(file, names, family, boot, cpu, isPublic, descriptions, shortDescriptions, purpose, beta, icon);\n\t\t} else if (tab === FROM_SHELL_TAB) {\n\t\t\tpromise = createFromShell(shell.Shell_Volume__, names, family, boot, cpu, isPublic, descriptions, shortDescriptions, purpose, beta, icon);\n\t\t} else {\n\t\t\tpromise = createEmpty(names, family, boot, cpu, isPublic, descriptions, shortDescriptions, purpose, beta, icon);\n\t\t}\n\n\t\tpromise.then(d => history.push(getCustomOsEditRoute(d.Shell_OS__)));\n\t};\n\n\tuseEffect(() => {\n\t\tif (\n\t\t\t!isValid ||\n\t\t\t(tab === FROM_SHELL_TAB && !shell) ||\n\t\t\t(tab === FROM_FILE_TAB && (!file || !isFileValid))\n\t\t) {\n\t\t\tsetSaveEnabled(false);\n\t\t\treturn;\n\t\t}\n\n\t\tsetSaveEnabled(true);\n\t}, [setSaveEnabled, file, data, isValid, shell, isFileValid]);\n\n\treturn (\n\t\t reset()}\n\t\t\tmaxWidth='xl'\n\t\t\tfullWidth\n\t\t>\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{t('dialog_create_os_title')}\n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\tsample \n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\tsample\n\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\tsample \n\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\tsample\n\t\t\t\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t{t('custom_os_file_label')}\n\t\t\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t{t(isFileValid ? 'custom_os_file_helperText' : 'custom_os_file_error_helperText')}\n\t\t\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t\t\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t{creatingFromFile && }\n\t\t\t\t\t\n\t\t\t\t\t\t{t('close_btn')}\n\t\t\t\t\t \n\t\t\t\t\t\n\t\t\t\t\t\t{t('create_btn')}\n\t\t\t\t\t \n\t\t\t\t \n\n\t\t\t \n\n\t\t \n\t);\n};\n\nexport default CreateDialog;\n\nCreateDialog.propTypes = {\n\topen: PropTypes.bool.isRequired,\n\tsetOpen: PropTypes.func.isRequired\n};\n","import React, { useState } from 'react';\nimport PageContainer from '../../components/layout/Container/PageContainer';\nimport { useTranslation } from 'react-i18next';\nimport { Grid } from '@material-ui/core';\nimport OperatingSystemTable from '../../components/common/OperatingSystem/OperatingSystemTable';\nimport Button from '../../components/core/input/Button';\nimport AddIcon from '@material-ui/icons/Add';\nimport Toolbar from '../../components/core/typography/Toolbar';\nimport CreateDialog from '../../components/common/OperatingSystem/CreateDialog';\n\nconst CustomOSList = () => {\n\tconst { t } = useTranslation();\n\tconst [showCreate, setShowCreate] = useState(false);\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t setShowCreate(true)}\n\t\t\t\t\t\t\tsize='small'\n\t\t\t\t\t\t\tvariant='contained'\n\t\t\t\t\t\t\tcolor='primary'\n\t\t\t\t\t\t\tstartIcon={ }\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{t('create_btn')}\n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t \n\t\t\t\t \n\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default CustomOSList;\n","import PropTypes from 'prop-types';\nimport React from 'react';\nimport { Grid } from '@material-ui/core';\nimport RichAlertTrans from '../../core/feedback/RichAlertTrans';\nimport ClipboardCopyTextField from '../../core/input/ClipboardCopyTextField';\n\nconst OperatingSystemShare = ({ os }) => {\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t \n\t\t\t \n\n\t\t\t{os.Public !== 'Y' &&\n\t\t\t\n\t\t\t\t \n\t\t\t \n\t\t\t}\n\n\t\t\t\n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default OperatingSystemShare;\n\nOperatingSystemShare.propTypes = {\n\tos: PropTypes.object.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React, { useEffect, useState } from 'react';\nimport Grid from '@material-ui/core/Grid';\nimport { deepCopy } from '../../../utils/misc';\nimport Form from './Form';\nimport Button from '../../core/input/Button';\nimport { useTranslation } from 'react-i18next';\nimport { getLocale } from '@karpeleslab/klbfw';\nimport { useUpdateOperatingSystem } from '@karpeleslab/klb-react-services';\n\nconst EditForm = ({ os, refresh }) => {\n\tconst [data, setData] = useState(deepCopy(os));\n\tconst [isValid, setIsValid] = useState(false);\n\tconst [saveEnabled, setSaveEnabled] = useState(false);\n\tconst { t } = useTranslation();\n\tconst [update, updating] = useUpdateOperatingSystem(os.Shell_OS__);\n\n\tuseEffect(() => {\n\t\tsetData(deepCopy(os));\n\t}, [os, setData]);\n\n\tconst saveHandler = () => {\n\t\t// We need to format the name\n\t\t// because on the backend it use multilingual input that is not supported yet on the frontend\n\t\tconst icon = data['New_Media_Image'] ?? null;\n\t\tconst cpy = deepCopy(data);\n\t\tcpy['Name'] = { [getLocale()]: cpy.Name.trim() };\n\t\tcpy['Description'] = { [getLocale()]: (cpy.Description ?? '').trim() };\n\t\tcpy['Short_Description'] = { [getLocale()]: (cpy.Short_Description ?? '').trim() };\n\t\tupdate(cpy, icon).then(refresh);\n\t};\n\n\tuseEffect(() => {\n\t\tif (\n\t\t\t(!!data['New_Media_Image'] && data['New_Media_Image'] instanceof File) ||\n\t\t\tdata['Public'] !== os['Public'] ||\n\t\t\tdata['Name'] !== os['Name'] ||\n\t\t\tdata['Description'] !== os['Description'] ||\n\t\t\tdata['Short_Description'] !== os['Short_Description'] ||\n\t\t\tdata['Family'] !== os['Family'] ||\n\t\t\tdata['Boot'] !== os['Boot'] ||\n\t\t\tdata['CPU'] !== os['CPU'] ||\n\t\t\tdata['Purpose'] !== os['Purpose'] ||\n\t\t\tdata['Beta'] !== os['Beta']\n\t\t)\n\t\t\tsetSaveEnabled(true);\n\t\telse\n\t\t\tsetSaveEnabled(false);\n\t}, [data, os, setSaveEnabled]);\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t \n\t\t\t \n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t{t('save_btn')}\n\t\t\t\t\t \n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default EditForm;\n\nEditForm.propTypes = {\n\tos: PropTypes.object.isRequired,\n\trefresh: PropTypes.func.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React, { useEffect, useState } from 'react';\nimport Dialog from '@material-ui/core/Dialog';\nimport DialogTitle from '@material-ui/core/DialogTitle';\nimport DialogContent from '@material-ui/core/DialogContent';\nimport DialogContentText from '@material-ui/core/DialogContentText';\nimport Grid from '@material-ui/core/Grid';\nimport DialogActions from '@material-ui/core/DialogActions';\nimport { Trans, useTranslation } from 'react-i18next';\nimport FormControl from '@material-ui/core/FormControl';\nimport InputLabel from '@material-ui/core/InputLabel';\nimport Input from '@material-ui/core/Input';\nimport FormHelperText from '@material-ui/core/FormHelperText';\nimport Tab from '@material-ui/core/Tab';\nimport Tabs from '@material-ui/core/Tabs';\nimport useMediaQuery from '@material-ui/core/useMediaQuery';\nimport uuid from '../../../../utils/uuid';\nimport RichAlertTrans from '../../../core/feedback/RichAlertTrans';\nimport Panel from '../../../layout/Container/tab/Panel';\nimport ShellSelector from '../../../core/input/ShellSelector';\nimport Button from '../../../core/input/Button';\nimport {\n\tuseOperatingSystemAddImageFromFile,\n\tuseOperatingSystemAddImageFromShell\n} from '@karpeleslab/klb-react-services';\nimport LinearProgress from '../../../core/feedback/LinearProgress';\nimport RichAlert from '../../../core/feedback/RichAlert';\nimport { fileExtensionIs } from '../../../../utils/misc';\n\nconst FROM_SHELL_TAB = 0;\nconst FROM_FILE_TAB = 1;\n\nconst AddVersionDialog = ({ open, setOpen, os, refresh, canAddNewVersion = true }) => {\n\tconst { t } = useTranslation();\n\n\tconst [createFromFile, creatingFromFile, progress] = useOperatingSystemAddImageFromFile(os?.Shell_OS__);\n\tconst [createFromShell, creatingFromShell] = useOperatingSystemAddImageFromShell(os?.Shell_OS__);\n\n\tconst [tab, setTab] = useState(FROM_SHELL_TAB);\n\n\tconst [file, setFile] = useState(null);\n\tconst [fileKey, setFileKey] = useState(uuid());\n\tconst [shell, setShell] = useState();\n\t// This will control, the input to display it red if the file is not a .shells,\n\t// We default to true, because when there is no selected file we don't want to have the 'red' error outline to the input\n\tconst [isFileValid, setIsFileValid] = useState(true);\n\n\tconst [saveEnabled, setSaveEnabled] = useState(false);\n\n\tconst isMobile = useMediaQuery(theme => theme.breakpoints.down('xs'));\n\n\tconst handleTabChange = (event, newValue) => {\n\t\tsetTab(newValue);\n\t};\n\n\tconst reset = () => {\n\t\tsetTab(FROM_SHELL_TAB);\n\t\tsetShell(undefined);\n\t\tsetFileKey(uuid());\n\t\tsetFile(null);\n\t\tsetIsFileValid(true);\n\t};\n\n\tconst handleClose = () => {\n\t\tsetOpen(false);\n\t};\n\n\tconst handleFile = e => {\n\t\tif (e.target.files.length > 0)\n\t\t\tsetFile(e.target.files[0]);\n\t};\n\n\tconst handleCreate = e => {\n\t\te.preventDefault();\n\n\t\tlet promise;\n\t\tif (tab === FROM_FILE_TAB) {\n\t\t\tpromise = createFromFile(file);\n\t\t} else {\n\t\t\tpromise = createFromShell(shell.Shell_Volume__);\n\t\t}\n\n\t\tpromise.then(() => refresh()).then(handleClose);\n\t};\n\n\tuseEffect(() => {\n\t\tif (!file) setIsFileValid(true); // No file so we default to true\n\t\telse setIsFileValid(fileExtensionIs(file, 'shells'));\n\t}, [file, setIsFileValid]);\n\n\tuseEffect(() => {\n\t\tif (\n\t\t\t(tab === FROM_SHELL_TAB && !shell) ||\n\t\t\t(tab === FROM_FILE_TAB && (!file || !isFileValid))\n\t\t) {\n\t\t\tsetSaveEnabled(false);\n\t\t\treturn;\n\t\t}\n\n\t\tsetSaveEnabled(true);\n\t}, [setSaveEnabled, file, tab, shell, isFileValid]);\n\n\treturn (\n\t\t reset()}\n\t\t\tmaxWidth='lg'\n\t\t\tfullWidth\n\t\t>\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{t('dialog_os_add_version_title')}\n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t\t\n\t\t\t\t\t\t{!canAddNewVersion &&\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t\t}\n\t\t\t\t\t\t{canAddNewVersion && \n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t \n\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t }\n\t\t\t\t\t\t{canAddNewVersion && \n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\tsample \n\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\tsample\n\t\t\t\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t{t('custom_os_file_label')}\n\t\t\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t{t(isFileValid ? 'custom_os_file_helperText' : 'custom_os_file_error_helperText')}\n\t\t\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t \n\t\t\t\t\t\t }\n\t\t\t\t\t \n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t{creatingFromFile && }\n\t\t\t\t\t\n\t\t\t\t\t\t{t('close_btn')}\n\t\t\t\t\t \n\t\t\t\t\t{canAddNewVersion && \n\t\t\t\t\t\t{t('create_btn')}\n\t\t\t\t\t \n\t\t\t\t\t}\n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default AddVersionDialog;\n\nAddVersionDialog.propTypes = {\n\tcanAddNewVersion: PropTypes.bool,\n\topen: PropTypes.bool.isRequired,\n\tos: PropTypes.object.isRequired,\n\trefresh: PropTypes.func.isRequired,\n\tsetOpen: PropTypes.func.isRequired\n};\n","import PropTypes from 'prop-types';\nimport { useTranslation } from 'react-i18next';\nimport React, { useEffect, useState } from 'react';\nimport Table from '../../../core/data/table/Table';\nimport TableDefinition from '../../../core/data/table/TableDefinition';\nimport DateUtil from '../../../core/data/Date/DateUtil';\nimport AddIcon from '@material-ui/icons/Add';\nimport Button from '../../../core/input/Button';\nimport AddVersionDialog from './AddVersionDialog';\nimport moment from 'moment';\nimport { Grid } from '@material-ui/core';\nimport RichAlertTrans from '../../../core/feedback/RichAlertTrans';\nimport Chip from '@material-ui/core/Chip';\nimport { getShellViewRoute } from '../../../RouteController/Factory';\nimport { useOperatingSystemImages } from '@karpeleslab/klb-react-services';\n\nconst OSImageTable = ({ os }) => {\n\tconst { t } = useTranslation();\n\tconst [images, fetch, loading] = useOperatingSystemImages(os.Shell_OS__);\n\tconst [showCreate, setShowCreate] = useState(false);\n\n\n\tconst [canAddNewVersion, setCanAddNewVersion] = useState(false);\n\tconst [hasValidImage, setHasValidImage] = useState(false);\n\n\t// The Image disk version is formatted as follow: YYYYMMDD (UTC)\n\t// It should be unique in the database, it means we can only add 1 Disk Image per UTC day\n\tuseEffect(() => {\n\t\tif (!images) return;\n\t\tconst today = moment.utc().format('YYYYMMDD');\n\n\t\tlet canAdd = true;\n\t\tlet hasValid = false;\n\t\tfor (let i = 0; i < (images.data ?? []).length; i++) {\n\t\t\tif (images.data[i].Version === today) {\n\t\t\t\tcanAdd = false;\n\t\t\t}\n\t\t\tif (images.data[i].Status === 'valid') hasValid = true;\n\t\t}\n\t\tsetCanAddNewVersion(canAdd);\n\t\tsetHasValidImage(hasValid);\n\t}, [images]);\n\n\treturn (\n\t\t\n\t\t\t{!hasValidImage && \n\t\t\t\t \n\t\t\t \n\t\t\t}\n\t\t\t\n\t\t\t\t setShowCreate(true)}\n\t\t\t\t\t\t\t\tsize=\"small\"\n\t\t\t\t\t\t\t\tvariant=\"contained\"\n\t\t\t\t\t\t\t\tcolor=\"primary\"\n\t\t\t\t\t\t\t\tstartIcon={ }\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{t('add_os_image_version_btn')}\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t]\n\t\t\t\t\t}\n\t\t\t\t\ttitle={t('custom_os_image_title')}\n\t\t\t\t\tfetch={fetch}\n\t\t\t\t\tdata={images}\n\t\t\t\t\tsearch={false}\n\t\t\t\t\tloading={loading}\n\t\t\t\t\tpaperProps={{ elevation: 0 }}\n\t\t\t\t>\n\t\t\t\t\t\n\t\t\t\t\t\t{image => {\n\t\t\t\t\t\t\tif (image.Source !== 'volume' || !image.Shell_Volume) return image.Filename;\n\t\t\t\t\t\t\tif (!image.Shell_Volume.Shell)\n\t\t\t\t\t\t\t\treturn ;\n\t\t\t\t\t\t\treturn ;\n\t\t\t\t\t\t}}\n\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t\t\n\t\t\t\t\t\t{image =>\n\t\t\t\t\t\t\timage.Hash ?\n\t\t\t\t\t\t\t\timage.Hash :\n\t\t\t\t\t\t\t\t }\n\t\t\t\t\t \n\t\t\t\t\t\n\t\t\t\t\t\t{image => }\n\t\t\t\t\t \n\n\t\t\t\t
\n\t\t\t \n\n\t\t\t \n\t\t \n\t);\n};\n\nexport default OSImageTable;\n\nOSImageTable.propTypes = {\n\tos: PropTypes.object.isRequired\n};\n","import React from 'react';\nimport Dialog from '@material-ui/core/Dialog';\nimport DialogContentText from '@material-ui/core/DialogContentText';\nimport DialogContent from '@material-ui/core/DialogContent';\nimport { useTranslation } from 'react-i18next';\nimport DialogTitle from '@material-ui/core/DialogTitle';\nimport DialogActions from '@material-ui/core/DialogActions';\nimport PropTypes from 'prop-types';\nimport { useHistory } from 'react-router';\nimport { getCustomOsRoute } from '../../RouteController/Factory';\nimport Button from '../../core/input/Button';\nimport RichAlertTrans from '../../core/feedback/RichAlertTrans';\nimport { useOperatingSystemDelete } from '@karpeleslab/klb-react-services';\n\nconst DeleteDialog = ({ os, open, setOpen }) => {\n\tconst { t } = useTranslation();\n\tconst [deleteOs, deleting] = useOperatingSystemDelete(os.Shell_OS__);\n\tconst history = useHistory();\n\n\tconst handleClose = () => {\n\t\tsetOpen(false);\n\t};\n\n\tconst handleDelete = e => {\n\t\te.preventDefault();\n\n\t\tdeleteOs()\n\t\t\t.then(handleClose)\n\t\t\t.then(() => history.push(getCustomOsRoute()));\n\t};\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t{t('dialog_delete_os_title')}\n\t\t\t \n\t\t\t\n\t\t\t\t\n\t\t\t\t\t \n\t\t\t\t \n\t\t\t \n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{t('close_btn')}\n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t{t('delete_btn')}\n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default DeleteDialog;\n\nDeleteDialog.propTypes = {\n\tos: PropTypes.object,\n\topen: PropTypes.bool.isRequired,\n\tsetOpen: PropTypes.func.isRequired\n};\n","import React, { useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { useParams } from 'react-router';\nimport PageLoader from '../../components/layout/Loader/PageLoader';\nimport PageNotFound from '../System/PageNotFound';\nimport PageContainer from '../../components/layout/Container/PageContainer';\nimport { Grid } from '@material-ui/core';\nimport Toolbar from '../../components/core/typography/Toolbar';\nimport { getCustomOsRoute } from '../../components/RouteController/Factory';\nimport OperatingSystemShare from '../../components/common/OperatingSystem/OperatingSystemShare';\nimport EditForm from '../../components/common/OperatingSystem/EditForm';\nimport OSImageTable from '../../components/common/OperatingSystem/Image/OSImageTable';\nimport { useOperatingSystem } from '@karpeleslab/klb-react-services';\nimport Button from '../../components/core/input/Button';\nimport DeleteDialog from '../../components/common/OperatingSystem/DeleteDialog';\n\nconst CustomOsEdit = () => {\n\tconst { t } = useTranslation();\n\tconst { osId } = useParams();\n\tconst [os, refresh] = useOperatingSystem(osId);\n\tconst [showDelete, setShowDelete] = useState(false);\n\n\tif (!os) return ;\n\tif (!os.data) return ;\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t \n\t\t\t\t \n\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t \n\n\t\t\t\t\n\t\t\t\t\t \n\t\t\t\t \n\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t \n\t\t\t\t{os.data.Is_Deletable &&\n\t\t\t\t\n\t\t\t\t\t setShowDelete(true)}\n\t\t\t\t\t>\n\t\t\t\t\t\t{t('delete_btn')}\n\t\t\t\t\t \n\t\t\t\t \n\t\t\t\t}\n\t\t\t \n\t\t\t{os.data.Is_Deletable && }\n\t\t \n\t);\n};\n\nexport default CustomOsEdit;\n","import React, { useContext, useEffect, useState } from 'react';\nimport PageContainer from '../../components/layout/Container/PageContainer';\nimport Helmet from 'react-helmet';\nimport { Grid } from '@material-ui/core';\nimport EmptyState from '../../components/core/feedback/State/Empty';\nimport { Trans, useTranslation } from 'react-i18next';\nimport Graphic from '../../assets/img/modeGraphic.svg';\nimport { ModeContext } from '../../context/ModeContext';\nimport { useHistory, useLocation, useParams } from 'react-router';\nimport { getShellsRoute } from '../../components/RouteController/Factory';\nimport { useSetSnackbar } from '../../hooks/useSnackbar';\nimport { useCookies } from 'react-cookie';\nimport queryString from 'query-string';\nimport { getCookiesOptions } from '../../utils/misc';\n\nconst SwitchMode = () => {\n\tconst [, setCookie] = useCookies(['mode']);\n\tconst { mode } = useParams();\n\tconst { t } = useTranslation();\n\tconst [, setMode] = useContext(ModeContext);\n\tconst history = useHistory();\n\tconst setSnackbar = useSetSnackbar();\n\tconst [returnTo, setReturnTo] = useState(getShellsRoute());\n\tconst location = useLocation();\n\n\n\tuseEffect(() => {\n\t\tconst params = queryString.parse(location.search);\n\t\tif (!params.to) setReturnTo(getShellsRoute());\n\t\telse setReturnTo(decodeURIComponent(params.to));\n\n\t}, [location, setReturnTo]);\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t{ /* https://devhints.io/html-meta */}\n\t\t\t\t{t('mode_switch_title', { mode: t(`${mode.toLowerCase()}_label`) })} \n\t\t\t \n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\t\tsample \n\t\t\t\t\t\t\t\tsample \n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\tsample \n\t\t\t\t\t\t\t\t \n\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t}\n\t\t\t\t\t\tgraphic={Graphic}\n\t\t\t\t\t\taction={{\n\t\t\t\t\t\t\ttitle: t('mode_change_btn', { mode: t(`${mode.toLowerCase()}_label`) }),\n\t\t\t\t\t\t\tonClick: e => {\n\t\t\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\t\t\tsetCookie('mode', mode.toUpperCase(), getCookiesOptions());\n\t\t\t\t\t\t\t\tsetMode(mode.toUpperCase());\n\t\t\t\t\t\t\t\tsetSnackbar(t('switched_to_mode', { mode: t(`${mode.toLowerCase()}_label`) }), 'success');\n\t\t\t\t\t\t\t\thistory.push(returnTo);\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}}\n\t\t\t\t\t/>\n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default SwitchMode;\n","import PropTypes from 'prop-types';\nimport React from 'react';\nimport Grid from '@material-ui/core/Grid';\nimport DateUtil from '../../core/data/Date/DateUtil';\nimport { IconButton } from '@material-ui/core';\nimport GetAppIcon from '@material-ui/icons/GetApp';\nimport { Link } from 'react-router-dom';\nimport { getOrderViewRoute } from '../../RouteController/Factory';\nimport VisibilityIcon from '@material-ui/icons/Visibility';\nimport { useTranslation } from 'react-i18next';\n\nconst OrderRowMobile = ({ order }) => {\n\tconst { t } = useTranslation();\n\n\treturn (\n\t\t\n\t\t\t{order.Invoice_Number} \n\t\t\t{`${order.Status ?? '-'}`} \n\n\t\t\t{t('history_order_date')} \n\t\t\t \n\t\t\t{t('history_paid_date')} \n\t\t\t \n\t\t\t{`${order.Total.display ?? '-'}`} \n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t\t\n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n\n};\n\nexport default OrderRowMobile;\n\nOrderRowMobile.propTypes = {\n\torder: PropTypes.object.isRequired\n};\n","import React from 'react';\nimport { useTranslation } from 'react-i18next';\nimport TableDefinition from '../../core/data/table/TableDefinition';\nimport Table from '../../core/data/table/Table';\nimport Button from '../../core/input/Button';\nimport VisibilityIcon from '@material-ui/icons/Visibility';\nimport { Link } from 'react-router-dom';\nimport { getOrderViewRoute } from '../../RouteController/Factory';\nimport DateUtil from '../../core/data/Date/DateUtil';\nimport GetAppIcon from '@material-ui/icons/GetApp';\nimport Grid from '@material-ui/core/Grid';\nimport useMediaQuery from '@material-ui/core/useMediaQuery';\nimport OrderRowMobile from './OrderRowMobile';\nimport { useOrders } from '@karpeleslab/klb-react-services';\n\nconst OrdersTable = () => {\n\tconst { t } = useTranslation();\n\tconst [orders, fetch, loading] = useOrders();\n\tconst isMobile = useMediaQuery(theme => theme.breakpoints.down('xs'));\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t{order => {\n\t\t\t\t\tif (!isMobile) return order.Invoice_Number;\n\t\t\t\t\treturn ;\n\t\t\t\t}}\n\t\t\t \n\n\t\t\t{!isMobile && \n\t\t\t\t{order => }\n\t\t\t }\n\n\t\t\t{!isMobile && \n\t\t\t\t{order => }\n\t\t\t }\n\n\t\t\t{!isMobile && \n\t\t\t\t{order => order.Status ?? '-'}\n\t\t\t }\n\n\t\t\t{!isMobile && \n\t\t\t\t{order => order.Total.display ?? '-'}\n\t\t\t }\n\n\t\t\t{!isMobile && \n\t\t\t\t{order =>\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t }\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{t('history_dl_pdf')}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t \n\t\t\t\t\t\t\n\t\t\t\t\t\t\t }\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{t('view_btn')}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t}\n\t\t\t }\n\n\t\t
\n\t);\n};\n\nexport default OrdersTable;\n","import PropTypes from 'prop-types';\nimport React, { useEffect, useState } from 'react';\nimport { deepCopy } from '../../../../utils/misc';\nimport { Grid } from '@material-ui/core';\nimport { Title } from '../../../core/typography/Title';\nimport Form from '../Location/Form';\nimport Button from '../../../core/input/Button';\nimport { useTranslation } from 'react-i18next';\nimport { useUserBillingUpdate, useUserLocationUpdate } from '@karpeleslab/klb-react-services';\n\n\nconst UpdateLocationForm = ({ billing, setBilling, location, setLocation }) => {\n\tconst { t } = useTranslation();\n\tconst [formValid, setFormValid] = useState(false);\n\tconst [saveEnabled, setSaveEnabled] = useState(false);\n\tconst [data, setData] = useState(deepCopy(location));\n\tconst [updateLocation, updatingLocation] = useUserLocationUpdate(location.User_Location__);\n\tconst [updateBilling, updatingBilling] = useUserBillingUpdate(billing.User_Billing__);\n\n\tuseEffect(() => {\n\t\tsetData(deepCopy(location));\n\t}, [location, setData]);\n\n\tuseEffect(() => {\n\t\tif (formValid && (\n\t\t\tlocation.First_Name !== (data.First_Name ?? '').trim() ||\n\t\t\tlocation.Last_Name !== (data.Last_Name ?? '').trim() ||\n\t\t\tlocation.Zip !== (data.Zip ?? '').trim() ||\n\t\t\tlocation.Country__ !== (data.Country__ ?? '').trim()\n\t\t))\n\t\t\tsetSaveEnabled(true);\n\t\telse\n\n\t\t\tsetSaveEnabled(false);\n\t}, [location, data, formValid, setSaveEnabled]);\n\n\tconst saveHandler = () => {\n\t\tconst toSave = {\n\t\t\tFirst_Name: data.First_Name.trim(),\n\t\t\tLast_Name: data.Last_Name.trim(),\n\t\t\tZip: data.Zip.trim(),\n\t\t\tCountry__: data.Country__,\n\t\t};\n\t\tupdateLocation(toSave)\n\t\t\t.then(location => {\n\t\t\t\tsetLocation(location);\n\t\t\t\treturn location;\n\t\t\t})\n\t\t\t.then(location => {\n\t\t\t\treturn updateBilling({ User_Location__: location.User_Location__ });\n\t\t\t})\n\t\t\t.then(billing => {\n\t\t\t\tsetBilling(billing);\n\t\t\t});\n\t};\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t{t('billing_user_location_update_title')} \n\t\t\t \n\n\t\t\t\n\t\t\t\t \n\t\t\t \n\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t{t('save_btn')}\n\t\t\t\t\t \n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default UpdateLocationForm;\n\nUpdateLocationForm.propTypes = {\n\tbilling: PropTypes.object.isRequired,\n\tlocation: PropTypes.object.isRequired,\n\tsetBilling: PropTypes.func.isRequired,\n\tsetLocation: PropTypes.func.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React, {useContext, useState} from 'react';\nimport {Grid} from '@material-ui/core';\nimport {Title} from '../../../core/typography/Title';\nimport {useTranslation} from 'react-i18next';\nimport Button from '../../../core/input/Button';\nimport Stripe from '../../../core/input/Stripe/Stripe';\nimport Alert from '@material-ui/lab/Alert';\nimport {useUserBillingMethodUpdate} from '@karpeleslab/klb-react-services';\nimport PaymentMethod from './PaymentMethod';\nimport {UserContext} from '../../../../context/UserContext';\n\n\n// We only support Stripe for now\nconst UpdatePaymentMethodForm = ({method, setMethod, location}) => {\n\tconst {t} = useTranslation();\n\tconst [update] = useUserBillingMethodUpdate(method.User_Billing_Method__);\n\tconst [updating, setUpdating] = useState(false);\n\n\tconst [userContext] = useContext(UserContext);\n\n\tconst [showForm, setShowForm] = useState(false);\n\tconst [stripe, setStripe] = useState(null);\n\tconst [stripeIntent, setStripeIntent] = useState(null);\n\tconst [stripeElements, setStripeElements] = useState(null);\n\n\tconst [saveEnabled, setSaveEnabled] = useState(false);\n\tconst [error, setError] = useState(null);\n\n\tconst onStripeChange = e => {\n\t\tsetSaveEnabled(e.complete === true);\n\t};\n\n\tconst handleSave = async () => {\n\t\tif (!stripe || !stripeElements)\n\t\t\treturn; // stripe not loaded yet\n\n\t\tsetUpdating(true);\n\n\t\tconst result = await stripe.confirmSetup({\n\t\t\telements: stripeElements,\n\t\t\tredirect: 'if_required',\n\t\t\tconfirmParams: {\n\t\t\t\tpayment_method_data: {\n\t\t\t\t\tbilling_details: {\n\t\t\t\t\t\tname: `${location.First_Name} ${location.Last_Name}`,\n\t\t\t\t\t\temail: userContext.user.data.Email,\n\t\t\t\t\t\taddress: {\n\t\t\t\t\t\t\tcountry: location.Country__,\n\t\t\t\t\t\t\tpostal_code: location.Zip,\n\t\t\t\t\t\t\tstate: location.Province ? location.Province : '',\n\t\t\t\t\t\t\tcity: location.City ? location.City : '',\n\t\t\t\t\t\t\tline1: location.Address ? location.Address : '',\n\t\t\t\t\t\t\tline2: location.Address2 ? location.Address2 : '',\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}\n\t\t});\n\n\t\tif (result.error) {\n\t\t\tif (result.error.type === 'card_error' || result.error.type === 'validation_error') {\n\t\t\t\tsetError(result.error.message);\n\t\t\t} else {\n\t\t\t\tsetError(t('unexpected_error'));\n\t\t\t}\n\n\t\t\tsetUpdating(false);\n\t\t\treturn;\n\t\t}\n\n\t\tupdate({stripe_intent: stripeIntent.stripe_intent, method: 'Stripe'})\n\t\t\t.then(setMethod)\n\t\t\t.then(() => setShowForm(false))\n\t\t\t.finally(() => setUpdating(false));\n\t};\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t{t('billing_payment_method_update_title')} \n\t\t\t \n\t\t\t{!showForm &&\n\t\t\t\t<>\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t \n\t\t\t\t\t \n\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t setShowForm(true)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{t('edit_btn')}\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t>\n\t\t\t}\n\n\t\t\t{showForm &&\n\t\t\t\t<>\n\n\t\t\t\t\t{method.Expired && \n\t\t\t\t\t\t\n\t\t\t\t\t\t\t{t('billing_method_expired')}\n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t\t}\n\n\t\t\t\t\t{method.Fail_Count_Reached && \n\t\t\t\t\t\t\n\t\t\t\t\t\t\t{t('billing_method_failed')}\n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t\t}\n\n\t\t\t\t\t{error && \n\t\t\t\t\t\t\n\t\t\t\t\t\t\t{error}\n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t\t}\n\n\t\t\t\t\t\n\t\t\t\t\t\t \n\t\t\t\t\t \n\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t{t('save_btn')}\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t>\n\t\t\t}\n\t\t \n\t);\n};\n\nexport default UpdatePaymentMethodForm;\n\nUpdatePaymentMethodForm.propTypes = {\n\tmethod: PropTypes.object.isRequired,\n\tsetMethod: PropTypes.func.isRequired,\n\tlocation: PropTypes.object.isRequired\n};\n","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { useFirstPaymentMethod } from '../../hooks/useUserBilling';\nimport NotFound from '../../components/core/feedback/State/NotFound';\nimport { Grid } from '@material-ui/core';\nimport UpdateLocationForm from '../../components/common/User/Billing/UpdateLocationForm';\nimport UpdatePaymentMethodForm from '../../components/common/User/Billing/UpdatePaymentMethodForm';\nimport { useUserLocation } from '@karpeleslab/klb-react-services';\nimport Loader from '../../components/layout/Loader/Loader';\n\nconst UpdateBillingWrapper = ({ billing, setBilling }) => {\n\tconst [location, refreshLocation] = useUserLocation(billing.User_Location__);\n\tconst [method, refreshMethod] = useFirstPaymentMethod(billing.User_Billing__);\n\n\tif (!location || !method)\n\t\treturn ;\n\n\tif (!method.data || !location.data)\n\t\treturn ;\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t \n\t\t\t \n\n\t\t\t\n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default UpdateBillingWrapper;\n\nUpdateBillingWrapper.propTypes = {\n\tbilling: PropTypes.object.isRequired,\n\tsetBilling: PropTypes.func.isRequired\n};\n","import React from 'react';\nimport { Trans, useTranslation } from 'react-i18next';\nimport EmptyState from '../../../core/feedback/State/Empty';\nimport Graphic from '../../../../assets/img/404.svg';\n\nconst NotFound = () => {\n\tconst { t } = useTranslation();\n\treturn (\n\t\t\n\t\t\t\tsample \n\t\t\t\tsample \n\t\t\t}\n\t\t\tgraphic={Graphic}\n\t\t/>\n\t);\n};\n\nexport default NotFound;\n","import React from 'react';\nimport { useFirstUserBilling } from '../../hooks/useUserBilling';\nimport UpdateBillingWrapper from './UpdateBillingWrapper';\nimport Loader from '../../components/layout/Loader/Loader';\nimport NotFound from '../../components/common/User/Billing/NotFound';\n\nconst Billing = () => {\n\tconst [billing, refresh] = useFirstUserBilling('@');\n\n\tif (!billing) return ;\n\tif (!billing.data) return ;\n\n\treturn (\n\t\t\n\t);\n};\n\nexport default Billing;\n","import React from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Grid } from '@material-ui/core';\nimport PageTitle from '../../components/core/typography/PageTitle';\nimport OrdersTable from '../../components/common/Order/OrdersTable';\nimport PageContainer from '../../components/layout/Container/PageContainer';\nimport { Title } from '../../components/core/typography/Title';\nimport Billing from './Billing';\n\nconst PaymentInfo = () => {\n\tconst { t } = useTranslation();\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t \n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t{t('order_history_title')} \n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t \n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default PaymentInfo;\n","import React from 'react';\nimport { useTranslation } from 'react-i18next';\nimport TableDefinition from '../../core/data/table/TableDefinition';\nimport Table from '../../core/data/table/Table';\nimport Button from '../../core/input/Button';\nimport VisibilityIcon from '@material-ui/icons/Visibility';\nimport { Link } from 'react-router-dom';\nimport { getISORoute } from '../../RouteController/Factory';\nimport Grid from '@material-ui/core/Grid';\nimport DateUtil from '../../core/data/Date/DateUtil';\nimport { useShellISOs } from '@karpeleslab/klb-react-services';\nimport Chip from '@material-ui/core/Chip';\n\nconst ISOTable = () => {\n\tconst { t } = useTranslation();\n\tconst [isos, fetch, loading] = useShellISOs();\n\n\treturn (\n\t\t\n\t\t\t \n\n\t\t\t\n\t\t\t\t{iso =>\n\t\t\t\t\tiso.Hash ?\n\t\t\t\t\t\tiso.Hash :\n\t\t\t\t\t\t }\n\t\t\t \n\n\t\t\t\n\t\t\t\t{iso => }\n\t\t\t \n\n\t\t\t\n\t\t\t\t{iso =>\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t }\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{t('view_btn')}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t}\n\t\t\t \n\n\n\t\t
\n\t);\n};\n\nexport default ISOTable;\n","import PropTypes from 'prop-types';\nimport React, { useState } from 'react';\nimport LinearProgress from '../../core/feedback/LinearProgress';\nimport DialogTitle from '@material-ui/core/DialogTitle';\nimport DialogContent from '@material-ui/core/DialogContent';\nimport Grid from '@material-ui/core/Grid';\nimport FormControl from '@material-ui/core/FormControl';\nimport InputLabel from '@material-ui/core/InputLabel';\nimport Input from '@material-ui/core/Input';\nimport FormHelperText from '@material-ui/core/FormHelperText';\nimport DialogActions from '@material-ui/core/DialogActions';\nimport Button from '../../core/input/Button';\nimport Dialog from '@material-ui/core/Dialog';\nimport { useTranslation } from 'react-i18next';\nimport uuid from '../../../utils/uuid';\nimport { useShellISOUpload } from '@karpeleslab/klb-react-services';\nimport { useHistory } from 'react-router';\nimport { getISORoute } from '../../RouteController/Factory';\nimport RichAlertTrans from '../../core/feedback/RichAlertTrans';\n\nconst IsoCreateDialog = ({ open, setOpen }) => {\n\tconst { t } = useTranslation();\n\n\tconst history = useHistory();\n\n\tconst [create, creating, progress] = useShellISOUpload();\n\n\tconst [file, setFile] = useState(null);\n\tconst [fileKey, setFileKey] = useState(uuid());\n\n\tconst handleClose = () => {\n\t\tsetOpen(false);\n\t};\n\n\tconst reset = () => {\n\t\tsetFileKey(uuid());\n\t\tsetFile(null);\n\t};\n\n\tconst handleFile = e => {\n\t\tif (e.target.files.length > 0)\n\t\t\tsetFile(e.target.files[0]);\n\t};\n\n\tconst handleCreate = () => {\n\t\tcreate(file).then((iso) => history.push(getISORoute(iso.Shell_ISO__)));\n\t};\n\n\treturn (\n\t\t reset()}\n\t\t\tmaxWidth='lg'\n\t\t\tfullWidth\n\t\t>\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{t('dialog_create_iso_title')}\n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t{t('iso_file_label')}\n\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t{t('custom_os_file_helperText')} \n\t\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t{creating && }\n\t\t\t\t\t\n\t\t\t\t\t\t{t('close_btn')}\n\t\t\t\t\t \n\t\t\t\t\t\n\t\t\t\t\t\t{t('create_btn')}\n\t\t\t\t\t \n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default IsoCreateDialog;\n\nIsoCreateDialog.propTypes = {\n\topen: PropTypes.bool.isRequired,\n\tsetOpen: PropTypes.func.isRequired\n};\n","import React, { useState } from 'react';\nimport PageContainer from '../../components/layout/Container/PageContainer';\nimport { useTranslation } from 'react-i18next';\nimport { Grid } from '@material-ui/core';\nimport Button from '../../components/core/input/Button';\nimport AddIcon from '@material-ui/icons/Add';\nimport Toolbar from '../../components/core/typography/Toolbar';\nimport ISOTable from '../../components/common/ISO/ISOTable';\nimport IsoCreateDialog from '../../components/common/ISO/ISOCreateDialog';\n\nconst ISOList = () => {\n\tconst { t } = useTranslation();\n\tconst [showCreate, setShowCreate] = useState(false);\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t setShowCreate(true)}\n\t\t\t\t\t\t\tsize='small'\n\t\t\t\t\t\t\tvariant='contained'\n\t\t\t\t\t\t\tcolor='primary'\n\t\t\t\t\t\t\tstartIcon={ }\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{t('create_btn')}\n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t \n\t\t\t\t \n\t\t\t \n\t\t\t\n\n\t\t \n\t);\n};\n\nexport default ISOList;\n","import PropTypes from 'prop-types';\nimport React from 'react';\nimport { Grid, Typography } from '@material-ui/core';\nimport Chip from '@material-ui/core/Chip';\nimport { useTranslation } from 'react-i18next';\nimport { Title } from '../../core/typography/Title';\n\nconst IsoInfo = ({ iso }) => {\n\tconst { t } = useTranslation();\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t{t('iso_info_filename')} \n\t\t\t \n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{iso.Filename}\n\t\t\t\t \n\t\t\t \n\t\t\t\n\t\t\t\t{t('iso_info_hash')} \n\t\t\t \n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{\n\t\t\t\t\t\t \n\t\t\t\t\t}\n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default IsoInfo;\n\nIsoInfo.propTypes = {\n\tiso: PropTypes.object.isRequired\n};\n","import React from 'react';\nimport Dialog from '@material-ui/core/Dialog';\nimport DialogContentText from '@material-ui/core/DialogContentText';\nimport DialogContent from '@material-ui/core/DialogContent';\nimport { useTranslation } from 'react-i18next';\nimport DialogTitle from '@material-ui/core/DialogTitle';\nimport DialogActions from '@material-ui/core/DialogActions';\nimport PropTypes from 'prop-types';\nimport { useHistory } from 'react-router';\nimport { getISOsRoute } from '../../RouteController/Factory';\nimport Button from '../../core/input/Button';\nimport RichAlertTrans from '../../core/feedback/RichAlertTrans';\nimport { useShellISODelete } from '@karpeleslab/klb-react-services';\n\nconst ISODeleteDialog = ({ iso, open, setOpen }) => {\n\tconst { t } = useTranslation();\n\tconst [deleteISO, deleting] = useShellISODelete(iso.Shell_ISO__);\n\tconst history = useHistory();\n\n\tconst handleClose = () => {\n\t\tsetOpen(false);\n\t};\n\n\tconst handleDelete = e => {\n\t\te.preventDefault();\n\n\t\tdeleteISO()\n\t\t\t.then(handleClose)\n\t\t\t.then(() => history.push(getISOsRoute()));\n\t};\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t{t('dialog_delete_iso_title')}\n\t\t\t \n\t\t\t\n\t\t\t\t\n\t\t\t\t\t \n\t\t\t\t \n\t\t\t \n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{t('close_btn')}\n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t{t('delete_btn')}\n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default ISODeleteDialog;\n\nISODeleteDialog.propTypes = {\n\tiso: PropTypes.object,\n\topen: PropTypes.bool.isRequired,\n\tsetOpen: PropTypes.func.isRequired\n};\n","import React, { useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { useParams } from 'react-router';\nimport { useShellISO } from '@karpeleslab/klb-react-services';\nimport PageLoader from '../../components/layout/Loader/PageLoader';\nimport PageNotFound from '../System/PageNotFound';\nimport { Grid } from '@material-ui/core';\nimport Toolbar from '../../components/core/typography/Toolbar';\nimport { getISOsRoute } from '../../components/RouteController/Factory';\nimport PageContainer from '../../components/layout/Container/PageContainer';\nimport IsoInfo from '../../components/common/ISO/ISOInfo';\nimport IsoMountTable from '../../components/common/ISO/IsoMountTable';\nimport Button from '../../components/core/input/Button';\nimport ISODeleteDialog from '../../components/common/ISO/ISODeleteDialog';\n\nconst IsoEdit = () => {\n\tconst { t } = useTranslation();\n\tconst { isoId } = useParams();\n\tconst [iso] = useShellISO(isoId);\n\tconst [showDelete, setShowDelete] = useState(false);\n\n\tif (!iso) return ;\n\tif (!iso.data) return ;\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t \n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t \n\t\t\t\t \n\t\t\t\t{!iso.data.Is_Mounted &&\n\t\t\t\t\n\t\t\t\t\t setShowDelete(true)}\n\t\t\t\t\t>\n\t\t\t\t\t\t{t('delete_btn')}\n\t\t\t\t\t \n\t\t\t\t \n\t\t\t\t}\n\t\t\t\t{!iso.data.Is_Mounted && }\n\t\t\t \n\t\t \n\t);\n};\n\nexport default IsoEdit;\n","import PropTypes from 'prop-types';\nimport React from 'react';\nimport Alert from '@material-ui/lab/Alert';\nimport AlertTitle from '@material-ui/lab/AlertTitle';\nimport { useTranslation } from 'react-i18next';\n\nconst TextWarning = ({ warning }) => {\n\tconst { t } = useTranslation();\n\treturn (\n\t\t\n\t\t\t{t('warning_global_title')} \n\t\t\t
\n\t\t \n\t);\n};\n\nexport default TextWarning;\n\nTextWarning.propTypes = {\n\twarning: PropTypes.object.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React from 'react';\nimport { Grid } from '@material-ui/core';\nimport TextWarning from './TextWarning';\n\nconst TextWarnings = ({ warnings = [] }) => {\n\tif (warnings.length < 1) return <>>;\n\n\treturn (\n\t\t\n\t\t\t{warnings.map(w =>\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t \n\t\t\t)}\n\t\t \n\t);\n};\n\nexport default TextWarnings;\n\nTextWarnings.propTypes = {\n\twarnings: PropTypes.array.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React from 'react';\nimport Alert from '@material-ui/lab/Alert';\nimport AlertTitle from '@material-ui/lab/AlertTitle';\nimport { useTranslation } from 'react-i18next';\n\nconst UserWarning = ({ warning }) => {\n\tconst {t} = useTranslation();\n\treturn (\n\t\t\n\t\t\t{t('warning_user_title')} \n\t\t\t
\n\t\t \n\t);\n};\n\nexport default UserWarning;\n\nUserWarning.propTypes = {\n\twarning: PropTypes.object.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Grid } from '@material-ui/core';\nimport { Title } from '../../../../core/typography/Title';\nimport UserWarning from './UserWarning';\n\nconst UserWarnings = ({ warnings = [] }) => {\n\tconst { t } = useTranslation();\n\n\tif (warnings.length < 1) return <>>;\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t{t('account_warning_user')} \n\t\t\t \n\t\t\t{warnings.map(w =>\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t \n\t\t\t)}\n\t\t \n\t);\n};\n\nexport default UserWarnings;\n\nUserWarnings.propTypes = {\n\twarnings: PropTypes.array.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React from 'react';\nimport Alert from '@material-ui/lab/Alert';\nimport AlertTitle from '@material-ui/lab/AlertTitle';\nimport { Trans } from 'react-i18next';\nimport { Link } from 'react-router-dom';\nimport { getShellViewRoute } from '../../../../RouteController/Factory';\n\nconst ShellWarning = ({ warning }) => {\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\tsample\n\t\t\t\t\t sample\n\t\t\t\t \n\t\t\t \n\t\t\t
\n\t\t \n\t);\n};\n\nexport default ShellWarning;\n\nShellWarning.propTypes = {\n\twarning: PropTypes.object.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Grid } from '@material-ui/core';\nimport { Title } from '../../../../core/typography/Title';\nimport ShellWarning from './ShellWarning';\n\nconst ShellWarnings = ({ warnings = [] }) => {\n\tconst { t } = useTranslation();\n\n\tif (warnings.length < 1) return <>>;\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t{t('account_warning_shell')} \n\t\t\t \n\t\t\t{warnings.map(w =>\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t \n\t\t\t)}\n\t\t \n\t);\n};\n\nexport default ShellWarnings;\n\nShellWarnings.propTypes = {\n\twarnings: PropTypes.array.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React from 'react';\nimport CardContent from '@material-ui/core/CardContent';\nimport Typography from '@material-ui/core/Typography';\nimport { UNIT_CPU, UNIT_HDD, UNIT_RAM } from '../../../../../hooks/useShells';\nimport Card from '@material-ui/core/Card';\nimport ShellPlanListItemPrice from '../../../Shell/Plan/ShellPlanListItemPrice';\nimport { useTranslation } from 'react-i18next';\nimport { Grid } from '@material-ui/core';\nimport { getPrice, isCustomPlan } from '../../../../../utils/shell';\n\nconst Plan = ({ product, from = null }) => {\n\tconst { t } = useTranslation();\n\n\tconst getColor = (v1, v2) => {\n\t\treturn v1 !== v2 ? 'red' : 'inherit';\n\t};\n\tconst getStyle = (v1, v2) => {\n\t\treturn { color: getColor(v1, v2) };\n\t};\n\n\tconst forceShowMonthly = (p) => {\n\t\treturn p['Basic.ServiceLifetime'] === '1y' || p['Description.AuthorCode'] === 'custom';\n\t};\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{product['Basic.Name']}\n\t\t\t\t \n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t{Math.ceil(product['Shell.Size'] * UNIT_CPU)}\n\t\t\t\t\t\t\t VCPU\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t{product['Shell.Size'] * UNIT_HDD}\n\t\t\t\t\t\t\t HDD\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t{product['Shell.Size'] * UNIT_RAM} GB\n\t\t\t\t\t\t\t RAM\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t{product['Shell.Timer_Allowance'] &&\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t{t('shell_time_allowance', {\n\t\t\t\t\t\t\t\t\ttime: parseInt(product['Shell.Timer_Allowance']) / 3600\n\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t{!product['Shell.Timer_Allowance'] &&\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t{t('shell_unlimited_usage')}\n\t\t\t\t\t\t\t \n\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t
\n\t\t\t\t\t \n\t\t\t\t\t\n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default Plan;\n\nPlan.propTypes = {\n\tfrom: PropTypes.object,\n\tproduct: PropTypes.object.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Grid } from '@material-ui/core';\nimport Plan from './Plan';\nimport AlertTitle from '@material-ui/lab/AlertTitle';\nimport Alert from '@material-ui/lab/Alert';\nimport ForwardIcon from '@material-ui/icons/Forward';\nimport DateUtil from '../../../../core/data/Date/DateUtil';\n\nconst ProductWarning = ({ warning }) => {\n\tconst { t } = useTranslation();\n\n\treturn (\n\t\t\n\t\t\t{warning.Data &&\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{t('warning_product_title')} \n\t\t\t\t\t
\n\t\t\t\t \n\t\t\t }\n\t\t\t\n\t\t\t\t\n\t\t\t \n\n\t\t\t{warning.Target_MetaObject__ &&\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t\t\n\t\t\t\t\t\t{t(warning.Expires ? 'warning_will_change_the' : 'warning_will_change_to')}\n\t\t\t\t\t \n\t\t\t\t\t{warning.Expires &&\n\t\t\t\t\t\n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t\t}\n\t\t\t\t \n\n\t\t\t }\n\t\t\t{warning.Target_MetaObject__ &&\n\t\t\t\n\t\t\t\t\n\t\t\t \n\t\t\t}\n\n\t\t \n\t);\n};\n\nexport default ProductWarning;\n\nProductWarning.propTypes = {\n\twarning: PropTypes.object.isRequired\n};\n","import React, { useEffect, useState } from 'react';\nimport Table from '@material-ui/core/Table';\nimport TableBody from '@material-ui/core/TableBody';\nimport TableRow from '@material-ui/core/TableRow';\nimport TableCell from '@material-ui/core/TableCell';\nimport ShellPicture from '../../../Shell/ShellPicture/ShellPicture';\nimport { getShellViewRoute } from '../../../../RouteController/Factory';\nimport { formatShellExpireDate, isExpired } from '../../../../../utils/shell';\nimport ShellExpiredMessage from '../../../Shell/Subscription/ShellExpiredMessage';\nimport { Grid } from '@material-ui/core';\nimport ShellUsage from '../../../Shell/Subscription/ShellUsage';\nimport TableContainer from '@material-ui/core/TableContainer';\nimport { useShellProductChangeWarning } from '@karpeleslab/klb-react-services';\nimport { useTranslation } from 'react-i18next';\nimport Loader from '../../../../layout/Loader/Loader';\nimport { Link } from 'react-router-dom';\n\nconst ConcernedShellTable = () => {\n\tconst { t } = useTranslation();\n\tconst [fetch] = useShellProductChangeWarning();\n\tconst [shells, setShells] = useState([]);\n\n\tuseEffect(() => {\n\t\tfetch().then(setShells);\n\t}, [fetch, setShells]);\n\n\tif (shells.length < 1) return ;\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t{shells.map(s =>\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t{s.Label}\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t{isExpired(s) && }\n\t\t\t\t\t\t\t\t{!isExpired(s) &&\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t{!s.User_Billing__ && t('shell_expire_text', { date: formatShellExpireDate(s) })}\n\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t }\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t)}\n\t\t\t\t \n\t\t\t
\n\t\t \n\t);\n};\n\nexport default ConcernedShellTable;\n","import PropTypes from 'prop-types';\nimport React from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Grid, Typography } from '@material-ui/core';\nimport { Title } from '../../../../core/typography/Title';\nimport ProductWarning from './ProductWarning';\nimport ConcernedShellTable from './ConcernedShellTable';\n\nconst ProductWarnings = ({ warnings = [] }) => {\n\tconst { t } = useTranslation();\n\n\tif (warnings.length < 1) return <>>;\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t{t('account_warning_product')} \n\t\t\t \n\t\t\t{warnings.map(w =>\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t \n\t\t\t)}\n\t\t\t\n\t\t\t\t{t('account_warning_product_shells')} \n\t\t\t \n\t\t\t\n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default ProductWarnings;\n\nProductWarnings.propTypes = {\n\twarnings: PropTypes.array.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React from 'react';\nimport Alert from '@material-ui/lab/Alert';\nimport AlertTitle from '@material-ui/lab/AlertTitle';\nimport { Trans } from 'react-i18next';\n\nconst OsWarning = ({ warning }) => {\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\tsample\n\t\t\t\t \n\t\t\t \n\t\t\t
\n\t\t \n\t);\n};\n\nexport default OsWarning;\n\nOsWarning.propTypes = {\n\twarning: PropTypes.object.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Grid } from '@material-ui/core';\nimport { Title } from '../../../../core/typography/Title';\nimport OsWarning from './OsWarning';\n\nconst OsWarnings = ({ warnings = [] }) => {\n\tconst { t } = useTranslation();\n\n\tif (warnings.length < 1) return <>>;\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t{t('account_warning_os')} \n\t\t\t \n\t\t\t{warnings.map(w =>\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t \n\t\t\t)}\n\t\t \n\t);\n};\n\nexport default OsWarnings;\n\nOsWarnings.propTypes = {\n\twarnings: PropTypes.array.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React from 'react';\nimport Alert from '@material-ui/lab/Alert';\nimport AlertTitle from '@material-ui/lab/AlertTitle';\nimport { Trans } from 'react-i18next';\n\nconst DatacenterWarning = ({ warning }) => {\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\tsample\n\t\t\t\t \n\t\t\t \n\t\t\t
\n\t\t \n\t);\n};\n\nexport default DatacenterWarning;\n\nDatacenterWarning.propTypes = {\n\twarning: PropTypes.object.isRequired\n};\n","import PropTypes from 'prop-types';\nimport React from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Grid } from '@material-ui/core';\nimport { Title } from '../../../../core/typography/Title';\nimport DatacenterWarning from './DatacenterWarning';\n\nconst DatacenterWarnings = ({ warnings = [] }) => {\n\tconst { t } = useTranslation();\n\n\tif (warnings.length < 1) return <>>;\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t{t('account_warning_datacenter')} \n\t\t\t \n\t\t\t{warnings.map(w =>\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t \n\t\t\t)}\n\t\t \n\t);\n};\n\nexport default DatacenterWarnings;\n\nDatacenterWarnings.propTypes = {\n\twarnings: PropTypes.array.isRequired\n};\n","import React, { useEffect, useState } from 'react';\nimport PageContainer from '../../components/layout/Container/PageContainer';\nimport { useShellAccountWarnings } from '@karpeleslab/klb-react-services';\nimport PageLoader from '../../components/layout/Loader/PageLoader';\nimport PageTitle from '../../components/core/typography/PageTitle';\nimport { Grid } from '@material-ui/core';\nimport { useTranslation } from 'react-i18next';\nimport TextWarnings from '../../components/common/Account/Warning/Text/TextWarnings';\nimport UserWarnings from '../../components/common/Account/Warning/User/UserWarnings';\nimport ShellWarnings from '../../components/common/Account/Warning/Shell/ShellWarnings';\nimport ProductWarnings from '../../components/common/Account/Warning/Product/ProductWarnings';\nimport OsWarnings from '../../components/common/Account/Warning/Os/OsWarnings';\nimport DatacenterWarnings from '../../components/common/Account/Warning/Datacenter/DatacenterWarnings';\n\nconst Warning = () => {\n\tconst { t } = useTranslation();\n\n\tconst [fetch, loading] = useShellAccountWarnings();\n\tconst [textWarnings, setTextWarnings] = useState([]);\n\tconst [productWarnings, setProductWarnings] = useState([]);\n\tconst [userWarnings, setUserWarnings] = useState([]);\n\tconst [shellWarnings, setShellWarnings] = useState([]);\n\tconst [osWarnings, setOsWarnings] = useState([]);\n\tconst [datacenterWarnings, setDatacenterWarnings] = useState([]);\n\n\tuseEffect(() => {\n\t\tfetch()\n\t\t\t.then(warnings => {\n\t\t\t\tsetTextWarnings(warnings.filter(w => w.Type === 'text'));\n\t\t\t\tsetProductWarnings(warnings.filter(w => w.Type === 'product'));\n\t\t\t\tsetUserWarnings(warnings.filter(w => w.Type === 'user'));\n\t\t\t\tsetShellWarnings(warnings.filter(w => w.Type === 'shell'));\n\t\t\t\tsetOsWarnings(warnings.filter(w => w.Type === 'shell_os'));\n\t\t\t\tsetDatacenterWarnings(warnings.filter(w => w.Type === 'datacenter'));\n\t\t\t});\n\t}, [fetch, setTextWarnings, setProductWarnings, setUserWarnings, setShellWarnings, setOsWarnings, setDatacenterWarnings]);\n\n\tif (loading) return ;\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t \n\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t \n\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t \n\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t \n\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t \n\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t \n\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default Warning;\n","import React from 'react';\nimport { Switch, useLocation } from 'react-router-dom';\nimport { default as Route } from '../core/utils/RouteTransition/RouteTransition';\nimport Login from '../../pages/Login/Login';\nimport {\n\tgetAccountWarningRoute,\n\tgetBillingRoute,\n\tgetCustomOsEditRoute,\n\tgetCustomOsRoute,\n\tgetISORoute,\n\tgetISOsRoute,\n\tgetLinksRoute,\n\tgetLoginRoute,\n\tgetOrderViewRoute,\n\tgetPartnershipRoute,\n\tgetShellsRoute,\n\tgetShellViewRoute,\n\tgetSSHKeychainEditRoute,\n\tgetSSHKeychainRoute,\n\tgetSwitchToModeRoute,\n\tgetUserSettingsRoute\n} from './Factory';\nimport Profile from '../../pages/Profile/Profile';\nimport Keychains from '../../pages/Keychain/Keychains';\nimport KeychainEdit from '../../pages/Keychain/KeychainEdit';\nimport PageNotFound from '../../pages/System/PageNotFound';\nimport Partnership from '../../pages/Partnership/Partnership';\nimport ViewOrder from '../../pages/Order/ViewOrder';\nimport ShellList from '../../pages/Shell/ShellList';\nimport Shell from '../../pages/Shell/Shell';\nimport Links from '../../pages/Links/Links';\nimport CustomOSList from '../../pages/OperatingSystem/CustomOSList';\nimport CustomOsEdit from '../../pages/OperatingSystem/CustomOSEdit';\nimport SwitchMode from '../../pages/Mode/SwitchMode';\nimport PaymentInfo from '../../pages/Billing/PaymentInfo';\nimport ISOList from '../../pages/ISO/ISOList';\nimport IsoEdit from '../../pages/ISO/ISOEdit';\nimport Warning from '../../pages/Warning/Warning';\n\n\nconst Routes = () => {\n\tconst location = useLocation();\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t\t\n\n\t\t\t\n\t\t \n\t);\n};\n\n\nexport default Routes;\n","import React, { useContext } from 'react';\nimport { CSSTransition, SwitchTransition } from 'react-transition-group';\nimport Loader from './../layout/Loader/Loader';\nimport { UserContext } from '../../context/UserContext';\nimport Routes from './Routes';\n\nconst RouteController = () => {\n\tconst [user] = useContext(UserContext);\n\n\treturn (\n\t\t\n\t\t\t node.addEventListener('transitionend', done, false)}\n\t\t\t\tclassNames=\"u-transition--vertical\"\n\t\t\t>\n\t\t\t\t{\n\t\t\t\t\t(!user || !user.loading) ? :\n\t\t\t\t\t\t(\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t
\n\t\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t \n\t\t \n\t);\n};\n\nexport default RouteController;\n","import React, { useCallback, useEffect, useState } from 'react';\nimport makeStyles from '@material-ui/core/styles/makeStyles';\nimport { Trans } from 'react-i18next';\nimport { Link, useLocation } from 'react-router-dom';\nimport { getAccountWarningRoute } from '../../RouteController/Factory';\nimport { Typography } from '@material-ui/core';\nimport Ellipsis from '../../core/typography/Ellipsis';\nimport { darken, lighten } from '@material-ui/core/styles';\nimport Paper from '@material-ui/core/Paper';\nimport Grid from '@material-ui/core/Grid';\nimport ReportProblemOutlinedIcon from '@material-ui/icons/ReportProblemOutlined';\nimport { LinkTypo } from '../../common/Links/Link';\nimport { useShellAccountWarnings } from '@karpeleslab/klb-react-services';\n\nconst useStyles = makeStyles(theme => {\n\t// based on https://github.com/mui-org/material-ui/blob/master/packages/material-ui-lab/src/Alert/Alert.js\n\tconst getColor = theme.palette.type === 'light' ? darken : lighten;\n\tconst getBackgroundColor = theme.palette.type === 'light' ? lighten : darken;\n\n\treturn {\n\t\troot: {\n\t\t\tpadding: theme.spacing(3),\n\t\t\tjustifyContent: 'center',\n\t\t\tcolor: getColor(theme.palette.warning.main, 0.6),\n\t\t\tbackgroundColor: getBackgroundColor(theme.palette.warning.main, 0.9),\n\t\t},\n\t\ticon: {\n\t\t\tcolor: theme.palette.warning.main,\n\t\t},\n\t\tmessage: {\n\t\t\ttextAlign: 'center'\n\t\t},\n\t\taction: {\n\t\t\tmarginLeft: 'unset',\n\t\t}\n\t};\n});\n\nconst AccountWarnings = () => {\n\tconst classes = useStyles();\n\n\tconst [fetch] = useShellAccountWarnings();\n\tconst [warnings, setWanings] = useState(null);\n\tconst location = useLocation();\n\n\tconst execute = useCallback(() => {\n\t\tfetch()\n\t\t\t.then(warnings => {\n\t\t\t\tlet found = {};\n\t\t\t\tlet result = [];\n\t\t\t\t// We only keep 1 warning of each type, and counting the number of time they occured\n\t\t\t\twarnings.forEach(w => {\n\t\t\t\t\tif (w.Type in found) {\n\t\t\t\t\t\tresult[found[w.Type]].count += 1;\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tresult.push({ ...w, count: 1 });\n\t\t\t\t\tfound[w.Type] = result.length - 1;\n\t\t\t\t});\n\n\t\t\t\tsetWanings(result);\n\t\t\t});\n\t}, [fetch, setWanings]);\n\n\tuseEffect(() => {\n\t\texecute();\n\t}, [fetch, setWanings, location]);\n\n\tuseEffect(() => {\n\t\tconst interval = setInterval(() => {\n\t\t\texecute();\n\t\t}, 1000 * 60 * 5); // every 5 minutes\n\t\treturn () => {\n\t\t\tclearInterval(interval);\n\t\t};\n\t}, [execute]);\n\n\tif (location.pathname === getAccountWarningRoute() || !warnings || warnings.length < 1) return <>>;\n\n\t// This is a custom warning alert basically\n\n\t// icon | title | action\n\t// warnings\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t \n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\tsample \n\t\t\t\t\t\t\t\t\tsample \n\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t \n\n\t\t\t\t \n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t{warnings.map(w =>\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t]+)>)/ig, '') }}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\tsample \n\t\t\t\t\t\t\t\t\t\tsample \n\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t )}\n\t\t\t\t\t
\n\t\t\t\t \n\t\t\t \n\n\t\t );\n};\n\nexport default AccountWarnings;\n","import React, { useContext } from 'react';\n\nimport Drawer from './Drawer/Drawer';\nimport Helmet from 'react-helmet';\nimport RouteController from '../RouteController/RouteController';\n\nimport { UserContext } from '../../context/UserContext';\nimport { MenuContext } from '../../context/MenuContext';\n\nimport './Layout.scss';\nimport AccountWarnings from './AccountWarnings/AccountWarnings';\n\nconst Layout = () => {\n\tconst [user] = useContext(UserContext);\n\tconst [menu] = useContext(MenuContext);\n\n\treturn (\n\t\t<>\n\t\t\t\n\t\t\t\t{ /* https://devhints.io/html-meta */}\n\t\t\t \n\t\t\t{user && user.loggedIn ? : ''}\n\t\t\t{user && user.loggedIn ? : ''}\n\t\t\t\n\t\t\t\t \n\t\t\t
\n\t\t>\n\t);\n};\n\nexport default Layout;\n","import React, { useEffect } from 'react';\nimport { CSSTransition, SwitchTransition } from 'react-transition-group';\n\nimport { useSetSnackbar, useSnackbar } from '../../../hooks/useSnackbar';\nimport CloseIcon from '@material-ui/icons/Close';\nimport Grid from '@material-ui/core/Grid';\nimport Box from '@material-ui/core/Box';\n\nimport './Snackbar.scss';\nimport useMediaQuery from '@material-ui/core/useMediaQuery';\n\nexport default function Snackbar() {\n\tconst { snackbar } = useSnackbar();\n\tconst { message, type } = snackbar;\n\tconst isMobile = useMediaQuery(theme => theme.breakpoints.down('xs'), { noSsr: true });\n\n\tconst setSnackbar = useSetSnackbar();\n\tconst handleClose = () => {\n\t\tsetSnackbar(null);\n\t};\n\n\tuseEffect(() => {\n\t\tif (message) {\n\t\t\tsetTimeout(() => {\n\t\t\t\tif (message)\n\t\t\t\t\tsetSnackbar(null);\n\t\t\t}, 5000);\n\t\t}\n\t}, [message, setSnackbar]);\n\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t node.addEventListener('transitionend', done, false)}\n\t\t\t\t\tclassNames='u-transition--vertical'\n\t\t\t\t>\n\t\t\t\t\t{message ?\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t{message}\n\t\t\t\t\t\t\t\t handleClose()}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t\t:\n\t\t\t\t\t\t \n\t\t\t\t\t}\n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n}\n","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { SnackbarContainer } from './context/SnackbarContext';\nimport { UserContainer } from './context/UserContext';\nimport { RestContextContainer } from '@karpeleslab/klb-react-services';\nimport { MenuContextContainer } from './context/MenuContext';\n\nconst AppContextContainers = ({ children }) => {\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t{children}\n\t\t\t\t\t \n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n};\n\nexport default AppContextContainers;\n\nAppContextContainers.propTypes = {\n\tchildren: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]).isRequired,\n};\n","import MuiTheme from './components/core/MuiTheme/MuiTheme';\nimport React from 'react';\nimport ScrollToTop from './components/core/utils/ScrollToTop/ScrollToTop';\nimport Helmet from 'react-helmet';\nimport Layout from './components/layout/Layout';\nimport Snackbar from './components/layout/Snackbar/Snackbar';\nimport AppContextContainers from './AppContextContainers';\nimport { ModeContainer } from './context/ModeContext';\n\nfunction App() {\n\treturn (\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t \n\t\t\t\t\t\n\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t\t \n\t\t\t\t \n\t\t\t \n\t\t \n\t);\n}\n\nexport default App;\n","import './polyfills';\n\nimport React from 'react';\nimport App from './App';\n\nimport i18n from 'i18next';\nimport { initReactI18next } from 'react-i18next';\nimport { getLocale, rest } from '@karpeleslab/klbfw';\nimport { Backend } from '@karpeleslab/i18next-klb-backend';\nimport { run } from '@karpeleslab/react-klbfw-hooks';\n\nimport './assets/styles/main.scss';\n\nlet i18nOpt = {\n\tlng: getLocale(),\n\tinitImmediate: false,\n\tload: 'currentOnly',\n\tinterpolation: { escapeValue: false },\n\treact: { useSuspense: false }\n};\n\nglobal.rest = rest;\n\nrun(\n\t ,\n\t[i18n.use(Backend).use(initReactI18next).init(i18nOpt)]\n);\n","Promise.prototype.finally = Promise.prototype.finally || {\n\tfinally (fn) {\n\t\tconst onFinally = callback => Promise.resolve(fn()).then(callback);\n\t\treturn this.then(\n\t\t\tresult => onFinally(() => result),\n\t\t\treason => onFinally(() => Promise.reject(reason))\n\t\t);\n\t}\n}.finally;\n","var map = {\n\t\"./af\": 317,\n\t\"./af.js\": 317,\n\t\"./ar\": 318,\n\t\"./ar-dz\": 319,\n\t\"./ar-dz.js\": 319,\n\t\"./ar-kw\": 320,\n\t\"./ar-kw.js\": 320,\n\t\"./ar-ly\": 321,\n\t\"./ar-ly.js\": 321,\n\t\"./ar-ma\": 322,\n\t\"./ar-ma.js\": 322,\n\t\"./ar-sa\": 323,\n\t\"./ar-sa.js\": 323,\n\t\"./ar-tn\": 324,\n\t\"./ar-tn.js\": 324,\n\t\"./ar.js\": 318,\n\t\"./az\": 325,\n\t\"./az.js\": 325,\n\t\"./be\": 326,\n\t\"./be.js\": 326,\n\t\"./bg\": 327,\n\t\"./bg.js\": 327,\n\t\"./bm\": 328,\n\t\"./bm.js\": 328,\n\t\"./bn\": 329,\n\t\"./bn-bd\": 330,\n\t\"./bn-bd.js\": 330,\n\t\"./bn.js\": 329,\n\t\"./bo\": 331,\n\t\"./bo.js\": 331,\n\t\"./br\": 332,\n\t\"./br.js\": 332,\n\t\"./bs\": 333,\n\t\"./bs.js\": 333,\n\t\"./ca\": 334,\n\t\"./ca.js\": 334,\n\t\"./cs\": 335,\n\t\"./cs.js\": 335,\n\t\"./cv\": 336,\n\t\"./cv.js\": 336,\n\t\"./cy\": 337,\n\t\"./cy.js\": 337,\n\t\"./da\": 338,\n\t\"./da.js\": 338,\n\t\"./de\": 339,\n\t\"./de-at\": 340,\n\t\"./de-at.js\": 340,\n\t\"./de-ch\": 341,\n\t\"./de-ch.js\": 341,\n\t\"./de.js\": 339,\n\t\"./dv\": 342,\n\t\"./dv.js\": 342,\n\t\"./el\": 343,\n\t\"./el.js\": 343,\n\t\"./en-au\": 344,\n\t\"./en-au.js\": 344,\n\t\"./en-ca\": 345,\n\t\"./en-ca.js\": 345,\n\t\"./en-gb\": 346,\n\t\"./en-gb.js\": 346,\n\t\"./en-ie\": 347,\n\t\"./en-ie.js\": 347,\n\t\"./en-il\": 348,\n\t\"./en-il.js\": 348,\n\t\"./en-in\": 349,\n\t\"./en-in.js\": 349,\n\t\"./en-nz\": 350,\n\t\"./en-nz.js\": 350,\n\t\"./en-sg\": 351,\n\t\"./en-sg.js\": 351,\n\t\"./eo\": 352,\n\t\"./eo.js\": 352,\n\t\"./es\": 353,\n\t\"./es-do\": 354,\n\t\"./es-do.js\": 354,\n\t\"./es-mx\": 355,\n\t\"./es-mx.js\": 355,\n\t\"./es-us\": 356,\n\t\"./es-us.js\": 356,\n\t\"./es.js\": 353,\n\t\"./et\": 357,\n\t\"./et.js\": 357,\n\t\"./eu\": 358,\n\t\"./eu.js\": 358,\n\t\"./fa\": 359,\n\t\"./fa.js\": 359,\n\t\"./fi\": 360,\n\t\"./fi.js\": 360,\n\t\"./fil\": 361,\n\t\"./fil.js\": 361,\n\t\"./fo\": 362,\n\t\"./fo.js\": 362,\n\t\"./fr\": 363,\n\t\"./fr-ca\": 364,\n\t\"./fr-ca.js\": 364,\n\t\"./fr-ch\": 365,\n\t\"./fr-ch.js\": 365,\n\t\"./fr.js\": 363,\n\t\"./fy\": 366,\n\t\"./fy.js\": 366,\n\t\"./ga\": 367,\n\t\"./ga.js\": 367,\n\t\"./gd\": 368,\n\t\"./gd.js\": 368,\n\t\"./gl\": 369,\n\t\"./gl.js\": 369,\n\t\"./gom-deva\": 370,\n\t\"./gom-deva.js\": 370,\n\t\"./gom-latn\": 371,\n\t\"./gom-latn.js\": 371,\n\t\"./gu\": 372,\n\t\"./gu.js\": 372,\n\t\"./he\": 373,\n\t\"./he.js\": 373,\n\t\"./hi\": 374,\n\t\"./hi.js\": 374,\n\t\"./hr\": 375,\n\t\"./hr.js\": 375,\n\t\"./hu\": 376,\n\t\"./hu.js\": 376,\n\t\"./hy-am\": 377,\n\t\"./hy-am.js\": 377,\n\t\"./id\": 378,\n\t\"./id.js\": 378,\n\t\"./is\": 379,\n\t\"./is.js\": 379,\n\t\"./it\": 380,\n\t\"./it-ch\": 381,\n\t\"./it-ch.js\": 381,\n\t\"./it.js\": 380,\n\t\"./ja\": 382,\n\t\"./ja.js\": 382,\n\t\"./jv\": 383,\n\t\"./jv.js\": 383,\n\t\"./ka\": 384,\n\t\"./ka.js\": 384,\n\t\"./kk\": 385,\n\t\"./kk.js\": 385,\n\t\"./km\": 386,\n\t\"./km.js\": 386,\n\t\"./kn\": 387,\n\t\"./kn.js\": 387,\n\t\"./ko\": 388,\n\t\"./ko.js\": 388,\n\t\"./ku\": 389,\n\t\"./ku.js\": 389,\n\t\"./ky\": 390,\n\t\"./ky.js\": 390,\n\t\"./lb\": 391,\n\t\"./lb.js\": 391,\n\t\"./lo\": 392,\n\t\"./lo.js\": 392,\n\t\"./lt\": 393,\n\t\"./lt.js\": 393,\n\t\"./lv\": 394,\n\t\"./lv.js\": 394,\n\t\"./me\": 395,\n\t\"./me.js\": 395,\n\t\"./mi\": 396,\n\t\"./mi.js\": 396,\n\t\"./mk\": 397,\n\t\"./mk.js\": 397,\n\t\"./ml\": 398,\n\t\"./ml.js\": 398,\n\t\"./mn\": 399,\n\t\"./mn.js\": 399,\n\t\"./mr\": 400,\n\t\"./mr.js\": 400,\n\t\"./ms\": 401,\n\t\"./ms-my\": 402,\n\t\"./ms-my.js\": 402,\n\t\"./ms.js\": 401,\n\t\"./mt\": 403,\n\t\"./mt.js\": 403,\n\t\"./my\": 404,\n\t\"./my.js\": 404,\n\t\"./nb\": 405,\n\t\"./nb.js\": 405,\n\t\"./ne\": 406,\n\t\"./ne.js\": 406,\n\t\"./nl\": 407,\n\t\"./nl-be\": 408,\n\t\"./nl-be.js\": 408,\n\t\"./nl.js\": 407,\n\t\"./nn\": 409,\n\t\"./nn.js\": 409,\n\t\"./oc-lnc\": 410,\n\t\"./oc-lnc.js\": 410,\n\t\"./pa-in\": 411,\n\t\"./pa-in.js\": 411,\n\t\"./pl\": 412,\n\t\"./pl.js\": 412,\n\t\"./pt\": 413,\n\t\"./pt-br\": 414,\n\t\"./pt-br.js\": 414,\n\t\"./pt.js\": 413,\n\t\"./ro\": 415,\n\t\"./ro.js\": 415,\n\t\"./ru\": 416,\n\t\"./ru.js\": 416,\n\t\"./sd\": 417,\n\t\"./sd.js\": 417,\n\t\"./se\": 418,\n\t\"./se.js\": 418,\n\t\"./si\": 419,\n\t\"./si.js\": 419,\n\t\"./sk\": 420,\n\t\"./sk.js\": 420,\n\t\"./sl\": 421,\n\t\"./sl.js\": 421,\n\t\"./sq\": 422,\n\t\"./sq.js\": 422,\n\t\"./sr\": 423,\n\t\"./sr-cyrl\": 424,\n\t\"./sr-cyrl.js\": 424,\n\t\"./sr.js\": 423,\n\t\"./ss\": 425,\n\t\"./ss.js\": 425,\n\t\"./sv\": 426,\n\t\"./sv.js\": 426,\n\t\"./sw\": 427,\n\t\"./sw.js\": 427,\n\t\"./ta\": 428,\n\t\"./ta.js\": 428,\n\t\"./te\": 429,\n\t\"./te.js\": 429,\n\t\"./tet\": 430,\n\t\"./tet.js\": 430,\n\t\"./tg\": 431,\n\t\"./tg.js\": 431,\n\t\"./th\": 432,\n\t\"./th.js\": 432,\n\t\"./tk\": 433,\n\t\"./tk.js\": 433,\n\t\"./tl-ph\": 434,\n\t\"./tl-ph.js\": 434,\n\t\"./tlh\": 435,\n\t\"./tlh.js\": 435,\n\t\"./tr\": 436,\n\t\"./tr.js\": 436,\n\t\"./tzl\": 437,\n\t\"./tzl.js\": 437,\n\t\"./tzm\": 438,\n\t\"./tzm-latn\": 439,\n\t\"./tzm-latn.js\": 439,\n\t\"./tzm.js\": 438,\n\t\"./ug-cn\": 440,\n\t\"./ug-cn.js\": 440,\n\t\"./uk\": 441,\n\t\"./uk.js\": 441,\n\t\"./ur\": 442,\n\t\"./ur.js\": 442,\n\t\"./uz\": 443,\n\t\"./uz-latn\": 444,\n\t\"./uz-latn.js\": 444,\n\t\"./uz.js\": 443,\n\t\"./vi\": 445,\n\t\"./vi.js\": 445,\n\t\"./x-pseudo\": 446,\n\t\"./x-pseudo.js\": 446,\n\t\"./yo\": 447,\n\t\"./yo.js\": 447,\n\t\"./zh-cn\": 448,\n\t\"./zh-cn.js\": 448,\n\t\"./zh-hk\": 449,\n\t\"./zh-hk.js\": 449,\n\t\"./zh-mo\": 450,\n\t\"./zh-mo.js\": 450,\n\t\"./zh-tw\": 451,\n\t\"./zh-tw.js\": 451\n};\n\n\nfunction webpackContext(req) {\n\tvar id = webpackContextResolve(req);\n\treturn __webpack_require__(id);\n}\nfunction webpackContextResolve(req) {\n\tif(!__webpack_require__.o(map, req)) {\n\t\tvar e = new Error(\"Cannot find module '\" + req + \"'\");\n\t\te.code = 'MODULE_NOT_FOUND';\n\t\tthrow e;\n\t}\n\treturn map[req];\n}\nwebpackContext.keys = function webpackContextKeys() {\n\treturn Object.keys(map);\n};\nwebpackContext.resolve = webpackContextResolve;\nmodule.exports = webpackContext;\nwebpackContext.id = 712;"],"sourceRoot":""}