diff --git a/.babelrc b/.babelrc.old
similarity index 86%
rename from .babelrc
rename to .babelrc.old
index 2ab6b2d3..1861e81e 100644
--- a/.babelrc
+++ b/.babelrc.old
@@ -1,5 +1,4 @@
{
- "presets": ["next/babel"],
"env": {
"test": {
"plugins": [
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 9ae61c40..fcab8fc3 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -13,7 +13,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
- node-version: [16.19.0]
+ node-version: [18.17.1]
steps:
- uses: actions/setup-node@v2.1.5
with:
diff --git a/README.md b/README.md
index ad913aca..33aa16bd 100644
--- a/README.md
+++ b/README.md
@@ -73,70 +73,77 @@ yarn test:headless
- Structure of the React components in this app
-Application (in pages/\_app.js) contains:
+**Startup** is main.jsx which renders the Application (App)
+
+**Application** (App.jsx) contains:
- AuthContext context
- StoreContext context:
-Home (in pages/index.js) contains:
-
-
-
-
-WorkspaceContainer component manages the Resource workspace
-
-- Contains Workspace component (resource workspace rcl) that contains several:
- - ScriptureCard components
- - ResourceCard components
+
+
+
+
+
+
+
-Layout component:
+**Layout** component:
- accesses authentication context and store context
- Manages server selection through url variables
- Displays Onboarding component if login is required
+- displays the settings page if selected
- Contains the header and footer
-BibleReference component:
+**WorkspaceContainer** component manages the workspace containing the resource cards
+
+- Contains Workspace component (resource workspace rcl) that contains several cards of type:
+ - ScriptureCard components
+ - ResourceCard components
+
+**BibleReference** component:
- Uses bible Reference RCL
- Updates reference store context
-Onboarding component
+**Onboarding** component
- Displays the AccountSetup component when login is required
-Header component:
+**Header** component:
- Contains BibleReference component
-Footer component:
+**Footer** component:
- Shows app version/build
-Drawer component (hamburger menu):
+**Drawer** component (hamburger menu):
- Shows
-TranslationSettings component:
+**TranslationSettings** component:
- Prompts for organization and language
-ResourceCard component:
+**ResourceCard** component:
- Card that displays translationHelps content
-ScriptureCard component:
+**ScriptureCard** component:
- Card that displays scripture content
-AuthContext context:
+**AuthContext** context:
- Initializes the authentication context (defined in gitea-react-toolkit)
StoreContext context:
-- Manages and persists application state data into local storage
+- Manages and persists the rest of the application state data into local storage
useLocalStorage - custom hook that persists generic application data into local storage
useUserLocalStorage - custom hook that application data for logged in user into local storage
+
diff --git a/index.html b/index.html
new file mode 100644
index 00000000..e3ac1cce
--- /dev/null
+++ b/index.html
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+ gatewayEdit
+
+
+
+
+
+
diff --git a/jest.config.js b/jest.config.js
deleted file mode 100644
index ef1cf259..00000000
--- a/jest.config.js
+++ /dev/null
@@ -1,37 +0,0 @@
-module.exports = {
- 'roots': [''],
- // 'transform': { '^.+\\.ts?$': 'ts-jest' },
- 'moduleFileExtensions': [
- 'js',
- 'ts',
- ],
- 'coveragePathIgnorePatterns': [
- '/node_modules/',
- '/.yalc/',
- 'scripts',
- 'cypress',
- ],
- 'testPathIgnorePatterns': [
- '/node_modules/',
- 'components',
- 'cypress',
- '/.yalc/',
- 'scripts',
- ],
- 'testMatch': [
- '**/?(*.)+(spec|test).[jt]s?(x)',
- ],
- 'moduleNameMapper': {
- '^@common/(.*)$': '/src/common/$1',
- '^@components/(.*)$': '/src/components/$1',
- '^@context/(.*)$': '/src/context/$1',
- '^@hooks/(.*)$': '/src/hooks/$1',
- '^@utils/(.*)$': '/src/utils/$1',
- },
- 'collectCoverageFrom': [
- './src/**.{js,jsx,ts}',
- '!**/node_modules/**',
- '!**/vendor/**',
- ],
- 'coverageDirectory': 'jest-coverage',
-}
diff --git a/netlify.toml b/netlify.toml
index faaee64b..583a2e19 100644
--- a/netlify.toml
+++ b/netlify.toml
@@ -2,8 +2,5 @@
command = "npm run build"
publish = "out"
-[[plugins]]
- package = "@netlify/plugin-nextjs"
-
[[plugins]]
package = "/scripts/zulip-notification"
diff --git a/package.json b/package.json
index 6919743c..a471e1f6 100644
--- a/package.json
+++ b/package.json
@@ -2,18 +2,19 @@
"name": "gateway-edit",
"version": "2.3.0",
"scripts": {
- "dev": "bash -c \"source ./scripts/set-env.sh && next\"",
- "build": "bash -c \"source ./scripts/set-env.sh && next build\"",
- "start": "bash -c \"source ./scripts/set-env.sh && next start\"",
- "export": "next export",
+ "dev": "bash -c \"source ./scripts/set-env.sh && vite\"",
+ "build": "bash -c \"source ./scripts/set-env.sh && vite build\"",
+ "lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0",
+ "preview": "bash -c \"source ./scripts/set-env.sh && vite preview",
+ "exportx": "next export",
"postinstall": "husky install",
"increment-build": "bash scripts/increment-build.sh && git add -A",
"cypress": "cross-env NODE_ENV=test cypress open",
"cypress:headless": "cross-env NODE_ENV=test cypress run",
"test": "cross-env NODE_ENV=test start-server-and-test dev http://localhost:3000 cypress",
"test:headless": "cross-env NODE_ENV=test start-server-and-test dev http://localhost:3000 cypress:headless",
- "test:unit": "cross-env NODE_ENV='test' jest --coverage __tests__",
- "test:unit-nocov": "cross-env NODE_ENV='test' jest",
+ "test:unit": "cross-env NODE_ENV='test' vitest --coverage __tests__",
+ "test:unit-nocov": "cross-env NODE_ENV='test' vitest",
"coverage-summary": "yarn nyc report --reporter=text-summary",
"mkdir:reports": "mkdir reports || true",
"precopy:reports": "yarn mkdir:reports",
@@ -41,7 +42,6 @@
"gitea-react-toolkit": "2.4.0",
"localforage": "^1.9.0",
"markdown-translatable": "2.0.3",
- "next": "10.2.0",
"postcss": "^8.2.1",
"react": "^17.0.2",
"react-bootstrap": "0.32.4",
@@ -52,7 +52,7 @@
"resource-workspace-rcl": "2.1.4",
"scripture-resources-rcl": "5.5.9",
"scripture-tsv": "0.4.0",
- "single-scripture-rcl": "3.4.17",
+ "single-scripture-rcl": "3.4.19-beta.2",
"tailwindcss": "^2.0.4",
"tc-ui-toolkit": "5.3.3",
"translation-helps-rcl": "3.5.14",
@@ -61,16 +61,12 @@
"word-aligner-rcl": "1.0.4"
},
"devDependencies": {
- "@babel/core": "^7.15.8",
- "@babel/preset-env": "^7.15.8",
"@cypress/code-coverage": "^3.9.11",
"@cypress/instrument-cra": "^1.4.0",
"@testing-library/jest-dom": "^5.14.1",
"@testing-library/react": "^12.1.2",
"@types/jest": "^27.0.2",
- "babel-eslint": "^10.1.0",
- "babel-jest": "^27.3.1",
- "babel-plugin-istanbul": "^6.1.1",
+ "@vitejs/plugin-react": "^4.2.0",
"cross-env": "7.0.3",
"cypress": "^8.6.0",
"eslint": "^7.16.0",
@@ -86,12 +82,13 @@
"eslint-plugin-react": "^7.21.5",
"eslint-plugin-react-hooks": "^4.2.0",
"husky": "^5.2.0",
- "jest": "^27.3.1",
"nyc": "^15.1.0",
"prettier": "^2.2.1",
"prop-types": "^15.7.2",
"react-icons": "^4.8.0",
- "start-server-and-test": "^1.14.0"
+ "start-server-and-test": "^1.14.0",
+ "vite": "4.5.1",
+ "vitest": "0.34.6"
},
"nyc": {
"report-dir": "cypress-coverage"
diff --git a/pages/404.js b/pages/404.js
deleted file mode 100644
index b4d52c68..00000000
--- a/pages/404.js
+++ /dev/null
@@ -1,49 +0,0 @@
-import PropTypes from 'prop-types'
-import Link from 'next/link'
-import Layout from '@components/Layout'
-
-export default function FourOhFour() {
- return (
-
-
-
-
-
-
- This page could not be found.
-
-
-
Go back home
-
-
-
- )
-}
-
-FourOhFour.propTypes = { statusCode: PropTypes.number }
diff --git a/pages/_app.js b/pages/_app.js
deleted file mode 100644
index b7482162..00000000
--- a/pages/_app.js
+++ /dev/null
@@ -1,41 +0,0 @@
-import { useEffect } from 'react'
-import PropTypes from 'prop-types'
-import { ThemeProvider } from '@material-ui/core/styles'
-import CssBaseline from '@material-ui/core/CssBaseline'
-import StoreContextProvider from '@context/StoreContext'
-import AuthContextProvider from '@context/AuthContext'
-import { APP_NAME } from '@common/constants'
-import AppHead from '@components/AppHead'
-import theme from '../src/theme'
-import '@styles/globals.css'
-
-export default function Application({ Component, pageProps }) {
- useEffect(() => {
- // Remove the server-side injected CSS.
- const jssStyles = document.querySelector('#jss-server-side')
-
- if (jssStyles) {
- jssStyles.parentElement.removeChild(jssStyles)
- }
- }, [])
-
- return (
- <>
-
-
- {/* CssBaseline kickstart an elegant, consistent, and simple baseline to build upon. */}
-
-
-
-
-
-
-
- >
- )
-}
-
-Application.propTypes = {
- Component: PropTypes.oneOfType([PropTypes.node, PropTypes.func]),
- pageProps: PropTypes.object,
-}
diff --git a/pages/_document.js b/pages/_document.js
deleted file mode 100644
index 7497f590..00000000
--- a/pages/_document.js
+++ /dev/null
@@ -1,71 +0,0 @@
-import React from 'react'
-import Document, { Html, Head, Main, NextScript } from 'next/document'
-import { ServerStyleSheets } from '@material-ui/core/styles'
-import theme from '../src/theme'
-
-export default class MyDocument extends Document {
- render() {
- return (
-
-
- {/* PWA primary color */}
-
-
-
-
-
-
-
-
- )
- }
-}
-
-// `getInitialProps` belongs to `_document` (instead of `_app`),
-// it's compatible with server-side generation (SSG).
-MyDocument.getInitialProps = async ctx => {
- // Resolution order
- //
- // On the server:
- // 1. app.getInitialProps
- // 2. page.getInitialProps
- // 3. document.getInitialProps
- // 4. app.render
- // 5. page.render
- // 6. document.render
- //
- // On the server with error:
- // 1. document.getInitialProps
- // 2. app.render
- // 3. page.render
- // 4. document.render
- //
- // On the client
- // 1. app.getInitialProps
- // 2. page.getInitialProps
- // 3. app.render
- // 4. page.render
-
- // Render app and page and get the context of the page with collected side effects.
- const sheets = new ServerStyleSheets()
- const originalRenderPage = ctx.renderPage
-
- ctx.renderPage = () =>
- originalRenderPage({
- enhanceApp: App => props => sheets.collect(),
- })
-
- const initialProps = await Document.getInitialProps(ctx)
-
- return {
- ...initialProps,
- // Styles fragment is rendered after the app and page rendering finish.
- styles: [
- ...React.Children.toArray(initialProps.styles),
- sheets.getStyleElement(),
- ],
- }
-}
diff --git a/pages/_error.js b/pages/_error.js
deleted file mode 100644
index e1e1f7e2..00000000
--- a/pages/_error.js
+++ /dev/null
@@ -1,62 +0,0 @@
-import PropTypes from 'prop-types'
-import Error from 'next/error'
-import { useRouter } from 'next/router'
-import Layout from '@components/Layout'
-
-export default function ErrorPage({ statusCode }) {
- const router = useRouter()
-
- if (statusCode) {
- return
- }
-
- localStorage.clear()
-
- const handleClick = (e) => {
- e.preventDefault()
- router.reload()
- router.push('/')
- }
-
- return (
-
-
-
-
- An unexpected error has occurred. The application cache has been cleared.
-
-
-
-
- )
-}
-
-ErrorPage.propTypes = { statusCode: PropTypes.number }
-
-ErrorPage.getInitialProps = ({ res, err }) => {//eslint-disable-next-line
- const statusCode = res ? res.statusCode : err ? err.statusCode : 404
- return { statusCode }
-}
diff --git a/pages/api/feedback.js b/pages/api/feedback.js
deleted file mode 100644
index 86cf7638..00000000
--- a/pages/api/feedback.js
+++ /dev/null
@@ -1,44 +0,0 @@
-import sendFeedback from '../../src/common/sendFeedback'
-
-export default async (req, res) => {
- let errorMessage
-
- if (req.method === 'POST') {
- const { name, email, message, category, extraData } = req.body
-
- try {
- const response = await sendFeedback({
- name,
- email,
- message,
- category,
- extraData,
- })
-
- console.log(`sendFeedback() response: ${JSON.stringify(response)}`)
-
- if (!errorMessage) {
- return res.status(200).json({...response})
- }
- } catch (e) {
- errorMessage = e.toString()
- console.warn(`sendFeedback() errorMessage: ${errorMessage}`)
- }
- }
-
- // see if we can parse http code from message
- let httpCode
- const found = errorMessage.match(/\((\d+)\)/)
-
- if (found?.length > 1) {
- httpCode = parseInt(found[1], 10)
- }
-
- return res.status(404).json({
- error: {
- code: httpCode || 'not_found',
- message: errorMessage ||
- 'The requested endpoint was not found or doesn\'t support this method.',
- },
- })
-}
diff --git a/pages/index.js b/pages/index.js
deleted file mode 100644
index 80d7c0b8..00000000
--- a/pages/index.js
+++ /dev/null
@@ -1,19 +0,0 @@
-import dynamic from 'next/dynamic'
-import Layout from '@components/Layout'
-import CircularProgress from '@components/CircularProgress'
-
-const WorkspaceContainer = dynamic(
- () => import('@components/WorkspaceContainer'),
- {
- ssr: false,
- loading: () => ,
- },
-)
-
-const Home = () => (
-
-
-
-)
-
-export default Home
diff --git a/pages/settings.js b/pages/settings.js
deleted file mode 100644
index bd958324..00000000
--- a/pages/settings.js
+++ /dev/null
@@ -1,37 +0,0 @@
-import { useContext } from 'react'
-import { useRouter } from 'next/router'
-import Button from '@material-ui/core/Button'
-import SaveIcon from '@material-ui/icons/Save'
-import { AuthenticationContext } from 'gitea-react-toolkit'
-import Layout from '@components/Layout'
-import TranslationSettings from '@components/TranslationSettings'
-
-const SettingsPage = () => {
- const router = useRouter()
- const { state: authentication } = useContext(AuthenticationContext)
-
- return (
-
-
-
-
Account Settings
-
-
-
-
-
-
-
- )
-}
-
-export default SettingsPage
diff --git a/scripts/set-env.sh b/scripts/set-env.sh
index 56b03ef8..77ce5847 100644
--- a/scripts/set-env.sh
+++ b/scripts/set-env.sh
@@ -27,9 +27,9 @@ set_env_var() {
}
# Call the function to set the environment variables
-set_env_var $ENV_FILE NEXT_PUBLIC_BUILD_NUMBER $BUILD_NUMBER
-set_env_var $ENV_FILE NEXT_PUBLIC_BUILD_BRANCH $BRANCH
-set_env_var $ENV_FILE NEXT_PUBLIC_BUILD_CONTEXT $CONTEXT
+set_env_var $ENV_FILE VITE_PUBLIC_BUILD_NUMBER $BUILD_NUMBER
+set_env_var $ENV_FILE VITE_PUBLIC_BUILD_BRANCH $BRANCH
+set_env_var $ENV_FILE VITE_PUBLIC_BUILD_CONTEXT $CONTEXT
echo "Environment file new contents: $(cat $ENV_FILE)"
diff --git a/src/common/constants.js b/src/common/constants.js
index 250ce9a7..6bd5105f 100644
--- a/src/common/constants.js
+++ b/src/common/constants.js
@@ -7,7 +7,10 @@ export const QA_BASE_URL = 'https://qa.door43.org'
export const QA = 'QA'
export const PROD = 'PROD'
export const TOKEN_ID = 'gatewayEdit'
+export const ERROR_PAGE = '/error'
export const FEEDBACK_PAGE = '/feedback'
+export const HOME_PAGE = '/'
+export const SETTINGS_PAGE = '/settings'
export const SERVER_KEY = 'server'
export const SERVER_MAX_WAIT_TIME_RETRY = 25000 // in milliseconds
diff --git a/src/common/sendFeedback.js b/src/common/sendFeedback.js
index 940ad538..15d2ab0c 100644
--- a/src/common/sendFeedback.js
+++ b/src/common/sendFeedback.js
@@ -17,14 +17,14 @@ export default async function sendFeedback({ name, email, message, category, ext
}
const msg = {
- to: process.env.HELP_DESK_EMAIL,
+ to: import.meta.env.VITE_HELP_DESK_EMAIL,
from: email,
subject: `gatewayEdit App: ${category}`,
text: fullMessage,
html: fullMessage.replace(/\n/g, '
'),
}
- sgMail.setApiKey(process.env.HELP_DESK_TOKEN)
+ sgMail.setApiKey(import.meta.env.VITE_HELP_DESK_TOKEN)
return sgMail.send(msg)
}
diff --git a/src/components/AccountSetup.js b/src/components/AccountSetup.jsx
similarity index 100%
rename from src/components/AccountSetup.js
rename to src/components/AccountSetup.jsx
diff --git a/src/components/App.jsx b/src/components/App.jsx
new file mode 100644
index 00000000..4e9bf4aa
--- /dev/null
+++ b/src/components/App.jsx
@@ -0,0 +1,28 @@
+import { ThemeProvider } from '@material-ui/core/styles'
+import CssBaseline from '@material-ui/core/CssBaseline'
+import StoreContextProvider from '@context/StoreContext'
+import AuthContextProvider from '@context/AuthContext'
+import '@styles/globals.css'
+import WorkspaceContainer from '@components/WorkspaceContainer'
+import Layout from '@components/Layout'
+import theme from '../theme'
+
+// TODO: set page title again
+
+export default function Application() {
+ return (
+
+ {/* CssBaseline kickstart an elegant, consistent, and simple baseline to build upon. */}
+
+
+
+
+
+
+
+
+
+ )
+}
+
+Application.propTypes = { }
diff --git a/src/components/AppHead.js b/src/components/AppHead.jsx
similarity index 92%
rename from src/components/AppHead.js
rename to src/components/AppHead.jsx
index fb52ea2a..67177bc3 100644
--- a/src/components/AppHead.js
+++ b/src/components/AppHead.jsx
@@ -1,5 +1,5 @@
+//TODO: remove - this is no longer needed as the head is now set in index.html in project folder
import React from 'react'
-import Head from 'next/head'
import { string } from 'prop-types'
const defaultDescription = ''
@@ -7,7 +7,7 @@ const defaultOGURL = ''
const defaultOGImage = ''
const AppHead = props => (
-
+
{props.title || ''}
(
-
+
)
AppHead.propTypes = {
diff --git a/src/components/BibleReference.js b/src/components/BibleReference.jsx
similarity index 100%
rename from src/components/BibleReference.js
rename to src/components/BibleReference.jsx
diff --git a/src/components/CircularProgress.js b/src/components/CircularProgress.jsx
similarity index 100%
rename from src/components/CircularProgress.js
rename to src/components/CircularProgress.jsx
diff --git a/src/components/Drawer.js b/src/components/Drawer.jsx
similarity index 98%
rename from src/components/Drawer.js
rename to src/components/Drawer.jsx
index c1a103c9..450a9f5f 100644
--- a/src/components/Drawer.js
+++ b/src/components/Drawer.jsx
@@ -1,6 +1,5 @@
import React, { useContext } from 'react'
import PropTypes from 'prop-types'
-import { useRouter } from 'next/router'
import SwipeableDrawer from '@material-ui/core/SwipeableDrawer'
import ChevronLeftIcon from '@material-ui/icons/ChevronLeft'
import ListItemIcon from '@material-ui/core/ListItemIcon'
@@ -9,14 +8,14 @@ import ListItemSecondaryAction from '@material-ui/core/ListItemSecondaryAction'
import ExitToAppIcon from '@material-ui/icons/ExitToApp'
import SettingsIcon from '@material-ui/icons/Settings'
import BugReportIcon from '@material-ui/icons/BugReport'
-import DoneAllIcon from '@material-ui/icons/DoneAll';
+import DoneAllIcon from '@material-ui/icons/DoneAll'
import IconButton from '@material-ui/core/IconButton'
import ListItem from '@material-ui/core/ListItem'
import List from '@material-ui/core/List'
import DashboardOutlinedIcon from '@material-ui/icons/DashboardOutlined'
import { MergeBranchButton, MergeDialog, ErrorDialog } from 'translation-helps-rcl'
import { StoreContext } from '@context/StoreContext'
-import useMergeCardsProps from '../hooks/useMergeCardsProps'
+import useMergeCardsProps from '@hooks/useMergeCardsProps'
// TODO: Enable buttons once ready to fully implement functionality
// import DashboardIcon from '@material-ui/icons/Dashboard'
// import Crop54Icon from '@material-ui/icons/Crop54'
@@ -34,13 +33,22 @@ export default function Drawer({
checkUnsavedChanges,
showFeedback,
}) {
- const router = useRouter()
+ const {
+ state: {
+ mergeStatusForCards,
+ cardsSaving,
+ cardsLoadingMerge,
+ },
+ actions: {
+ setShowAccountSetup,
+ }
+ } = useContext(StoreContext)
async function onSettingsClick() {
const okToContinue = await checkUnsavedChanges()
if (okToContinue) {
- router.push('/settings')
+ setShowAccountSetup(true)
onClose()
}
}
@@ -48,16 +56,8 @@ export default function Drawer({
function onFeedbackClick() {
onClose()
showFeedback && showFeedback()
- }
-
- const {
- state: {
- mergeStatusForCards,
- cardsSaving,
- cardsLoadingMerge,
- },
- } = useContext(StoreContext)
+ }
const mergeButtonProps = useMergeCardsProps({ mergeStatusForCards, isMerging: cardsLoadingMerge?.length });
const {
diff --git a/src/components/ErrorPage.jsx b/src/components/ErrorPage.jsx
new file mode 100644
index 00000000..e8241a07
--- /dev/null
+++ b/src/components/ErrorPage.jsx
@@ -0,0 +1,61 @@
+import { useContext } from 'react'
+import PropTypes from 'prop-types'
+import { StoreContext } from '@context/StoreContext'
+import { HOME_PAGE } from '@common/constants'
+
+export default function ErrorPage({ statusCode }) {
+ const {
+ actions: { setPage },
+ } = useContext(StoreContext)
+
+ if (statusCode) {
+ return {`Error ${statusCode}`}
+ }
+
+ localStorage.clear()
+
+ const handleClick = (e) => {
+ e.preventDefault()
+ setPage(HOME_PAGE)
+ }
+
+ return (
+
+
+
+ An unexpected error has occurred. The application cache has been cleared.
+
+
+
+)
+}
+
+ErrorPage.propTypes = { statusCode: PropTypes.number }
+
+ErrorPage.getInitialProps = ({ res, err }) => {//eslint-disable-next-line
+ const statusCode = res ? res.statusCode : err ? err.statusCode : 404
+ return { statusCode }
+}
diff --git a/src/components/ErrorPopUp.js b/src/components/ErrorPopUp.jsx
similarity index 97%
rename from src/components/ErrorPopUp.js
rename to src/components/ErrorPopUp.jsx
index 56c3e04d..4509e2d9 100644
--- a/src/components/ErrorPopUp.js
+++ b/src/components/ErrorPopUp.jsx
@@ -4,7 +4,7 @@ import Button from '@material-ui/core/Button'
import DraggableCard from 'translation-helps-rcl/dist/components/DraggableCard'
import { CANCEL } from '@common/constants'
-export default function ErrorPopup(
+export default function ErrorPopUp(
{
onClose,
title,
@@ -91,7 +91,7 @@ export default function ErrorPopup(
)
}
-ErrorPopup.defaultProps = {
+ErrorPopUp.defaultProps = {
id: `error_popup`,
actionButtonStr: '',
startIcon: null,
@@ -102,7 +102,7 @@ ErrorPopup.defaultProps = {
dimBackground: true,
}
-ErrorPopup.propTypes = {
+ErrorPopUp.propTypes = {
/** On close event handler */
onClose: PropTypes.func,
/** title Content */
diff --git a/src/components/FeedbackCard.js b/src/components/FeedbackCard.jsx
similarity index 88%
rename from src/components/FeedbackCard.js
rename to src/components/FeedbackCard.jsx
index 04c4e4ff..bb02eac3 100644
--- a/src/components/FeedbackCard.js
+++ b/src/components/FeedbackCard.jsx
@@ -11,11 +11,12 @@ import { getBuildId } from '@utils/build'
import { getLocalStorageItem, getUserKey } from '@hooks/useUserLocalStorage'
import { processNetworkError } from '@utils/network'
import { CLOSE, HTTP_GET_MAX_WAIT_TIME } from '@common/constants'
-import NetworkErrorPopup from '@components/NetworkErrorPopUp'
+import NetworkErrorPopUp from '@components/NetworkErrorPopUp'
import PropTypes from 'prop-types'
import useFeedbackData from '@hooks/useFeedbackData'
+import sendFeedback from '../common/sendFeedback'
-// FeedbackCard.js renders feedback content that is placed in FeedbackPopup
+// FeedbackCard.jsx renders feedback content that is placed in FeedbackPopup
/**
* show message bar with alert
@@ -234,45 +235,21 @@ const FeedbackCard = ({
helpsCardSettings,
})
- let res
-
+ const { name, email, message, category } = state
try {
- const fetchPromise = fetch('/api/feedback', {
- method: 'POST',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify({
- name: state.name,
- email: state.email,
- category: state.category,
- message: state.message,
- extraData,
- }),
- })
- const timeout = new Promise((_r, rej) => {
- const TIMEOUT_ERROR = `Network Timeout Error ${HTTP_GET_MAX_WAIT_TIME}ms`
- return setTimeout(() => rej(TIMEOUT_ERROR), HTTP_GET_MAX_WAIT_TIME)
+ const response = await sendFeedback({
+ name,
+ email,
+ message,
+ category,
+ extraData,
})
- res = await Promise.race([fetchPromise, timeout])
- } catch (e) {
- console.warn(`onSubmitFeedback() - failure calling '/api/feedback'`, e)
- processError(e)
- actions.setSubmitting(false)
- actions.setShowSuccess(false)
- actions.setShowError(true)
- return
- }
-
- const response = await res.json()
- if (res.status === 200) {
- actions.setShowSuccess(true)
- } else {
- const error = response.error
- console.warn(`onSubmitFeedback() - error response = ${JSON.stringify(error)}`)
- const httpCode = parseInt(error.code, 10)
- const errorMessage = error.message + '.'
+ console.log(`onSubmitFeedback() response: ${JSON.stringify(response)}`)
+ } catch (error) {
+ console.warn(`onSubmitFeedback() errorMessage`, error)
+ processError(error)
actions.setShowError(true)
- processError(errorMessage, httpCode)
}
actions.setSubmitting(false)
@@ -372,7 +349,7 @@ const FeedbackCard = ({
{ !!state.networkError &&
- router.push('/')}
+ onClick={() => setPage(HOME_PAGE)}
>
{title}
diff --git a/src/components/Layout.js b/src/components/Layout.jsx
similarity index 61%
rename from src/components/Layout.js
rename to src/components/Layout.jsx
index 2c520024..028b9559 100644
--- a/src/components/Layout.js
+++ b/src/components/Layout.jsx
@@ -6,16 +6,24 @@ import Footer from '@components/Footer'
import Onboarding from '@components/Onboarding'
import { StoreContext } from '@context/StoreContext'
import { getBuildId } from '@utils/build'
-import { APP_NAME, BASE_URL, PROD, QA, QA_BASE_URL } from '@common/constants'
+import {
+ APP_NAME,
+ BASE_URL,
+ HOME_PAGE,
+ PROD,
+ QA,
+ QA_BASE_URL,
+ SETTINGS_PAGE,
+} from '@common/constants'
import useValidateAccountSettings from '@hooks/useValidateAccountSettings'
-import { useRouter } from 'next/router'
+import SettingsPage from '@components/SettingsPage'
+import { reloadPage } from '@utils/pages'
export default function Layout({
children,
showChildren,
title = APP_NAME,
}) {
- const router = useRouter()
const mainScreenRef = useRef(null)
const [feedback, setFeedback_] = useState(null) // contains feedback data
const {
@@ -43,6 +51,7 @@ export default function Layout({
owner,
server,
mergeStatusForCards,
+ page,
},
actions: {
setCurrentLayout,
@@ -57,27 +66,70 @@ export default function Layout({
}, [ mainScreenRef?.current ])
useEffect(() => {
- const params = router?.query
+ if (page?.pageId) {
+ switch (page.pageId) {
+ case HOME_PAGE:
+ reloadPage(page.pageId, page.params)
+ break
- if (typeof params?.server === 'string') { // if URL param given
- let serverID_ = params.server.toUpperCase() === QA ? QA : PROD
+ case SETTINGS_PAGE:
+ showAccountSetup(true)
+ break
+ }
+ }
+ }, [ page ])
+
+ useEffect(() => {
+ const parsedUrl = new URL(window.location.href)
+ const params = parsedUrl.searchParams
+
+ if (params && typeof params.get('server') === 'string') { // if URL param given
+ let serverID_ = params.get('server').toUpperCase() === QA ? QA : PROD
let server_ = (serverID_ === QA) ? QA_BASE_URL : BASE_URL
- if (params.server?.length === 0){
- server_ = (process.env.NEXT_PUBLIC_BUILD_CONTEXT === 'production') ? BASE_URL : QA_BASE_URL
+
+ if (params.get('server')?.length === 0){
+ server_ = (import.meta.env.VITE_PUBLIC_BUILD_CONTEXT === 'production') ? BASE_URL : QA_BASE_URL
serverID_ = (server_ === QA_BASE_URL) ? QA : PROD
}
-
+
if (server !== server_) {
- console.log(`_app.js - On init switching server to: ${serverID_}, url server param '${params.server}', old server ${server}, reloading page`)
+ console.log(
+ `_app.js - On init switching server to: ${serverID_}, url server param '${params.get(
+ 'server',
+ )}', old server ${server}, reloading page`,
+ )
setServer(server_) // persist server selection in localstorage
- router.push(`/?server=${serverID_}`) // reload page
+ reloadPage('/', `server=${serverID_}`)
}
}
- }, [router?.query]) // TRICKY query property not loaded on first pass, so watch for change
+ }, [])
const buildId = useMemo(getBuildId, [])
useValidateAccountSettings(authentication, showAccountSetup, languageId, owner, setShowAccountSetup)
+ /**
+ * determine the page to show based on state
+ * @returns {*|JSX.Element}
+ */
+ function getDisplayPage() {
+ if (showChildren || (authentication && !showAccountSetup)) {
+ return children
+ }
+
+ if (authentication && showAccountSetup) {
+ return (
+
+ )
+ }
+
+ return (
+
+ )
+ }
+
return (
- {showChildren || (authentication && !showAccountSetup) ? (
- children
- ) : (
-
- )}
+ {getDisplayPage()}