Attempt to at move app into app sub dir
This commit is contained in:
67
app/web/src/pages/AccountRecoveryPage/AccountRecoveryPage.js
Normal file
67
app/web/src/pages/AccountRecoveryPage/AccountRecoveryPage.js
Normal file
@@ -0,0 +1,67 @@
|
||||
import { routes, navigate } from '@redwoodjs/router'
|
||||
import { useAuth } from '@redwoodjs/auth'
|
||||
import { Form, Submit } from '@redwoodjs/forms'
|
||||
import { useFlash } from '@redwoodjs/web'
|
||||
|
||||
import InputTextForm from 'src/components/InputTextForm'
|
||||
import MainLayout from 'src/layouts/MainLayout'
|
||||
import Seo from 'src/components/Seo/Seo'
|
||||
|
||||
const AccountRecoveryPage = () => {
|
||||
const { addMessage } = useFlash()
|
||||
const { client } = useAuth()
|
||||
const onSubmit = ({ email }) => {
|
||||
client
|
||||
.requestPasswordRecovery(email)
|
||||
.then(() => {
|
||||
addMessage('Email sent', { classes: 'rw-flash-success' })
|
||||
setTimeout(() => {
|
||||
navigate(routes.home())
|
||||
}, 500)
|
||||
})
|
||||
.catch(() => {
|
||||
addMessage('Problem sending email', {
|
||||
classes: 'bg-red-300 text-red-900',
|
||||
})
|
||||
})
|
||||
}
|
||||
return (
|
||||
<MainLayout>
|
||||
<Seo
|
||||
title="Account recovery"
|
||||
description="Send recovery email"
|
||||
lang="en-US"
|
||||
/>
|
||||
|
||||
<section className="max-w-md mx-auto mt-20">
|
||||
<h2 className="text-xl text-indigo-500 pb-4">Send recovery email</h2>
|
||||
<Form onSubmit={onSubmit}>
|
||||
<div
|
||||
className="grid items-center gap-2"
|
||||
style={{ gridTemplateColumns: 'auto 1fr' }}
|
||||
>
|
||||
<span className="capitalize text-gray-500 text-sm align-middle my-3">
|
||||
email:
|
||||
</span>
|
||||
<InputTextForm
|
||||
className="text-xl"
|
||||
name="email"
|
||||
validation={{
|
||||
required: true,
|
||||
pattern: {
|
||||
value: /[^@]+@[^.]+\..+/,
|
||||
message: 'please enter a valid email address',
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<Submit className="bg-indigo-200 text-indigo-800 p-2 px-4 shadow hover:shadow-lg mt-4 rounded">
|
||||
Send email
|
||||
</Submit>
|
||||
</Form>
|
||||
</section>
|
||||
</MainLayout>
|
||||
)
|
||||
}
|
||||
|
||||
export default AccountRecoveryPage
|
||||
@@ -0,0 +1,7 @@
|
||||
import AccountRecoveryPage from './AccountRecoveryPage'
|
||||
|
||||
export const generated = () => {
|
||||
return <AccountRecoveryPage />
|
||||
}
|
||||
|
||||
export default { title: 'Pages/AccountRecoveryPage' }
|
||||
@@ -0,0 +1,11 @@
|
||||
import { render } from '@redwoodjs/testing'
|
||||
|
||||
import AccountRecoveryPage from './AccountRecoveryPage'
|
||||
|
||||
describe('AccountRecoveryPage', () => {
|
||||
it('renders successfully', () => {
|
||||
expect(() => {
|
||||
render(<AccountRecoveryPage />)
|
||||
}).not.toThrow()
|
||||
})
|
||||
})
|
||||
12
app/web/src/pages/AdminPartsPage/AdminPartsPage.js
Normal file
12
app/web/src/pages/AdminPartsPage/AdminPartsPage.js
Normal file
@@ -0,0 +1,12 @@
|
||||
import MainLayout from 'src/layouts/MainLayout'
|
||||
import AdminPartsCell from 'src/components/AdminPartsCell'
|
||||
|
||||
const PartsPage = () => {
|
||||
return (
|
||||
<MainLayout>
|
||||
<AdminPartsCell />
|
||||
</MainLayout>
|
||||
)
|
||||
}
|
||||
|
||||
export default PartsPage
|
||||
198
app/web/src/pages/CodeOfConductPage/CodeOfConductPage.js
Normal file
198
app/web/src/pages/CodeOfConductPage/CodeOfConductPage.js
Normal file
@@ -0,0 +1,198 @@
|
||||
import MainLayout from 'src/layouts/MainLayout'
|
||||
import Seo from 'src/components/Seo/Seo'
|
||||
import OutBound from 'src/components/OutBound'
|
||||
import { Link, routes } from '@redwoodjs/router'
|
||||
|
||||
const Li = ({ children }) => (
|
||||
<li className="pb-2 font-roboto text-lg text-gray-800">{children}</li>
|
||||
)
|
||||
|
||||
const P = ({ children }) => <p className="py-2">{children}</p>
|
||||
|
||||
const CodeOfConductPage = () => {
|
||||
return (
|
||||
<MainLayout>
|
||||
<Seo
|
||||
title={'Code Of Conduct'}
|
||||
description="Outlines CadHub's policy in regards to Code of Conduct"
|
||||
lang="en-US"
|
||||
/>
|
||||
<div className="max-w-5xl mx-auto mt-20">
|
||||
<h1 className="text-3xl">Code of Conduct</h1>
|
||||
<h2 className="text-2xl font-ropa-sans py-4">What's Required</h2>
|
||||
<ul className="list-disc pl-4">
|
||||
<Li>
|
||||
We are committed to providing a friendly, safe and welcoming
|
||||
environment for all, regardless of any morally irrelevant attributes
|
||||
(level of experience, gender identity and expression, sexual
|
||||
orientation, disability, personal appearance, body size, race,
|
||||
ethnicity, age, religion, nationality, or other similar
|
||||
characteristic).
|
||||
</Li>
|
||||
<Li>
|
||||
Please avoid using overtly sexual parts, title, usernames or other
|
||||
user-creatable content that might detract from a friendly, safe and
|
||||
welcoming environment for all.
|
||||
</Li>
|
||||
<Li>
|
||||
Please be kind and courteous. There’s no need to be mean or rude.
|
||||
</Li>
|
||||
<Li>
|
||||
Respect that people have differences of opinion and that every
|
||||
design or implementation choice carries a trade-off and numerous
|
||||
costs. There is seldom a right answer.
|
||||
</Li>
|
||||
<Li>Please keep unstructured critique to a minimum.</Li>
|
||||
<Li>
|
||||
We will exclude you from interaction if you insult, demean or harass
|
||||
anyone. That is not welcome behavior. We interpret the term
|
||||
“harassment” as including the definition in the{' '}
|
||||
<OutBound
|
||||
className="text-gray-600 underline"
|
||||
to="https://github.com/stumpsyn/policies/blob/master/citizen_code_of_conduct.md"
|
||||
>
|
||||
Citizen Code of Conduct
|
||||
</OutBound>
|
||||
; if you have any lack of clarity about what might be included in
|
||||
that concept, please read their definition.
|
||||
</Li>
|
||||
<Li>
|
||||
Private harassment is also unacceptable. No matter who you are, if
|
||||
you feel you have been or are being harassed or made uncomfortable
|
||||
by a community member, please contact the{' '}
|
||||
<a
|
||||
className="text-gray-600 underline"
|
||||
href="mailto:moderation@kurthutten.com"
|
||||
>
|
||||
CadHub moderation team
|
||||
</a>{' '}
|
||||
immediately. We care about making this community a safe place for
|
||||
you and we’ve got your back.
|
||||
</Li>
|
||||
<Li>
|
||||
Likewise any spamming, trolling, flaming, baiting or other
|
||||
attention-stealing behavior is not welcome.
|
||||
</Li>
|
||||
</ul>
|
||||
|
||||
<h2 className="text-2xl font-ropa-sans py-4">Moderation</h2>
|
||||
<div className="font-roboto text-lg text-gray-800">
|
||||
<P>
|
||||
These are the policies for upholding our community’s standards of
|
||||
conduct.
|
||||
</P>
|
||||
<ol className="list-decimal pl-6">
|
||||
<Li>
|
||||
Remarks that violate the CadHub standards of conduct, including
|
||||
hateful, hurtful, oppressive, or exclusionary remarks, are not
|
||||
allowed. (Cursing is allowed, but never targeting another user,
|
||||
and never in a hateful manner.)
|
||||
</Li>
|
||||
<Li>
|
||||
Remarks that moderators find inappropriate, whether listed in the
|
||||
code of conduct or not, are also not allowed.
|
||||
</Li>
|
||||
<Li>
|
||||
Moderators will first respond to such remarks with a warning.
|
||||
</Li>
|
||||
<Li>
|
||||
If the warning is unheeded, the user will be “kicked,” i.e.,
|
||||
kicked out of the communication channel to cool off.
|
||||
</Li>
|
||||
<Li>
|
||||
If the user comes back and continues to make trouble, they will be
|
||||
banned, i.e., indefinitely excluded.
|
||||
</Li>
|
||||
<Li>
|
||||
Moderators may choose at their discretion to un-ban the user if it
|
||||
was a first offense and they offer the offended party a genuine
|
||||
apology.
|
||||
</Li>
|
||||
<Li>
|
||||
If a moderator bans someone and you think it was unjustified,
|
||||
please take it up with that moderator, or with a different
|
||||
moderator, <strong>in private</strong>. Complaints about bans
|
||||
in-channel are not allowed.
|
||||
</Li>
|
||||
<Li>
|
||||
Moderators are held to a higher standard than other community
|
||||
members. If a moderator creates an inappropriate situation, they
|
||||
should expect less leeway than others.
|
||||
</Li>
|
||||
</ol>
|
||||
<P>
|
||||
In the CadHub community we strive to go the extra step to look out
|
||||
for each other. Don’t just aim to be technically unimpeachable, try
|
||||
to be your best self. In particular, avoid flirting with offensive
|
||||
or sensitive issues, particularly if they’re off-topic; this all too
|
||||
often leads to unnecessary fights, hurt feelings, and damaged trust;
|
||||
worse, it can drive people away from the community entirely.
|
||||
</P>
|
||||
<P>
|
||||
And if someone takes issue with something you said or did, resist
|
||||
the urge to be defensive. Just stop doing what it was they
|
||||
complained about and apologize. Even if you feel you were
|
||||
misinterpreted or unfairly accused, chances are good there was
|
||||
something you could’ve communicated better. Everyone wants to get
|
||||
along and we are all here first and foremost because we want to talk
|
||||
about cool technology. You will find that people will be eager to
|
||||
assume good intent and forgive as long as you earn their trust.
|
||||
</P>
|
||||
<P>
|
||||
The enforcement policies listed above apply to all official CadHub
|
||||
venues; including{' '}
|
||||
<OutBound
|
||||
className="text-gray-600 underline"
|
||||
to="https://discord.gg/SD7zFRNjGH"
|
||||
>
|
||||
Discord channels
|
||||
</OutBound>
|
||||
,{' '}
|
||||
<OutBound
|
||||
className="text-gray-600 underline"
|
||||
to="https://github.com/Irev-Dev/cadhub"
|
||||
>
|
||||
GitHub
|
||||
</OutBound>{' '}
|
||||
and{' '}
|
||||
<Link className="text-gray-600 underline" to={routes.home()}>
|
||||
CadHub
|
||||
</Link>
|
||||
. Please contact the maintainers of those projects for enforcement.
|
||||
If you wish to use this code of conduct for your own project,
|
||||
consider explicitly mentioning your moderation policy or making a
|
||||
copy with your own moderation policy so as to avoid confusion.
|
||||
</P>
|
||||
<P>
|
||||
<i>
|
||||
Adapted from{' '}
|
||||
<OutBound
|
||||
className="text-gray-600 underline"
|
||||
to="http://blog.izs.me/post/30036893703/policy-on-trolling"
|
||||
>
|
||||
Node.js Policy on Trolling
|
||||
</OutBound>
|
||||
,{' '}
|
||||
<OutBound
|
||||
className="text-gray-600 underline"
|
||||
to="https://www.contributor-covenant.org/version/1/3/0/"
|
||||
>
|
||||
Contributor Covenant v1.3.0
|
||||
</OutBound>{' '}
|
||||
and{' '}
|
||||
<OutBound
|
||||
className="text-gray-600 underline"
|
||||
to="https://www.rust-lang.org/policies/code-of-conduct"
|
||||
>
|
||||
Rust Code of Conduct
|
||||
</OutBound>
|
||||
.
|
||||
</i>
|
||||
</P>
|
||||
</div>
|
||||
</div>
|
||||
</MainLayout>
|
||||
)
|
||||
}
|
||||
|
||||
export default CodeOfConductPage
|
||||
@@ -0,0 +1,7 @@
|
||||
import CodeOfConductPage from './CodeOfConductPage'
|
||||
|
||||
export const generated = () => {
|
||||
return <CodeOfConductPage />
|
||||
}
|
||||
|
||||
export default { title: 'Pages/CodeOfConductPage' }
|
||||
@@ -0,0 +1,11 @@
|
||||
import { render } from '@redwoodjs/testing'
|
||||
|
||||
import CodeOfConductPage from './CodeOfConductPage'
|
||||
|
||||
describe('CodeOfConductPage', () => {
|
||||
it('renders successfully', () => {
|
||||
expect(() => {
|
||||
render(<CodeOfConductPage />)
|
||||
}).not.toThrow()
|
||||
})
|
||||
})
|
||||
35
app/web/src/pages/DevIdePage/DevIdePage.js
Normal file
35
app/web/src/pages/DevIdePage/DevIdePage.js
Normal file
@@ -0,0 +1,35 @@
|
||||
import MainLayout from 'src/layouts/MainLayout'
|
||||
import Seo from 'src/components/Seo/Seo'
|
||||
import IdeToolbar from 'src/components/IdeToolbarNew'
|
||||
import OutBound from 'src/components/OutBound'
|
||||
|
||||
const DevIdePage = ({ cadPackage }) => {
|
||||
return (
|
||||
<div className="h-screen flex flex-col">
|
||||
<MainLayout shouldRemoveFooterInIde>
|
||||
<Seo
|
||||
title="new ide in development"
|
||||
description="new ide in development"
|
||||
lang="en-US"
|
||||
/>
|
||||
<div className="py-2 bg-pink-200">
|
||||
<div className="mx-auto max-w-3xl">
|
||||
We're still working on this. Since you're here, have a look what{' '}
|
||||
<OutBound
|
||||
className="text-pink-700"
|
||||
to="https://github.com/Irev-Dev/cadhub/discussions/212"
|
||||
>
|
||||
we've got planned
|
||||
</OutBound>
|
||||
.
|
||||
</div>
|
||||
</div>
|
||||
</MainLayout>
|
||||
<div className="flex-auto">
|
||||
<IdeToolbar cadPackage={cadPackage} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default DevIdePage
|
||||
18
app/web/src/pages/DraftPartPage/DraftPartPage.js
Normal file
18
app/web/src/pages/DraftPartPage/DraftPartPage.js
Normal file
@@ -0,0 +1,18 @@
|
||||
import MainLayout from 'src/layouts/MainLayout'
|
||||
import IdeCascadeStudio from 'src/components/IdeCascadeStudio'
|
||||
import Seo from 'src/components/Seo/Seo'
|
||||
|
||||
const DraftPartPage = () => {
|
||||
return (
|
||||
<MainLayout shouldRemoveFooterInIde>
|
||||
<Seo
|
||||
title="draft part"
|
||||
description="black slate to hack on a new part"
|
||||
lang="en-US"
|
||||
/>
|
||||
<IdeCascadeStudio />
|
||||
</MainLayout>
|
||||
)
|
||||
}
|
||||
|
||||
export default DraftPartPage
|
||||
7
app/web/src/pages/DraftPartPage/DraftPartPage.stories.js
Normal file
7
app/web/src/pages/DraftPartPage/DraftPartPage.stories.js
Normal file
@@ -0,0 +1,7 @@
|
||||
import DraftPartPage from './DraftPartPage'
|
||||
|
||||
export const generated = () => {
|
||||
return <DraftPartPage />
|
||||
}
|
||||
|
||||
export default { title: 'Pages/DraftPartPage' }
|
||||
11
app/web/src/pages/DraftPartPage/DraftPartPage.test.js
Normal file
11
app/web/src/pages/DraftPartPage/DraftPartPage.test.js
Normal file
@@ -0,0 +1,11 @@
|
||||
import { render } from '@redwoodjs/testing'
|
||||
|
||||
import DraftPartPage from './DraftPartPage'
|
||||
|
||||
describe('DraftPartPage', () => {
|
||||
it('renders successfully', () => {
|
||||
expect(() => {
|
||||
render(<DraftPartPage />)
|
||||
}).not.toThrow()
|
||||
})
|
||||
})
|
||||
23
app/web/src/pages/EditPartPage/EditPartPage.js
Normal file
23
app/web/src/pages/EditPartPage/EditPartPage.js
Normal file
@@ -0,0 +1,23 @@
|
||||
import { useAuth } from '@redwoodjs/auth'
|
||||
|
||||
import MainLayout from 'src/layouts/MainLayout'
|
||||
import PartCell from 'src/components/PartCell'
|
||||
import Seo from 'src/components/Seo/Seo'
|
||||
|
||||
const EditPartPage = ({ userName, partTitle }) => {
|
||||
const { currentUser } = useAuth()
|
||||
return (
|
||||
<MainLayout>
|
||||
<Seo title={partTitle} description="Edit part page" lang="en-US" />
|
||||
|
||||
<PartCell
|
||||
userName={userName}
|
||||
partTitle={partTitle}
|
||||
currentUserId={currentUser?.sub}
|
||||
isEditable
|
||||
/>
|
||||
</MainLayout>
|
||||
)
|
||||
}
|
||||
|
||||
export default EditPartPage
|
||||
7
app/web/src/pages/EditPartPage/EditPartPage.stories.js
Normal file
7
app/web/src/pages/EditPartPage/EditPartPage.stories.js
Normal file
@@ -0,0 +1,7 @@
|
||||
import EditPartPage from './EditPartPage'
|
||||
|
||||
export const generated = () => {
|
||||
return <EditPartPage />
|
||||
}
|
||||
|
||||
export default { title: 'Pages/EditPartPage' }
|
||||
11
app/web/src/pages/EditPartPage/EditPartPage.test.js
Normal file
11
app/web/src/pages/EditPartPage/EditPartPage.test.js
Normal file
@@ -0,0 +1,11 @@
|
||||
import { render } from '@redwoodjs/testing'
|
||||
|
||||
import EditPartPage from './EditPartPage'
|
||||
|
||||
describe('EditPartPage', () => {
|
||||
it('renders successfully', () => {
|
||||
expect(() => {
|
||||
render(<EditPartPage />)
|
||||
}).not.toThrow()
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,12 @@
|
||||
import SubjectAccessRequestsLayout from 'src/layouts/SubjectAccessRequestsLayout'
|
||||
import EditSubjectAccessRequestCell from 'src/components/EditSubjectAccessRequestCell'
|
||||
|
||||
const EditSubjectAccessRequestPage = ({ id }) => {
|
||||
return (
|
||||
<SubjectAccessRequestsLayout>
|
||||
<EditSubjectAccessRequestCell id={id} />
|
||||
</SubjectAccessRequestsLayout>
|
||||
)
|
||||
}
|
||||
|
||||
export default EditSubjectAccessRequestPage
|
||||
15
app/web/src/pages/EditUserPage/EditUserPage.js
Normal file
15
app/web/src/pages/EditUserPage/EditUserPage.js
Normal file
@@ -0,0 +1,15 @@
|
||||
import MainLayout from 'src/layouts/MainLayout'
|
||||
import EditUserCell from 'src/components/EditUserCell'
|
||||
import Seo from 'src/components/Seo/Seo'
|
||||
|
||||
const UserPage = ({ userName }) => {
|
||||
return (
|
||||
<MainLayout>
|
||||
<Seo title={userName} description="Add new part page" lang="en-US" />
|
||||
|
||||
<EditUserCell userName={userName} isEditable />
|
||||
</MainLayout>
|
||||
)
|
||||
}
|
||||
|
||||
export default UserPage
|
||||
56
app/web/src/pages/FatalErrorPage/FatalErrorPage.js
Normal file
56
app/web/src/pages/FatalErrorPage/FatalErrorPage.js
Normal file
@@ -0,0 +1,56 @@
|
||||
// This page will be rendered when an error makes it all the way to the top of the
|
||||
// application without being handled by a Javascript catch statement or React error
|
||||
// boundary.
|
||||
//
|
||||
// You can modify this page as you wish, but it is important to keep things simple to
|
||||
// avoid the possibility that it will cause its own error. If it does, Redwood will
|
||||
// still render a generic error page, but your users will prefer something a bit more
|
||||
// thoughtful. =)
|
||||
import Seo from 'src/components/Seo/Seo'
|
||||
|
||||
export default () => (
|
||||
<main>
|
||||
<Seo title="Fatal error" description="Fatal error" lang="en-US" />
|
||||
|
||||
<style
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: `
|
||||
html, body {
|
||||
margin: 0;
|
||||
}
|
||||
html * {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
main {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif;
|
||||
text-align: center;
|
||||
background-color: #E2E8F0;
|
||||
height: 100vh;
|
||||
}
|
||||
section {
|
||||
background-color: white;
|
||||
border-radius: 0.25rem;
|
||||
width: 32rem;
|
||||
padding: 1rem;
|
||||
margin: 0 auto;
|
||||
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
h1 {
|
||||
font-size: 2rem;
|
||||
margin: 0;
|
||||
font-weight: 500;
|
||||
line-height: 1;
|
||||
color: #2D3748;
|
||||
}
|
||||
`,
|
||||
}}
|
||||
/>
|
||||
<section>
|
||||
<h1>
|
||||
<span>Something went wrong</span>
|
||||
</h1>
|
||||
</section>
|
||||
</main>
|
||||
)
|
||||
16
app/web/src/pages/HomePage/HomePage.js
Normal file
16
app/web/src/pages/HomePage/HomePage.js
Normal file
@@ -0,0 +1,16 @@
|
||||
import MainLayout from 'src/layouts/MainLayout'
|
||||
import PartsCell from 'src/components/PartsCell'
|
||||
import LandingSection from 'src/components/LandingSection'
|
||||
import Seo from 'src/components/Seo/Seo'
|
||||
|
||||
const PartsPage = () => {
|
||||
return (
|
||||
<MainLayout>
|
||||
<Seo title="Parts page" description="Cadhub parts page" lang="en-US" />
|
||||
<LandingSection />
|
||||
<PartsCell shouldFilterPartsWithoutImage />
|
||||
</MainLayout>
|
||||
)
|
||||
}
|
||||
|
||||
export default PartsPage
|
||||
15
app/web/src/pages/IdePartPage/IdePartPage.js
Normal file
15
app/web/src/pages/IdePartPage/IdePartPage.js
Normal file
@@ -0,0 +1,15 @@
|
||||
import MainLayout from 'src/layouts/MainLayout'
|
||||
import IdePartCell from 'src/components/IdePartCell'
|
||||
import Seo from 'src/components/Seo/Seo'
|
||||
|
||||
const IdePartPage = ({ userName, partTitle }) => {
|
||||
return (
|
||||
<MainLayout shouldRemoveFooterInIde>
|
||||
<Seo title={partTitle} description={partTitle} lang="en-US" />
|
||||
|
||||
<IdePartCell userName={userName} partTitle={partTitle} />
|
||||
</MainLayout>
|
||||
)
|
||||
}
|
||||
|
||||
export default IdePartPage
|
||||
11
app/web/src/pages/IdePartPage/IdePartPage.test.js
Normal file
11
app/web/src/pages/IdePartPage/IdePartPage.test.js
Normal file
@@ -0,0 +1,11 @@
|
||||
import { render } from '@redwoodjs/testing'
|
||||
|
||||
import IdePartPage from './IdePartPage'
|
||||
|
||||
describe('IdePartPage', () => {
|
||||
it('renders successfully', () => {
|
||||
expect(() => {
|
||||
render(<IdePartPage />)
|
||||
}).not.toThrow()
|
||||
})
|
||||
})
|
||||
27
app/web/src/pages/NewPartPage/NewPartPage.js
Normal file
27
app/web/src/pages/NewPartPage/NewPartPage.js
Normal file
@@ -0,0 +1,27 @@
|
||||
import { useEffect } from 'react'
|
||||
import { useAuth } from '@redwoodjs/auth'
|
||||
import { navigate, routes } from '@redwoodjs/router'
|
||||
|
||||
import MainLayout from 'src/layouts/MainLayout'
|
||||
import PartCell from 'src/components/PartCell'
|
||||
import Seo from 'src/components/Seo/Seo'
|
||||
|
||||
const NewPartPage = ({ userName }) => {
|
||||
const { isAuthenticated, currentUser } = useAuth()
|
||||
useEffect(() => {
|
||||
!isAuthenticated && navigate(routes.home())
|
||||
}, [currentUser])
|
||||
return (
|
||||
<MainLayout>
|
||||
<Seo title="New part" description="Add new part page" lang="en-US" />
|
||||
|
||||
<PartCell
|
||||
userName={userName}
|
||||
currentUserId={currentUser?.sub}
|
||||
isEditable
|
||||
/>
|
||||
</MainLayout>
|
||||
)
|
||||
}
|
||||
|
||||
export default NewPartPage
|
||||
7
app/web/src/pages/NewPartPage/NewPartPage.stories.js
Normal file
7
app/web/src/pages/NewPartPage/NewPartPage.stories.js
Normal file
@@ -0,0 +1,7 @@
|
||||
import NewPartPage from './NewPartPage'
|
||||
|
||||
export const generated = () => {
|
||||
return <NewPartPage />
|
||||
}
|
||||
|
||||
export default { title: 'Pages/NewPartPage' }
|
||||
11
app/web/src/pages/NewPartPage/NewPartPage.test.js
Normal file
11
app/web/src/pages/NewPartPage/NewPartPage.test.js
Normal file
@@ -0,0 +1,11 @@
|
||||
import { render } from '@redwoodjs/testing'
|
||||
|
||||
import NewPartPage from './NewPartPage'
|
||||
|
||||
describe('NewPartPage', () => {
|
||||
it('renders successfully', () => {
|
||||
expect(() => {
|
||||
render(<NewPartPage />)
|
||||
}).not.toThrow()
|
||||
})
|
||||
})
|
||||
49
app/web/src/pages/NotFoundPage/NotFoundPage.js
Normal file
49
app/web/src/pages/NotFoundPage/NotFoundPage.js
Normal file
@@ -0,0 +1,49 @@
|
||||
import MainLayout from 'src/layouts/MainLayout'
|
||||
import Seo from 'src/components/Seo/Seo'
|
||||
|
||||
export default () => (
|
||||
<MainLayout>
|
||||
<Seo title="Page not found" description="404 page not found" lang="en-US" />
|
||||
|
||||
<style
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: `
|
||||
html, body {
|
||||
margin: 0;
|
||||
}
|
||||
html * {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
main {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif;
|
||||
text-align: center;
|
||||
background-color: #E2E8F0;
|
||||
height: 100vh;
|
||||
}
|
||||
section {
|
||||
background-color: white;
|
||||
border-radius: 0.25rem;
|
||||
width: 32rem;
|
||||
padding: 1rem;
|
||||
margin: 0 auto;
|
||||
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
h1 {
|
||||
font-size: 2rem;
|
||||
margin: 0;
|
||||
font-weight: 500;
|
||||
line-height: 1;
|
||||
color: #2D3748;
|
||||
}
|
||||
`,
|
||||
}}
|
||||
/>
|
||||
<section className="">
|
||||
<h1>
|
||||
<span className="font-ropa-sans">404 Page Not Found</span>
|
||||
</h1>
|
||||
</section>
|
||||
</MainLayout>
|
||||
)
|
||||
22
app/web/src/pages/PartPage/PartPage.js
Normal file
22
app/web/src/pages/PartPage/PartPage.js
Normal file
@@ -0,0 +1,22 @@
|
||||
import { useAuth } from '@redwoodjs/auth'
|
||||
|
||||
import MainLayout from 'src/layouts/MainLayout'
|
||||
import PartCell from 'src/components/PartCell'
|
||||
import Seo from 'src/components/Seo/Seo'
|
||||
|
||||
const PartPage = ({ userName, partTitle }) => {
|
||||
const { currentUser } = useAuth()
|
||||
return (
|
||||
<MainLayout>
|
||||
<Seo title={partTitle} description={partTitle} lang="en-US" />
|
||||
|
||||
<PartCell
|
||||
userName={userName}
|
||||
partTitle={partTitle}
|
||||
currentUserId={currentUser?.sub}
|
||||
/>
|
||||
</MainLayout>
|
||||
)
|
||||
}
|
||||
|
||||
export default PartPage
|
||||
7
app/web/src/pages/PartPage/PartPage.stories.js
Normal file
7
app/web/src/pages/PartPage/PartPage.stories.js
Normal file
@@ -0,0 +1,7 @@
|
||||
import PartPage from './PartPage'
|
||||
|
||||
export const generated = () => {
|
||||
return <PartPage />
|
||||
}
|
||||
|
||||
export default { title: 'Pages/PartPage' }
|
||||
11
app/web/src/pages/PartPage/PartPage.test.js
Normal file
11
app/web/src/pages/PartPage/PartPage.test.js
Normal file
@@ -0,0 +1,11 @@
|
||||
import { render } from '@redwoodjs/testing'
|
||||
|
||||
import PartPage from './PartPage'
|
||||
|
||||
describe('PartPage', () => {
|
||||
it('renders successfully', () => {
|
||||
expect(() => {
|
||||
render(<PartPage />)
|
||||
}).not.toThrow()
|
||||
})
|
||||
})
|
||||
153
app/web/src/pages/PrivacyPolicyPage/PrivacyPolicyPage.js
Normal file
153
app/web/src/pages/PrivacyPolicyPage/PrivacyPolicyPage.js
Normal file
@@ -0,0 +1,153 @@
|
||||
import MainLayout from 'src/layouts/MainLayout'
|
||||
import Seo from 'src/components/Seo/Seo'
|
||||
import OutBound from 'src/components/OutBound'
|
||||
|
||||
const Li = ({ children }) => (
|
||||
<li className="pb-2 font-roboto text-lg text-gray-800">{children}</li>
|
||||
)
|
||||
|
||||
const P = ({ children }) => <p className="py-2">{children}</p>
|
||||
|
||||
const A = ({ to }) => <OutBound to={to}>{to}</OutBound>
|
||||
|
||||
const SubHeading = ({ children }) => <h3>{children}</h3>
|
||||
|
||||
const PrivacyPolicyPage = () => {
|
||||
return (
|
||||
<MainLayout>
|
||||
<Seo
|
||||
title={'Privacy Policy'}
|
||||
description="Outlines CadHub's policy in regards to User's right to privacy"
|
||||
lang="en-US"
|
||||
/>
|
||||
<div className="max-w-5xl mx-auto mt-20">
|
||||
<h1 className="text-3xl">CadHub Privacy Policy</h1>
|
||||
<P>
|
||||
This Privacy Policy describes how your personal information is
|
||||
collected, used, and shared when you visit or use{' '}
|
||||
<A to="https://cadhub.xyz" /> (the “Site”).
|
||||
</P>
|
||||
<SubHeading>PERSONAL INFORMATION WE COLLECT</SubHeading>
|
||||
<P>
|
||||
When you visit the Site, we automatically collect certain information
|
||||
about your device, including information about your web browser, IP
|
||||
address, time zone, and some of the cookies that are installed on your
|
||||
device. Additionally, as you browse the Site, we collect information
|
||||
about the individual web pages that you view, what websites or search
|
||||
terms referred you to the Site, and information about how you interact
|
||||
with the Site. We refer to this automatically-collected information as
|
||||
“Device Information.”
|
||||
</P>
|
||||
<P>We collect Device Information using the following technologies:</P>
|
||||
<ul className="list-disc pl-4">
|
||||
<Li>
|
||||
“Cookies” are data files that are placed on your device or computer
|
||||
and often include an anonymous unique identifier. For more
|
||||
information about cookies, and how to disable cookies, visit
|
||||
<A to="http://www.allaboutcookies.org" />.
|
||||
</Li>
|
||||
<Li>
|
||||
“Log files” track actions occurring on the Site, and collect data
|
||||
including your IP address, browser type, Internet service provider,
|
||||
referring/exit pages, and date/time stamps.
|
||||
</Li>
|
||||
<Li>
|
||||
“Web beacons,” “tags,” and “pixels” are electronic files used to
|
||||
record information about how you browse the Site.
|
||||
</Li>
|
||||
</ul>
|
||||
<P>
|
||||
Additionally when you make an account or sign in to the app through
|
||||
the Site, we collect certain information from you, including your
|
||||
name, email address as well as any information you add to the website,
|
||||
such as your profile bio, or "parts" you have added. We refer to this
|
||||
information as “Account Information.”
|
||||
</P>
|
||||
<P>
|
||||
When we talk about “Personal Information” in this Privacy Policy, we
|
||||
are talking both about Device Information and Account Information.
|
||||
</P>
|
||||
<SubHeading>HOW DO WE USE YOUR PERSONAL INFORMATION?</SubHeading>
|
||||
<P>
|
||||
We use the Account Information that we collect generally to link you
|
||||
to your account and the content you create through CadHub.xyz.
|
||||
Additionally, we use this Account Information to communicate with you.
|
||||
We use the Device Information that we collect to help us screen for
|
||||
potential risk (in particular, your IP address), and more generally to
|
||||
improve and optimize our Site (for example, by generating analytics
|
||||
about how our customers browse and interact with the Site, and to
|
||||
assess the success of our marketing and advertising campaigns).
|
||||
</P>
|
||||
<SubHeading>SHARING YOUR PERSONAL INFORMATION</SubHeading>
|
||||
<P>
|
||||
We share your Personal Information with third parties to help us use
|
||||
your Personal Information, as described above. For example, we use
|
||||
Netlify's idenity service to handle user logins and authentication --
|
||||
you can read more about how Netlify uses your Personal Information
|
||||
here: <A to="https://www.netlify.com/privacy/" /> --{' '}
|
||||
<A to="https://www.netlify.com/gdpr-ccpa" />. We also use Google
|
||||
Analytics to help us understand how our customers use the Site -- you
|
||||
can read more about how Google uses your Personal Information here:{' '}
|
||||
<A to="https://www.google.com/intl/en/policies/privacy/" />. You can
|
||||
also opt-out of Google Analytics here:{' '}
|
||||
<A to="https://tools.google.com/dlpage/gaoptout" />. We also use
|
||||
MailChimp to send newsletters, You can read more about how MailChip
|
||||
uses your Personal Information here:{' '}
|
||||
<A to="https://mailchimp.com/legal/privacy/" />.
|
||||
</P>
|
||||
<P>
|
||||
Finally, we may also share your Personal Information to comply with
|
||||
applicable laws and regulations, to respond to a subpoena, search
|
||||
warrant or other lawful request for information we receive, or to
|
||||
otherwise protect our rights.
|
||||
</P>
|
||||
|
||||
<SubHeading>DO NOT TRACK</SubHeading>
|
||||
<P>
|
||||
Please note that we do not alter our Site’s data collection and use
|
||||
practices when we see a Do Not Track signal from your browser.
|
||||
</P>
|
||||
<SubHeading>YOUR RIGHTS</SubHeading>
|
||||
<P>
|
||||
If you are a European resident, you have the right to access personal
|
||||
information we hold about you and to ask that your personal
|
||||
information be corrected, updated, or deleted. If you would like to
|
||||
exercise this right, please contact us through the contact information
|
||||
below.
|
||||
</P>
|
||||
<P>
|
||||
Additionally, if you are a European resident we note that we are
|
||||
processing your information in order to fulfill contracts we might
|
||||
have with you (for example if you make an order through the Site), or
|
||||
otherwise to pursue our legitimate business interests listed above.
|
||||
Additionally, please note that your information will be transferred
|
||||
outside of Europe, including to Australia, Canada and the United
|
||||
States.
|
||||
</P>
|
||||
<SubHeading>DATA RETENTION</SubHeading>
|
||||
<P>
|
||||
When you place an create a "part" through the Site, we will keep this
|
||||
record to become part of the public website, you can delete you parts
|
||||
at anytime.
|
||||
</P>
|
||||
<SubHeading>CHANGES</SubHeading>
|
||||
<P>
|
||||
We may update this privacy policy from time to time in order to
|
||||
reflect, for example, changes to our practices or for other
|
||||
operational, legal or regulatory reasons.
|
||||
</P>
|
||||
<SubHeading>CONTACT US</SubHeading>
|
||||
<P>
|
||||
For more information about our privacy practices, if you have
|
||||
questions, or if you would like to make a complaint, please contact us
|
||||
by e-mail at{' '}
|
||||
<a href="mailto:privacy@kurthutten.com">privacy@kurthutten.com</a> or
|
||||
by mail using the details provided below:
|
||||
</P>
|
||||
<P>PO Box 462, Figtree, NSW, 2525, Australia</P>
|
||||
</div>
|
||||
</MainLayout>
|
||||
)
|
||||
}
|
||||
|
||||
export default PrivacyPolicyPage
|
||||
@@ -0,0 +1,7 @@
|
||||
import PrivacyPolicyPage from './PrivacyPolicyPage'
|
||||
|
||||
export const generated = () => {
|
||||
return <PrivacyPolicyPage />
|
||||
}
|
||||
|
||||
export default { title: 'Pages/PrivacyPolicyPage' }
|
||||
@@ -0,0 +1,11 @@
|
||||
import { render } from '@redwoodjs/testing'
|
||||
|
||||
import PrivacyPolicyPage from './PrivacyPolicyPage'
|
||||
|
||||
describe('PrivacyPolicyPage', () => {
|
||||
it('renders successfully', () => {
|
||||
expect(() => {
|
||||
render(<PrivacyPolicyPage />)
|
||||
}).not.toThrow()
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,12 @@
|
||||
import SubjectAccessRequestsLayout from 'src/layouts/SubjectAccessRequestsLayout'
|
||||
import SubjectAccessRequestCell from 'src/components/SubjectAccessRequestCell'
|
||||
|
||||
const SubjectAccessRequestPage = ({ id }) => {
|
||||
return (
|
||||
<SubjectAccessRequestsLayout>
|
||||
<SubjectAccessRequestCell id={id} />
|
||||
</SubjectAccessRequestsLayout>
|
||||
)
|
||||
}
|
||||
|
||||
export default SubjectAccessRequestPage
|
||||
@@ -0,0 +1,7 @@
|
||||
import SubjectAccessRequestPage from './SubjectAccessRequestPage'
|
||||
|
||||
export const generated = () => {
|
||||
return <SubjectAccessRequestPage />
|
||||
}
|
||||
|
||||
export default { title: 'Pages/SubjectAccessRequestPage' }
|
||||
@@ -0,0 +1,11 @@
|
||||
import { render } from '@redwoodjs/testing'
|
||||
|
||||
import SubjectAccessRequestPage from './SubjectAccessRequestPage'
|
||||
|
||||
describe('SubjectAccessRequestPage', () => {
|
||||
it('renders successfully', () => {
|
||||
expect(() => {
|
||||
render(<SubjectAccessRequestPage />)
|
||||
}).not.toThrow()
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,164 @@
|
||||
import { useState, useEffect } from 'react'
|
||||
import SubjectAccessRequestsCell from 'src/components/SubjectAccessRequestsCell'
|
||||
import { Flash, useQuery, useMutation, useFlash } from '@redwoodjs/web'
|
||||
import { Form, Submit } from '@redwoodjs/forms'
|
||||
|
||||
import MainLayout from 'src/layouts/MainLayout'
|
||||
import Seo from 'src/components/Seo/Seo'
|
||||
import InputTextForm from 'src/components/InputTextForm'
|
||||
|
||||
export const QUERY = gql`
|
||||
query SUBJECT_ACCESS_REQUEST($userName: String!) {
|
||||
userName(userName: $userName) {
|
||||
id
|
||||
userName
|
||||
email
|
||||
name
|
||||
createdAt
|
||||
updatedAt
|
||||
image
|
||||
bio
|
||||
Parts {
|
||||
id
|
||||
title
|
||||
description
|
||||
code
|
||||
mainImage
|
||||
createdAt
|
||||
updatedAt
|
||||
deleted
|
||||
}
|
||||
Reaction {
|
||||
id
|
||||
emote
|
||||
part {
|
||||
id
|
||||
title
|
||||
}
|
||||
createdAt
|
||||
updatedAt
|
||||
}
|
||||
Comment {
|
||||
id
|
||||
text
|
||||
part {
|
||||
id
|
||||
title
|
||||
}
|
||||
createdAt
|
||||
updatedAt
|
||||
}
|
||||
SubjectAccessRequest {
|
||||
id
|
||||
comment
|
||||
createdAt
|
||||
updatedAt
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
const CREATE_SUBJECT_ACCESS_REQUEST_MUTATION = gql`
|
||||
mutation CreateSubjectAccessRequestMutation(
|
||||
$input: CreateSubjectAccessRequestInput!
|
||||
) {
|
||||
createSubjectAccessRequest(input: $input) {
|
||||
id
|
||||
comment
|
||||
payload
|
||||
userId
|
||||
createdAt
|
||||
updatedAt
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
const SubjectAccessRequestPage = () => {
|
||||
const { addMessage } = useFlash()
|
||||
const [input, setInput] = useState({})
|
||||
const { data } = useQuery(QUERY, {
|
||||
skip: !input.userName,
|
||||
variables: { userName: input.userName },
|
||||
})
|
||||
const onSubmit = (input) => {
|
||||
setInput(input)
|
||||
}
|
||||
const stringData = JSON.stringify(data?.userName)
|
||||
const [createSubjectAccessRequest] = useMutation(
|
||||
CREATE_SUBJECT_ACCESS_REQUEST_MUTATION,
|
||||
{
|
||||
onCompleted: () => {
|
||||
addMessage('SubjectAccessRequest created.', {
|
||||
classes: 'rw-flash-success',
|
||||
})
|
||||
},
|
||||
}
|
||||
)
|
||||
useEffect(() => {
|
||||
if (stringData) {
|
||||
createSubjectAccessRequest({
|
||||
variables: {
|
||||
input: {
|
||||
comment: input?.comment,
|
||||
payload: stringData,
|
||||
userId: data?.userName?.id,
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
}, [stringData])
|
||||
return (
|
||||
<MainLayout>
|
||||
<Seo
|
||||
title={'Subject Access Request'}
|
||||
description="Code of Conduct"
|
||||
lang="en-US"
|
||||
/>
|
||||
<section className="max-w-6xl mx-auto mt-20">
|
||||
<SubjectAccessRequestsCell />
|
||||
Here to fulfill a user's right to portability, before running this
|
||||
please check that the query in
|
||||
"pages/SubjectAccessRequestPage/SubjectAccessRequestPage.js" is
|
||||
up-to-date.
|
||||
<Form onSubmit={onSubmit}>
|
||||
<div
|
||||
className="grid items-center gap-2"
|
||||
style={{ gridTemplateColumns: 'auto 1fr' }}
|
||||
>
|
||||
<span className="capitalize text-gray-500 text-sm align-middle my-3">
|
||||
userName:
|
||||
</span>
|
||||
<InputTextForm
|
||||
className="text-xl"
|
||||
name="userName"
|
||||
validation={{
|
||||
required: true,
|
||||
}}
|
||||
/>
|
||||
<div />
|
||||
<div className="mt-10">
|
||||
Please add how they made the request, who is fulling it (who you
|
||||
are) and any other details
|
||||
</div>
|
||||
<span className="capitalize text-gray-500 text-sm align-middle my-3">
|
||||
comment:
|
||||
</span>
|
||||
<InputTextForm
|
||||
className="text-xl"
|
||||
name="comment"
|
||||
validation={{
|
||||
required: true,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<Submit className="bg-indigo-200 text-indigo-800 p-2 px-4 shadow hover:shadow-lg mt-4 rounded">
|
||||
Submit
|
||||
</Submit>
|
||||
</Form>
|
||||
<pre className="whitespace-pre-wrap">{stringData}</pre>
|
||||
</section>
|
||||
</MainLayout>
|
||||
)
|
||||
}
|
||||
|
||||
export default SubjectAccessRequestPage
|
||||
78
app/web/src/pages/UpdatePasswordPage/UpdatePasswordPage.js
Normal file
78
app/web/src/pages/UpdatePasswordPage/UpdatePasswordPage.js
Normal file
@@ -0,0 +1,78 @@
|
||||
import { routes, navigate } from '@redwoodjs/router'
|
||||
import { useAuth } from '@redwoodjs/auth'
|
||||
import { Form, Submit } from '@redwoodjs/forms'
|
||||
import { useFlash } from '@redwoodjs/web'
|
||||
|
||||
import InputTextForm from 'src/components/InputTextForm'
|
||||
import MainLayout from 'src/layouts/MainLayout'
|
||||
import Seo from 'src/components/Seo/Seo'
|
||||
|
||||
const UpdatePasswordPage = () => {
|
||||
const { addMessage } = useFlash()
|
||||
const { client } = useAuth()
|
||||
const onSubmit = ({ password, confirm }) => {
|
||||
if (password !== confirm || !password) {
|
||||
addMessage("Passwords don't match, try again", {
|
||||
classes: 'bg-red-300 text-red-900',
|
||||
})
|
||||
return
|
||||
}
|
||||
client
|
||||
.currentUser()
|
||||
.update({ password })
|
||||
.then(() => {
|
||||
addMessage('Password updated', { classes: 'rw-flash-success' })
|
||||
setTimeout(() => {
|
||||
navigate(routes.home())
|
||||
}, 500)
|
||||
})
|
||||
.catch(() => {
|
||||
addMessage('Problem updating password', {
|
||||
classes: 'bg-red-300 text-red-900',
|
||||
})
|
||||
})
|
||||
}
|
||||
return (
|
||||
<MainLayout>
|
||||
<Seo title="Update Password" description="Update Password" lang="en-US" />
|
||||
|
||||
<section className="max-w-md mx-auto mt-20">
|
||||
<h2 className="text-xl text-indigo-500 pb-4">Reset Password</h2>
|
||||
<Form onSubmit={onSubmit}>
|
||||
<div
|
||||
className="grid items-center gap-2"
|
||||
style={{ gridTemplateColumns: 'auto 1fr' }}
|
||||
>
|
||||
<span className="capitalize text-gray-500 text-sm align-middle my-3">
|
||||
password:
|
||||
</span>
|
||||
<InputTextForm
|
||||
className="text-xl"
|
||||
name="password"
|
||||
type="password"
|
||||
validation={{
|
||||
required: true,
|
||||
}}
|
||||
/>
|
||||
<span className="capitalize text-gray-500 text-sm align-middle my-3">
|
||||
confirm:
|
||||
</span>
|
||||
<InputTextForm
|
||||
className="text-xl"
|
||||
name="confirm"
|
||||
type="password"
|
||||
validation={{
|
||||
required: true,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<Submit className="bg-indigo-200 text-indigo-800 p-2 px-4 shadow hover:shadow-lg mt-4 rounded">
|
||||
Update
|
||||
</Submit>
|
||||
</Form>
|
||||
</section>
|
||||
</MainLayout>
|
||||
)
|
||||
}
|
||||
|
||||
export default UpdatePasswordPage
|
||||
@@ -0,0 +1,7 @@
|
||||
import UpdatePasswordPage from './UpdatePasswordPage'
|
||||
|
||||
export const generated = () => {
|
||||
return <UpdatePasswordPage />
|
||||
}
|
||||
|
||||
export default { title: 'Pages/UpdatePasswordPage' }
|
||||
@@ -0,0 +1,11 @@
|
||||
import { render } from '@redwoodjs/testing'
|
||||
|
||||
import UpdatePasswordPage from './UpdatePasswordPage'
|
||||
|
||||
describe('UpdatePasswordPage', () => {
|
||||
it('renders successfully', () => {
|
||||
expect(() => {
|
||||
render(<UpdatePasswordPage />)
|
||||
}).not.toThrow()
|
||||
})
|
||||
})
|
||||
15
app/web/src/pages/UserPage/UserPage.js
Normal file
15
app/web/src/pages/UserPage/UserPage.js
Normal file
@@ -0,0 +1,15 @@
|
||||
import MainLayout from 'src/layouts/MainLayout'
|
||||
import EditUserCell from 'src/components/EditUserCell'
|
||||
import Seo from 'src/components/Seo/Seo'
|
||||
|
||||
const UserPage = ({ userName }) => {
|
||||
return (
|
||||
<MainLayout>
|
||||
<Seo title={userName} description="User page" lang="en-US" />
|
||||
|
||||
<EditUserCell userName={userName} />
|
||||
</MainLayout>
|
||||
)
|
||||
}
|
||||
|
||||
export default UserPage
|
||||
15
app/web/src/pages/UsersPage/UsersPage.js
Normal file
15
app/web/src/pages/UsersPage/UsersPage.js
Normal file
@@ -0,0 +1,15 @@
|
||||
import MainLayout from 'src/layouts/MainLayout'
|
||||
import UsersCell from 'src/components/UsersCell'
|
||||
import Seo from 'src/components/Seo/Seo'
|
||||
|
||||
const UsersPage = () => {
|
||||
return (
|
||||
<MainLayout>
|
||||
<Seo title="Users" description="Users page" lang="en-US" />
|
||||
|
||||
<UsersCell />
|
||||
</MainLayout>
|
||||
)
|
||||
}
|
||||
|
||||
export default UsersPage
|
||||
Reference in New Issue
Block a user