\n {list.map((item, index) => (\n
= index + 1,\n })}\n />\n ))}\n
{tip}
\n
\n );\n }\n}\n","import { parseDomain, ParseResultType } from 'parse-domain';\n\nexport function getCookieDomain(hostname = window.location.hostname) {\n const parseResult = parseDomain(hostname);\n let cookieDomain;\n if (parseResult.type === ParseResultType.Listed) {\n const { domain, topLevelDomains } = parseResult;\n cookieDomain = `.${[domain, ...topLevelDomains].join('.')}`;\n }\n return cookieDomain;\n}\nconst cookieDomain = getCookieDomain();\nexport { cookieDomain };\n","import querystring from 'querystring';\nimport Cookies from 'js-cookie';\nimport { sha512 } from 'js-sha512';\n\nimport { UserInfo } from '../type';\nimport { cookieDomain } from './domain';\nimport { getProviderConfig } from '../constants/providerConfig';\nexport const ONE_TIME_TOKEN_KEY = '_token';\nexport interface CookieToken {\n accessToken: string;\n refreshToken: string;\n idToken: string;\n}\nexport interface CookieConfig {\n domain?: string;\n expires?: number;\n secure?: boolean;\n}\nconst cookieBaseConfig = {\n domain: cookieDomain,\n secure: !(isDev() || isLocal()),\n};\n\nexport function getUrlQueryParams(search = window.location.search): {\n [key: string]: string | string[] | undefined;\n} {\n try {\n if (search.startsWith('?')) {\n search = search.substring(1);\n }\n return querystring.parse(search) || {};\n } catch (e) {\n return {};\n }\n}\n\nexport function setToken(\n { accessToken, refreshToken, idToken }: CookieToken,\n config: CookieConfig = {}\n) {\n const finalConfig = {\n ...cookieBaseConfig,\n ...config,\n };\n Cookies.set('accessToken', accessToken, finalConfig);\n Cookies.set('refreshToken', refreshToken, finalConfig);\n Cookies.set('idToken', idToken, finalConfig);\n // Cookies.set('idpIdToken', idpIdToken, finalConfig);\n}\n\nexport function getToken(): CookieToken {\n return {\n accessToken: Cookies.get('accessToken') || '',\n refreshToken: Cookies.get('refreshToken') || '',\n idToken: Cookies.get('idToken') || '',\n };\n}\n\nexport function setUser(user: Partial
, config: CookieConfig = {}) {\n const finalConfig = {\n ...cookieBaseConfig,\n ...config,\n };\n setCookieObj('user', user, finalConfig);\n}\n\nexport function getUser(): Partial | null {\n return getCookieObj('user');\n}\nexport function setLoginFlag(config: CookieConfig = {}) {\n const finalConfig = {\n ...cookieBaseConfig,\n ...config,\n };\n Cookies.set('loginTime', Date.now(), finalConfig);\n}\nexport function setCookieObj(key: string, obj: any, config: CookieConfig = {}) {\n try {\n Cookies.set(key, JSON.stringify(obj), config);\n } catch (e) {}\n}\n\nexport function getCookieObj(key: string) {\n try {\n return JSON.parse(Cookies.get(key));\n } catch (e) {\n return null;\n }\n}\n\nexport function clearToken() {\n Cookies.remove('accessToken', cookieBaseConfig);\n Cookies.remove('refreshToken', cookieBaseConfig);\n Cookies.remove('idToken', cookieBaseConfig);\n}\n\nexport function clearUser() {\n Cookies.remove('user', cookieBaseConfig);\n}\n\nexport function clearAllAuth() {\n clearToken();\n clearUser();\n}\n\n// return 1, 2, 3, 4 (strong)\nexport function testPasswordStrength(pwd = '') {\n let strongRegex = new RegExp(\n '^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#$%^&*])(?=.{8,})'\n );\n let mediumRegex = new RegExp(\n '^(((?=.*[a-z])(?=.*[A-Z]))|((?=.*[a-z])(?=.*[0-9]))|((?=.*[A-Z])(?=.*[0-9])))(?=.{8,})'\n );\n if (strongRegex.test(pwd)) {\n return 4;\n }\n if (mediumRegex.test(pwd)) {\n if (pwd.length >= 6) {\n return 3;\n } else {\n return 2;\n }\n }\n return 1;\n}\n\nexport function testInviteCode(code: string) {\n const allowed = [\n '92f3bf45390c5bfc4fa03f9378486bec6395918e35f412faf5a78da96fddc1c198cd211d9fa1c5ae0b658dabc67788bf3e8d8835f3e7495e8162550de0dcf056',\n '498e2c4988a239aba05e9fdee2a307568facaf66cfcea06fe0f3631fb6a6ef066f6d2901473fe86591938689031e9bd933a259023ab0cec6f21821ec5bfaae28',\n '620c5756739d618c3b98e6d933ff9cb423de9f53c99002f2a5208b87e6a388d7509d75119e15561afdb551ddb469ad51b4ebda4cd84ed122ef130ec2448a9e77',\n 'fdecac90672d1743d5d3616f774cf0562d2e277007e8a96e8a9be89aacd5fed6a50bf3ad6f1ba5fa2fb0af20b020a54421f87139081406d0d0a62972bf519ce7',\n 'c19b36cc882f011f7c065215ebed135cf2df9956068c12bb5a80b2bbd091381eb6db4c086d548f8aede74c5458c8787956029bd567f645a9832444337119c8f1',\n ];\n const salt = 'xaareawdfgagpaw';\n const res = sha512(code + salt);\n return allowed.includes(res);\n}\nexport function isCn() {\n return process.env.REACT_APP_BUILD_ENV === 'cn';\n}\nexport function isProd() {\n return process.env.REACT_APP_BUILD_ENV === 'prod';\n}\nexport function isDev() {\n return process.env.REACT_APP_BUILD_ENV === 'dev';\n}\nexport function isLocal() {\n return process.env.REACT_APP_BUILD_ENV === 'local';\n}\nexport function isFromTidy3d() {\n return isFromApp('tidy3d');\n}\n\nexport function isFromFlow360() {\n return isFromApp('flow360');\n}\n\nexport function isFromAdmin() {\n return isFromApp('admin');\n}\nexport function isFromBoss() {\n return isFromApp('boss');\n}\nexport function isFromLog() {\n return isFromApp('logapp');\n}\nexport function isFromInternal() {\n return isFromAdmin() || isFromLog() || isFromBoss();\n}\n/**\n * Parse and extract ${app} from URL\n * @returns {string}\n */\nexport function getAppNameFromUrl() {\n if (isFromTidy3d()) {\n return 'tidy3d';\n } else if (isFromAdmin()) {\n return 'admin';\n } else if (isFromBoss()) {\n return 'boss';\n } else if (isFromFlow360()) {\n return 'flow360';\n } else if (isFromLog()) {\n return 'logapp';\n }\n}\nexport function getAppTitleFromUrl() {\n if (isFromTidy3d()) {\n return 'Tidy3D - FDTD for Electromagnetic Simulation | Flexcompute Inc.';\n } else if (isFromFlow360()) {\n return 'Flow360 - The revolutionary CFD solver | Flexcompute Inc.';\n }\n return 'Flexcompute Inc.';\n}\nexport function getAppDescFromUrl() {\n if (isFromTidy3d()) {\n return 'Faster, Larger Simulations - A new solver dedicated to next-generation chips has yielded a simulation breakthrough';\n } else if (isFromFlow360()) {\n return 'A Scalable CFD Solver for Better Product Design - Flow360 Solver is a revolutionary CFD solver based on a breakthrough computing architecture that results in scalability of accurate aerodynamic simulations at unprecedented speeds.';\n }\n return 'Flexcompute Inc.';\n}\nexport function isFromApp(appName: string) {\n const params = getUrlQueryParams();\n const ref = decodeURIComponent((params.ref as string) || '');\n // const app = params.app || '';\n // const isFromApp =\n // ref.indexOf(`${appName}.simulation.cloud`) > -1 ||\n // app.toLowerCase() === appName;\n // const isFromApp = ref.indexOf(`${appName}.simulation.cloud`) > -1;\n const reg = new RegExp(\n appName +\n '\\\\.((dev\\\\-)|(uat\\\\-)|(aws\\\\-)|(itar\\\\-))??(simulation|fangzhen)\\\\.cloud',\n 'i'\n );\n const isFromApp = reg.test(ref);\n return isFromApp;\n}\nexport function isFromClientHost(\n clientHost: string,\n host = window.location.host\n) {\n const reg = new RegExp(\n `^${clientHost}-.*\\\\.((dev-)|(uat-)|(aws-)|(itar-))??(simulation|fangzhen)\\\\.cloud$`,\n 'i'\n );\n const isFromClientHost = reg.test(host);\n return isFromClientHost;\n}\nexport function isFromAnduril() {\n return isFromClientHost('anduril');\n}\nexport function jumpToAnduril() {\n const config = getProviderConfig('anduril');\n if (config) {\n window.location.href = config.loginUrl;\n }\n}\n// export function getDefaultAppHost(appName) {\n// appName = getAppNameFromUrl() || 'flow360';\n// if (isFromApp(appName)) {\n// return `${getDefaultHostPrefix()}${appName}.simulation.cloud`;\n// }\n// }\n\n// export function getDefaultHostPrefix() {\n// const BUILD_ENV = process.env.REACT_APP_BUILD_ENV;\n// if (BUILD_ENV === 'prod') {\n// return '';\n// } else if (BUILD_ENV === 'uat') {\n// return 'uat-';\n// }\n// return 'dev-';\n// }\n// const PAGE_TITLE_MAP = {\n// '/login': {\n// title: 'Sign In',\n// },\n// '/reset_password': {\n// title: 'Reset Password',\n// },\n// '/signup': {\n// title: 'Sign Up',\n// },\n// };\nexport function initDocTitleAndDesc() {\n const title = getAppTitleFromUrl();\n const desc = getAppDescFromUrl();\n // const pageTitle = PAGE_TITLE_MAP[location?.pathname]?.title || '';\n const headTitleEle = document.getElementById('headTitle') as HTMLTitleElement;\n const metaTitleEle = document.getElementById('metaTitle') as HTMLMetaElement;\n const metaDescEle = document.getElementById('metaDesc') as HTMLMetaElement;\n headTitleEle.innerText = title;\n metaTitleEle.content = title;\n metaDescEle.content = desc;\n}\nexport function encodeUrlJson(obj: any): string {\n try {\n return encodeURIComponent(JSON.stringify(obj)) || '';\n } catch (e) {\n console.error(e);\n return '';\n }\n}\nexport function decodeUrlJson(str: string) {\n try {\n return JSON.parse(decodeURIComponent(str)) || {};\n } catch (e) {\n console.error(e);\n return {};\n }\n}\nexport function initHubspotForm(formId: string, formData: any) {\n const iframeName = `${Date.now()}_form`;\n\n const form = document.createElement('form');\n form.id = formId;\n form.style.display = 'none';\n form.target = iframeName;\n Object.entries(formData ?? {}).forEach(([name, value]) => {\n const input = document.createElement('input');\n input.type = 'text';\n input.name = name;\n input.value = value as string;\n form.appendChild(input);\n });\n const submitBtn = document.createElement('button');\n submitBtn.type = 'submit';\n form.appendChild(submitBtn);\n\n const iframe = document.createElement('iframe');\n iframe.style.visibility = 'none';\n iframe.width = '0';\n iframe.height = '0';\n iframe.name = iframeName;\n // iframe.srcdoc = div.innerHTML;\n document.body.appendChild(iframe);\n document.body.appendChild(form);\n return {\n submit: () => {\n clearHubspotCache();\n setTimeout(() => {\n submitBtn.click();\n document.body.removeChild(iframe);\n document.body.removeChild(form);\n }, 1000);\n },\n };\n}\nexport function clearHubspotCache() {\n localStorage.removeItem('li_submission');\n}\nexport function addTokenToUrl(url: string, token: string) {\n const resultUrl = new URL(url);\n resultUrl.searchParams.set(ONE_TIME_TOKEN_KEY, token);\n return resultUrl.href;\n}\n","export default __webpack_public_path__ + \"static/media/flow360_logo.33383d3d.svg\";","export const LOGIN_SALT = '5ac0e45f46654d70bda109477f10c299';\n","import { sha512 } from 'js-sha512';\n\nimport { LOGIN_SALT } from '../constants';\n\nexport function toUsername(email: string) {\n return email.toLowerCase().replace('@', '-at-');\n}\n\nexport function hashPassword(password: string) {\n return sha512(password + LOGIN_SALT);\n}\n","// extracted by mini-css-extract-plugin\nmodule.exports = {\"reset_password_page\":\"index_reset_password_page__mza6C\",\"success_msg\":\"index_success_msg__3Td9p\"};","// extracted by mini-css-extract-plugin\nmodule.exports = {\"sign_up_page\":\"index_sign_up_page__1i2qk\",\"success_msg\":\"index_success_msg__2Vb4k\"};","export interface ProviderConfigMap {\n anduril: ProviderConfig;\n}\nexport interface ProviderConfig {\n redirectUrl: string;\n loginUrl: string;\n}\nconst dev: ProviderConfigMap = {\n anduril: {\n redirectUrl: 'https://anduril-flow360.dev-simulation.cloud',\n loginUrl: `https://sso.dev-simulation.cloud/oauth2/authorize?client_id=3juubqouhhf354ai4b79tcal2j&response_type=code&scope=email+openid+profile&redirect_uri=https://anduril-my.dev-simulation.cloud/callback/flow360/anduril`,\n },\n};\nconst uat: ProviderConfigMap = {\n anduril: {\n redirectUrl: 'https://anduril-flow360.uat-simulation.cloud',\n loginUrl: `https://sso.uat-simulation.cloud/oauth2/authorize?client_id=24oodmcut9qcrbiij0i274cnrf&response_type=code&scope=email+openid+profile&redirect_uri=https://anduril-my.uat-simulation.cloud/callback/flow360/anduril`,\n },\n};\nconst pentest: ProviderConfigMap = { ...uat };\nconst prod: ProviderConfigMap = {\n anduril: {\n redirectUrl: 'https://anduril-flow360.simulation.cloud',\n loginUrl: `https://sso.simulation.cloud/oauth2/authorize?client_id=41ut0khprdcacuc5cfedl4s3hh&response_type=code&scope=email+openid+profile&redirect_uri=https://anduril-my.simulation.cloud/callback/flow360/anduril`,\n },\n};\n\nexport function getProviderConfigMap(): ProviderConfigMap {\n const BUILD_ENV = process.env.REACT_APP_BUILD_ENV;\n if (BUILD_ENV === 'prod') {\n return prod;\n } else if (BUILD_ENV === 'uat') {\n return uat;\n } else if (BUILD_ENV === 'pentest') {\n return pentest;\n }\n return dev;\n}\nexport function getProviderConfig(provider: string): ProviderConfig | null {\n const providerConfigMap = getProviderConfigMap();\n return providerConfigMap[provider as keyof typeof providerConfigMap] ?? null;\n}\n","import { cookieDomain } from '../utils/domain';\nimport { getAppConfigMap } from './appConfig';\n\nexport interface PortalConfig {\n cookieDomain?: string;\n loginUrl: string;\n homeUrl: string;\n}\nconst basic = {\n cookieDomain: cookieDomain,\n loginUrl: `${window.location.origin}/login`,\n};\nconst dev: PortalConfig = {\n ...basic,\n homeUrl: `${basic.loginUrl}?ref=${getAppConfigMap().flow360.redirectUrl}`,\n};\nconst uat: PortalConfig = {\n ...basic,\n homeUrl: 'https://www.simulation.cloud',\n};\nconst pentest: PortalConfig = {\n ...basic,\n homeUrl: 'https://www.simulation.cloud',\n};\nconst prod: PortalConfig = {\n ...basic,\n homeUrl: 'https://www.simulation.cloud',\n};\nconst cn: PortalConfig = {\n ...basic,\n homeUrl: `${basic.loginUrl}?ref=${getAppConfigMap().flow360.redirectUrl}`,\n};\nexport function getPortalConfig(): PortalConfig {\n const BUILD_ENV = process.env.REACT_APP_BUILD_ENV;\n if (BUILD_ENV === 'prod') {\n return prod;\n } else if (BUILD_ENV === 'uat') {\n return uat;\n } else if (BUILD_ENV === 'pentest') {\n return pentest;\n } else if (BUILD_ENV === 'cn') {\n return cn;\n }\n return dev;\n}\n\nexport default getPortalConfig();\n","import React, { Component } from 'react';\nimport { Row, Col, Select } from 'antd';\nimport countryList from './country-region.json';\n\nconst { Option } = Select;\n\nexport interface CountrySelectProps {\n value?: [Country | null, Region | null];\n needRegion: boolean;\n onChange?: (value: [Country | null, Region | null]) => void;\n}\nexport interface CountrySelectState {\n selectedCountry: Country | null;\n selectedRegion: Region | null;\n regionList: Region[];\n}\nexport interface Region {\n code: string;\n name: string;\n}\nexport interface Country extends Region {\n regionList?: Region[];\n}\nexport default class CountrySelect extends Component<\n CountrySelectProps,\n CountrySelectState\n> {\n constructor(props: CountrySelectProps) {\n super(props);\n const { value } = props;\n const [selectedCountry = null, selectedRegion = null] = value || [];\n const regionList =\n countryList.find(country => country.code === selectedCountry?.code)\n ?.regionList || [];\n this.state = {\n selectedCountry,\n selectedRegion,\n regionList,\n };\n }\n isRegionSelectVisible = () => {\n const { needRegion } = this.props;\n if (!needRegion) {\n return false;\n }\n const { selectedCountry, regionList } = this.state;\n if (!selectedCountry || regionList?.length) {\n // if (regionList?.length) {\n return true;\n } else {\n return false;\n }\n };\n onCountryChange = (value: string, { data }: { data: Country }) => {\n const { onChange } = this.props;\n //exclude regionList from data\n const { regionList, ...selectedCountry } = data;\n this.setState(\n {\n selectedCountry: selectedCountry,\n selectedRegion: null,\n regionList: regionList || [],\n },\n () => {\n onChange?.([selectedCountry, null]);\n }\n );\n };\n onRegionChange = (value: string, { data }: { data: Region }) => {\n const { onChange } = this.props;\n const { selectedCountry } = this.state;\n this.setState(\n {\n selectedCountry,\n selectedRegion: data,\n },\n () => {\n onChange?.([selectedCountry, data]);\n }\n );\n };\n render() {\n const { selectedCountry, selectedRegion, regionList } = this.state;\n const isRegionVisible = this.isRegionSelectVisible();\n return (\n \n \n \n {countryList.map(country => (\n \n {country.name}\n \n ))}\n \n \n {isRegionVisible && (\n \n \n {regionList?.map(region => (\n \n {region.name}\n \n ))}\n \n \n )}\n
\n );\n }\n}\n","// extracted by mini-css-extract-plugin\nmodule.exports = {\"login_page\":\"index_login_page__1sYMo\",\"hidden\":\"index_hidden__1J7LR\"};","// extracted by mini-css-extract-plugin\nmodule.exports = {\"success_msg\":\"index_success_msg__gc3EQ\"};","// extracted by mini-css-extract-plugin\nmodule.exports = {\"micro_soft_page\":\"index_micro_soft_page__1dyME\",\"success_msg\":\"index_success_msg__rkP0t\"};","import axios, { AxiosResponse } from 'axios';\nimport { isFromTidy3d } from './util';\nexport interface ResponseData {\n code: number | string;\n [key: string]: any;\n}\nlet fetcher = axios.create({\n withCredentials: false,\n headers: {\n 'Access-Control-Allow-Origin': '*',\n 'content-type': 'application/json',\n Application: isFromTidy3d() ? 'TIDY3D' : '',\n },\n});\n\n// Request interceptors\nfetcher.interceptors.request.use(\n config => {\n const { headers = {}, params = {} } = config;\n const _ = Date.now();\n config.headers = {\n ...headers,\n };\n //add timestamp\n config.params = {\n _,\n ...params,\n };\n return config;\n },\n error => {\n return Promise.reject(error);\n }\n);\n\n// Response interceptors\nfunction checkStatus(response: AxiosResponse) {\n if (response.status >= 200 && response.status < 300) {\n response.data.code =\n parseInt(`${response.data.code}`, 10) || response.status;\n return response.data;\n }\n}\nfetcher.interceptors.response.use(\n function (response) {\n return checkStatus(response);\n },\n function (e) {\n return Promise.reject(e);\n }\n);\n\nfetcher.interceptors.response.use(\n function (response) {\n return response;\n },\n function (error) {\n const code = parseInt(error.response?.data?.code || error.response.status);\n const message = error.response?.data?.error || error.message;\n return Promise.reject({\n ...error,\n code,\n message,\n });\n }\n);\n\n// export const post = fetcher.post;\n// export const put = fetcher.put;\n// export const get = axios.get;\n// export const del = (url, params) => {\n// return fetcher.delete(url, { params });\n// };\nexport default fetcher;\n","import { AxiosRequestConfig } from 'axios';\nimport request from './request';\n\nexport interface RequestApiConfig {\n method: 'get' | 'post' | 'put' | 'delete';\n url: string;\n isUpload?: boolean;\n timeout?: number;\n}\nexport interface RequestApiConfigMap {\n [key: string]: RequestApiConfig;\n}\nconst upload = (\n apiConfig: RequestApiConfig,\n data: any,\n config: AxiosRequestConfig\n) => {\n const { url, method } = apiConfig;\n if (data instanceof FormData) {\n }\n return request({\n url,\n method,\n data,\n headers: {\n 'Content-Type': 'multipart/form-data',\n },\n ...config,\n });\n};\n\nexport const generator = (APIS: RequestApiConfigMap) => {\n const api: { [key: string]: Function } = {};\n Object.entries(APIS).forEach(([apiKey = '', apiConfig]) => {\n const { method = 'get', url = '', isUpload = false } = apiConfig || {};\n if (!apiKey || !apiConfig || !url) {\n return;\n }\n switch (method.toUpperCase()) {\n case 'POST':\n api[apiKey] = (data: any, config = {}) =>\n isUpload\n ? upload(apiConfig, data, config)\n : request.post(url, data, config);\n break;\n case 'DELETE':\n api[apiKey] = (params: any, config = {}) =>\n request.delete(url, { params, ...config });\n break;\n case 'PUT':\n api[apiKey] = (data: any, config = {}) =>\n request.put(url, data, config);\n break;\n case 'GET':\n default:\n api[apiKey] = (params: any, config = {}) =>\n request.get(url, { params, ...config });\n }\n });\n return api;\n};\n","export interface EnvConfig {\n webapiV2: {\n URL: string;\n };\n}\nconst dev: EnvConfig = {\n webapiV2: {\n URL: 'https://portal-api.dev-simulation.cloud',\n //URL: \"http://localhost:5000\",\n },\n};\n\nconst prod: EnvConfig = {\n webapiV2: {\n URL: 'https://portal-api.simulation.cloud',\n },\n};\nconst uat: EnvConfig = {\n webapiV2: {\n URL: 'https://portal-api.uat-simulation.cloud',\n //URL: \"http://localhost:5000\",\n },\n};\nconst pentest: EnvConfig = {\n ...uat,\n webapiV2: {\n URL: 'https://pentest-portal-api.uat-simulation.cloud',\n //URL: \"http://localhost:5000\",\n },\n};\nconst cn: EnvConfig = {\n webapiV2: {\n URL: 'https://portal-api.fangzhen.cloud',\n },\n};\nexport function getConfig(): EnvConfig {\n const BUILD_ENV = process.env.REACT_APP_BUILD_ENV;\n if (BUILD_ENV === 'prod') {\n return prod;\n } else if (BUILD_ENV === 'uat') {\n return uat;\n } else if (BUILD_ENV === 'pentest') {\n return pentest;\n } else if (BUILD_ENV === 'cn') {\n return cn;\n }\n return dev;\n}\n\nexport default getConfig();\n","import { generator, RequestApiConfigMap } from '../utils/apiGenerator';\nimport config from '../constants/envConfig';\nconst { webapiV2 } = config;\nconst APIS: RequestApiConfigMap = {\n login: {\n method: 'get',\n url: `${webapiV2.URL}/auth`,\n },\n oauth2: {\n method: 'get',\n url: `${webapiV2.URL}/oauth2/token`,\n },\n sendRegisterEmail: {\n method: 'post',\n url: `${webapiV2.URL}/auth/register`,\n },\n sendWaitingEmail: {\n method: 'post',\n url: `${webapiV2.URL}/anonymous/waitinglist`,\n },\n verifyEmail: {\n method: 'put',\n url: `${webapiV2.URL}/auth/verify`,\n },\n resendEmail: {\n method: 'put',\n url: `${webapiV2.URL}/auth/resend`,\n },\n forgotPassword: {\n method: 'post',\n url: `${webapiV2.URL}/auth/forgot-password`,\n },\n saveKyc: {\n method: 'put',\n url: `${webapiV2.URL}/auth/kyc`,\n },\n mfaAuth: {\n method: 'post',\n url: `${webapiV2.URL}/auth/challenge`,\n },\n mfaReset: {\n method: 'post',\n url: `${webapiV2.URL}/auth/mfa/reset`,\n },\n mfaResetConfirm: {\n method: 'post',\n url: `${webapiV2.URL}/auth/mfa/resetConfirm`,\n },\n confirmPassword: {\n method: 'post',\n url: `${webapiV2.URL}/auth/confirm-forget-password`,\n },\n checkIp: {\n method: 'get',\n url: `${webapiV2.URL}/auth/check`,\n timeout: 3000,\n },\n getMicrosoftLoginMetadata: {\n method: 'get',\n url: `${webapiV2.URL}/auth/pre/metadata`,\n timeout: 3000,\n },\n};\nexport default generator(APIS);\n","export default __webpack_public_path__ + \"static/media/logo2.1567433e.png\";","import React, { Component } from 'react';\nimport { Button } from 'antd';\nimport AuthLayout from '@/components/AuthLayout';\nimport flow360Logo from '../../../assets/flow360_logo.svg';\nimport { jumpToAnduril } from '../../../utils/util';\nimport styles from './index.module.less';\n\nexport default class AndurilLoginPage extends Component {\n render() {\n return (\n \n
\n \n
\n
Welcome to Flow360!
\n
\n Flow360 Solver is a Scalable CFD Solver for Better Product Design\n
\n
\n {\n jumpToAnduril();\n }}\n type={'primary'}\n className={styles.sign_in_btn}\n >\n Sign In\n \n
\n
\n \n
\n );\n }\n}\n","export default __webpack_public_path__ + \"static/media/google_icon.e6226f71.svg\";","export default __webpack_public_path__ + \"static/media/microsoft_icon.28d8f59e.svg\";","import React, { Component } from 'react';\nimport { Link, RouteComponentProps, withRouter } from 'react-router-dom';\nimport {\n Form,\n Input,\n Button,\n Divider,\n FormInstance,\n Radio,\n RadioChangeEvent,\n} from 'antd';\nimport { AppleFilled } from '@ant-design/icons';\n\nimport styles from './index.module.less';\nimport { getCurrentAppConfig } from '@/constants/appConfig';\nimport googleIcon from '../../../../assets/google_icon.svg';\nimport microsoftIcon from '../../../../assets/microsoft_icon.svg';\nimport {\n encodeUrlJson,\n getUrlQueryParams,\n isFromFlow360,\n isFromTidy3d,\n isFromInternal,\n isCn,\n} from '../../../../utils/util';\n\nconst { Item } = Form;\nconst { Password } = Input;\nconst appTypeOptions = [\n { label: 'Flow360', value: 'FLOW360' },\n { label: 'Tidy3d', value: 'TIDY3D' },\n];\n\nexport interface LoginPanelProps extends RouteComponentProps {\n onLogin: (data: any) => void;\n loading: boolean;\n}\nexport interface LoginPanelState {\n referralCode: string;\n ref: string;\n appType: string;\n}\nclass LoginPanel extends Component {\n constructor(props: LoginPanelProps) {\n super(props);\n const params = getUrlQueryParams();\n let appType = 'FLOW360'; // Default to FLOW360\n\n if (isFromFlow360()) {\n appType = 'FLOW360';\n } else if (isFromTidy3d()) {\n appType = 'TIDY3D';\n }\n this.state = {\n referralCode: (params.referralCode as string) || '',\n ref: params.ref as string,\n appType: appType,\n };\n }\n form: FormInstance | null = null;\n onChange = (e: RadioChangeEvent) => {\n this.setState({ appType: e.target.value });\n };\n login = () => {\n this.form?.validateFields().then(formData => {\n const { email } = formData;\n const { onLogin } = this.props;\n onLogin({\n ...formData,\n appType: this.state.appType.toUpperCase(),\n email: email.toLowerCase(),\n });\n });\n };\n render() {\n const { referralCode, ref, appType } = this.state;\n const { loading, location } = this.props;\n const currentAppConfig = getCurrentAppConfig();\n const layout = {\n labelCol: {\n span: 0,\n },\n wrapperCol: {\n span: 24,\n },\n };\n return (\n \n );\n }\n}\nexport default withRouter(LoginPanel);\n","import React, { PureComponent } from 'react';\nimport { isFromApp } from '../utils/util';\nimport portalConfig from '../constants/portalConfig';\n\n// auth HOC, handle auth logic globally\nexport default function auth(WrappedComponent: Function) {\n return class extends PureComponent {\n isLegal = () => {\n const isSimulationCloud = isFromApp('');\n if (!isSimulationCloud) {\n this.goHome();\n return false;\n }\n return isSimulationCloud;\n };\n goHome = () => {\n window.location.href = portalConfig.homeUrl;\n };\n render() {\n if (!this.isLegal()) {\n return null;\n }\n return ;\n }\n };\n}\n","import React, { Component } from 'react';\nimport { notification } from 'antd';\nimport { sha512 } from 'js-sha512';\nimport LogRocket from 'logrocket';\n\nimport AuthLayout from '@/components/AuthLayout';\nimport { LOGIN_SALT } from '@/constants';\nimport {\n getUrlQueryParams,\n setToken,\n setUser,\n setLoginFlag,\n addTokenToUrl,\n} from '@/utils/util';\nimport api from '@/services';\nimport { RouteComponentProps } from 'react-router-dom';\nimport LoginPanel from './components/LoginPanel';\nimport auth from '../auth';\n\nimport styles from './index.module.less';\nimport ResendModal from '../../components/ResendModal';\n// import { getDefaultAppHost } from '../../utils/util';\n\nexport interface LoginPageProps extends RouteComponentProps {}\nexport interface LoginPageState {\n loading: boolean;\n ref: string;\n resendEmail: string;\n resendModalVisible: boolean;\n}\nclass LoginPage extends Component {\n constructor(props: LoginPageProps) {\n super(props);\n const params = getUrlQueryParams();\n this.state = {\n loading: false,\n ref: decodeURIComponent((params.ref as string) || ''),\n resendEmail: '',\n resendModalVisible: false,\n };\n }\n\n componentDidMount() {\n // bypass login if accessToken exists\n // if (Cookies.get('accessToken')) {\n // this.redirect();\n // }\n }\n\n redirect = (token: string) => {\n const { ref } = this.state;\n if (ref) {\n window.location.href = addTokenToUrl(ref, token);\n } else {\n notification.warning({\n message: 'No ref found',\n description: 'Login success, but no [ref] param found in url address',\n });\n // window.location.href = getDefaultAppHost();\n }\n };\n loading = (loading = false) => {\n this.setState({\n loading: loading,\n });\n };\n onLogin = async (formData: any) => {\n const { email, password, appType } = formData;\n\n try {\n this.loading(true);\n LogRocket.identify(email, {\n name: email,\n email,\n });\n LogRocket.track('login start', { email });\n const { data } = await api.login(\n {},\n {\n auth: {\n username: email,\n password: sha512(password + LOGIN_SALT),\n },\n headers: {\n Application: appType,\n },\n }\n );\n LogRocket.track('login success', { email });\n const { authResult } = data;\n if (authResult?.challengeName === 'SOFTWARE_TOKEN_MFA') {\n const { history, location } = this.props;\n history.push({\n ...location,\n pathname: '/challenge',\n state: {\n email,\n challengeData: authResult,\n },\n });\n } else {\n const {\n auth: {\n accessToken,\n refreshToken,\n idToken,\n // expiresIn = 36000\n },\n oneTimeToken,\n user,\n } = data;\n const { email: userEmail, identityId } = user;\n const expires = 365;\n // const expires = new Date(Date.now() + expiresIn * 1000);\n // save token to cookies, default alive in 36000 sec\n setToken({ accessToken, refreshToken, idToken }, { expires });\n setUser({ email: userEmail, identityId }, { expires });\n setLoginFlag();\n // window.frames[0].postMessage(JSON.stringify(user), ref);\n this.redirect(oneTimeToken);\n }\n } catch (e: any) {\n LogRocket.track('login error', { email, message: e.message });\n // unconfirmed user\n if (e.code === 4010000002) {\n this.showResendModal(email);\n } else {\n notification.error({\n message: 'Incorrect email or password',\n description: e.message || 'Please try again or contact the admin',\n });\n }\n } finally {\n this.loading(false);\n }\n };\n showResendModal = (resendEmail: string) => {\n this.setState({\n resendEmail,\n resendModalVisible: true,\n });\n };\n hideResendModal = () => {\n this.setState({\n resendModalVisible: false,\n });\n };\n render() {\n const { loading, resendEmail, resendModalVisible } = this.state;\n return (\n \n }\n email={resendEmail}\n visible={resendModalVisible}\n onCancel={this.hideResendModal}\n />\n \n );\n }\n}\nexport default auth(LoginPage);\n","import React, { Component } from 'react';\nimport { Link, RouteComponentProps, withRouter } from 'react-router-dom';\nimport { Form, Input, Button, FormInstance } from 'antd';\nimport OtpInput from 'react-otp-input';\n\nimport styles from './index.module.less';\n\nconst { Item } = Form;\n\nexport interface ChallengePanelProps extends RouteComponentProps {\n onSubmit: (data: any) => void;\n loading: boolean;\n onDisable: () => void;\n}\nclass ChallengePanel extends Component