Skip to content

Commit

Permalink
User feedback mechanism with login (#790)
Browse files Browse the repository at this point in the history
  • Loading branch information
majakomel authored Mar 8, 2023
1 parent d224928 commit 2e4d5d7
Show file tree
Hide file tree
Showing 38 changed files with 1,957 additions and 304 deletions.
3 changes: 2 additions & 1 deletion .env.development
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
# To override locally, make a copy called `.env.development.local`
# Refer: https://nextjs.org/docs/basic-features/environment-variables

NEXT_PUBLIC_OONI_API=https://ams-pg-test.ooni.org
NEXT_PUBLIC_OONI_API=https://api.ooni.io
NEXT_PUBLIC_USER_FEEDBACK_API=https://ams-pg-test.ooni.org
NEXT_PUBLIC_EXPLORER_URL=http://localhost:3100

RUN_GIT_COMMIT_SHA_SHORT=yarn --silent git:getCommitSHA:short
Expand Down
1 change: 1 addition & 0 deletions .env.production
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@
# Refer: https://nextjs.org/docs/basic-features/environment-variables

NEXT_PUBLIC_OONI_API=https://api.ooni.io
NEXT_PUBLIC_USER_FEEDBACK_API=https://api.ooni.io
NEXT_PUBLIC_SENTRY_DSN=https://[email protected]/1427510
NEXT_PUBLIC_EXPLORER_URL=https://explorer.ooni.org
9 changes: 3 additions & 6 deletions .env.test
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@
# Refer: https://nextjs.org/docs/basic-features/environment-variables

NEXT_PUBLIC_OONI_API=https://api.ooni.io
NEXT_PUBLIC_EXPLORER_URL=https://explorer-test.ooni.io

RUN_GIT_COMMIT_SHA_SHORT=yarn --silent git:getCommitSHA:short
RUN_GIT_COMMIT_SHA=yarn --silent git:getCommitSHA
RUN_GIT_COMMIT_REF=yarn --silent git:getCommitRef
RUN_GIT_COMMIT_TAGS=yarn --silent git:getReleasesAndTags
NEXT_PUBLIC_USER_FEEDBACK_API=https://ams-pg-test.ooni.org
NEXT_PUBLIC_EXPLORER_URL=https://explorer.test.ooni.org
NEXT_PUBLIC_IS_TEST_ENV=1
9 changes: 5 additions & 4 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,19 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v3

- name: Cypress run
uses: cypress-io/github-action@v4.1.0
uses: cypress-io/github-action@v5
with:
build: npm run build
start: npm start
wait-on: 'http://localhost:3100'
browser: chrome
env:
NODE_ENV: 'test'

- name: Upload screenshots on failure
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v3
if: always()
with:
name: cypress-screenshots
Expand Down
6 changes: 3 additions & 3 deletions components/Flag.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ const FlagContainer = styled.div`
border-radius: 50%;
/* padding-left: 3px; */
/* padding-top: 3px; */
width: ${props => props.size + 6}px;
height: ${props => props.size + 6}px;
border: ${props => props.border ? '3px solid white' : 'none'};
width: ${props => props.size + 2}px;
height: ${props => props.size + 2}px;
border: ${props => props.border ? '1px solid white' : 'none'};
`

export const Flag = ({countryCode, size, border}) => {
Expand Down
21 changes: 11 additions & 10 deletions components/Layout.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import Header from './Header'
import Footer from './Footer'
import { useIntl } from 'react-intl'
import { getDirection } from 'components/withIntl'
// import FeedbackButton from '../components/FeedbackFloat'
import { UserProvider } from 'hooks/useUser'

theme.maxWidth = 1024

Expand Down Expand Up @@ -61,22 +61,23 @@ const Layout = ({ children, disableFooter = false }) => {
return (
<MatomoProvider value={matomoInstance}>
<ThemeProvider theme={theme}>
<GlobalStyle direction={getDirection(locale)} />
<div className="site">
<Header />
<div className="content">
{ children }
<UserProvider>
<GlobalStyle direction={getDirection(locale)} />
<div className="site">
<Header />
<div className="content">
{ children }
</div>
{!disableFooter && <Footer />}
</div>
{!disableFooter && <Footer />}
</div>
{/* <FeedbackButton /> */}
</UserProvider>
</ThemeProvider>
</MatomoProvider>
)
}

Layout.propTypes = {
children: PropTypes.array.isRequired,
children: PropTypes.object.isRequired,
disableFooter: PropTypes.bool
}

Expand Down
20 changes: 17 additions & 3 deletions components/NavBar.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,16 @@ import { useRouter, withRouter } from 'next/router'
import NLink from 'next/link'
import styled from 'styled-components'
import { FormattedMessage, useIntl } from 'react-intl'

import { getLocalisedLanguageName } from 'utils/i18nCountries'

import ExplorerLogo from 'ooni-components/components/svgs/logos/Explorer-HorizontalMonochromeInverted.svg'

import {
Link,
Flex,
Box,
Container,
Select,
} from 'ooni-components'
import useUser from 'hooks/useUser'

const StyledNavItem = styled.a`
text-decoration: none;
Expand Down Expand Up @@ -83,11 +81,17 @@ export const NavBar = ({color}) => {
const { locale } = useIntl()
const router = useRouter()
const { pathname, asPath, query } = router
const { user, logout } = useUser()

const handleLocaleChange = (event) => {
router.push({ pathname, query }, asPath, { locale: event.target.value })
}

const logoutUser = (e) => {
e.preventDefault()
logout()
}

return (
<StyledNavBar color={color}>
<Container>
Expand Down Expand Up @@ -116,6 +120,16 @@ export const NavBar = ({color}) => {
))}
</LanguageSelect>
</Box> */}
{user?.logged_in &&
<Box ml={[0, 4]} my={[2, 0]}>
<StyledNavItem>
<NavItemLabel onClick={logoutUser}>
<FormattedMessage id='General.Logout' />
</NavItemLabel>
<Underline />
</StyledNavItem>
</Box>
}
</Flex>
</Box>
</Flex>
Expand Down
107 changes: 107 additions & 0 deletions components/login/LoginForm.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import React, { useState, useCallback, useEffect } from 'react'
import { useForm, Controller } from 'react-hook-form'
import { Flex, Box, Input, Button, Modal, Text, Heading, Container } from 'ooni-components'
import styled from 'styled-components'
import NLink from 'next/link'

import { registerUser } from '/lib/api'
import { useRouter } from 'next/router'
import { FormattedMessage } from 'react-intl'
import SpinLoader from 'components/vendor/SpinLoader'

const StyledError = styled.small`
color: ${props => props.theme.colors.red5};
`

const StyledInputContainer = styled(Box).attrs({
width: '100%',
mt: 3,
})`
position: relative;
& ${StyledError} {
position: absolute;
top: -10px;
right: 0px;
}
`

export const LoginForm = ({ onLogin, redirectTo }) => {
const router = useRouter()
const [submitting, setSubmitting] = useState(false)
const [loginError, setError] = useState(null)

const { handleSubmit, control, formState, reset } = useForm({
mode: 'onTouched',
defaultValues: { email_address: '' }
})

const { errors, isValid, isDirty } = formState

const onSubmit = useCallback((data) => {
const { email_address } = data
const registerApi = async (email_address) => {
try {
await registerUser(email_address, redirectTo)
if (typeof onLogin === 'function') {
onLogin()
}
} catch (e) {
setError(e.message)
// Reset form to mark `isDirty` as false
reset({}, { keepValues: true })
} finally {
setSubmitting(false)
}
}
setSubmitting(true)
registerApi(email_address)
}, [onLogin, reset, redirectTo])

useEffect(() => {
// Remove previous errors when form becomes dirty again
if (isDirty) {
setError(null)
}
}, [isDirty])

return (
<form onSubmit={handleSubmit(onSubmit)}>
<Flex
flexDirection={['column']}
>
<StyledInputContainer>
<Controller
render={({field}) => (
<Input
placeholder='Email *'
{...field}
/>
)}
rules={{
pattern: {
value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i,
},
required: true,
}}
name='email_address'
control={control}
/>
<StyledError>{errors?.email_address?.message}</StyledError>
</StyledInputContainer>
{loginError &&
<Box mt={1}>
<StyledError>{loginError}</StyledError>
</Box>
}
<Box mt={3} alignSelf='center'>
{!submitting ?
<Button disabled={!isValid} type='submit'><FormattedMessage id="General.Login" /></Button> :
<SpinLoader size={3} margin='1px' />
}
</Box>
</Flex>
</form>
)
}

export default LoginForm
2 changes: 1 addition & 1 deletion components/measurement/AccessPointStatus.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ const AccessPointStatus = ({ icon, label, ok, content, color, ...props}) => {
}

AccessPointStatus.propTypes = {
icon: PropTypes.element.isRequired,
icon: PropTypes.element,
label: PropTypes.oneOfType([
PropTypes.string,
PropTypes.element
Expand Down
12 changes: 11 additions & 1 deletion components/measurement/CommonDetails.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ JsonViewer.propTypes = {

const CommonDetails = ({
measurement,
reportId
reportId,
userFeedbackItems =[]
}) => {
const {
software_name,
Expand Down Expand Up @@ -143,6 +144,15 @@ const CommonDetails = ({
bg={theme.colors.gray2}
/>
</Flex>
{/* User Feedback */}
{!!userFeedbackItems.length &&
<Flex my={4}>
<DetailsBoxTable
title={<FormattedMessage id='Measurement.CommonDetails.Label.UserFeedback' />}
items={userFeedbackItems}
/>
</Flex>
}
{/* Raw Measurement */}
<Flex>
<DetailsBox
Expand Down
Loading

1 comment on commit 2e4d5d7

@vercel
Copy link

@vercel vercel bot commented on 2e4d5d7 Mar 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

explorer – ./

explorer-one.vercel.app
explorer-ooni1.vercel.app
explorer-git-master-ooni1.vercel.app

Please sign in to comment.