Skip to content

Commit e7d0d4b

Browse files
authored
Fe add organization creation (canada-ca#2290)
* Button on admin page brings users to CreateOrganizationPage.js * Added FormControl to all input fields, added validation schema for acronyms * Centered "No admin orgs" screen * translations * added AcronymField.js and validation errors appear * Removed unneeded Form Error Messages * Add tests * input placeholders * changed toast to display org name instead of slug * more tests * move test into proper describe * All fields now have labels and validation schema * translation for required field * htmlFor={name} added to CreateOrganizationField.js
1 parent 71ba5ae commit e7d0d4b

10 files changed

Lines changed: 778 additions & 13 deletions

File tree

frontend/src/AdminPage.js

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React, { useState } from 'react'
2-
import { Stack, Text, Select, useToast } from '@chakra-ui/core'
2+
import { Stack, Text, Select, useToast, Icon, Divider } from '@chakra-ui/core'
33
import { Trans, t } from '@lingui/macro'
44
import { Layout } from './Layout'
55
import AdminPanel from './AdminPanel'
@@ -8,6 +8,8 @@ import { useQuery } from '@apollo/client'
88
import { useUserState } from './UserState'
99
import { ErrorFallbackMessage } from './ErrorFallbackMessage'
1010
import { LoadingMessage } from './LoadingMessage'
11+
import { TrackerButton } from './TrackerButton'
12+
import { Link as RouteLink } from 'react-router-dom'
1113

1214
export default function AdminPage() {
1315
const { currentUser } = useUserState()
@@ -90,7 +92,7 @@ export default function AdminPage() {
9092
<Text fontSize="4xl" fontWeight="bold" textAlign={['center', 'left']}>
9193
<Trans>Welcome, Admin</Trans>
9294
</Text>
93-
<Stack isInline align="center">
95+
<Stack flexDirection={['column', 'row']} align="center">
9496
<Text fontWeight="bold" fontSize="2xl">
9597
<Trans>Organization: </Trans>
9698
</Text>
@@ -105,6 +107,16 @@ export default function AdminPage() {
105107
>
106108
{options}
107109
</Select>
110+
<TrackerButton
111+
ml={['0', 'auto']}
112+
w={['100%', 'auto']}
113+
variant="primary"
114+
as={RouteLink}
115+
to="/create-organization"
116+
>
117+
<Icon name="add" />
118+
<Trans>Create Organization</Trans>
119+
</TrackerButton>
108120
</Stack>
109121
{options.length > 1 && orgDetails ? (
110122
<Stack>
@@ -125,9 +137,23 @@ export default function AdminPage() {
125137
)
126138
} else {
127139
return (
128-
<Text fontSize="3xl" fontWeight="bold" textAlign="center">
129-
<Trans>You do not have admin permissions in any organization</Trans>
130-
</Text>
140+
<Layout>
141+
<Stack align="center">
142+
<Text fontSize="3xl" fontWeight="bold" textAlign="center">
143+
<Trans>You do not have admin permissions in any organization</Trans>
144+
</Text>
145+
<Divider />
146+
<TrackerButton
147+
w={['100%', 'auto']}
148+
variant="primary"
149+
as={RouteLink}
150+
to="/create-organization"
151+
>
152+
<Icon name="add" />
153+
<Trans>Create Organization</Trans>
154+
</TrackerButton>
155+
</Stack>
156+
</Layout>
131157
)
132158
}
133159
}

frontend/src/App.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ const TwoFactorAuthenticatePage = lazy(() =>
3636
import('./TwoFactorAuthenticatePage'),
3737
)
3838
const EmailValidationPage = lazy(() => import('./EmailValidationPage'))
39+
const CreateOrganizationPage = lazy(() => import('./CreateOrganizationPage'))
3940

4041
export default function App() {
4142
// Hooks to be used with this functional component
@@ -203,6 +204,13 @@ export default function App() {
203204
<EmailValidationPage />
204205
</Page>
205206

207+
<PrivatePage
208+
path="/create-organization"
209+
title={t`Create Organization`}
210+
>
211+
<CreateOrganizationPage />
212+
</PrivatePage>
213+
206214
<Page component={PageNotFound} title="404" />
207215
</Switch>
208216
</Suspense>
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import React from 'react'
2+
import { elementType, func, oneOfType, shape, string } from 'prop-types'
3+
import {
4+
FormControl,
5+
FormErrorMessage,
6+
FormLabel,
7+
Input,
8+
} from '@chakra-ui/core'
9+
import { useField } from 'formik'
10+
import WithPseudoBox from './withPseudoBox'
11+
12+
const OrganizationCreateField = WithPseudoBox(function OrganizationCreateField({
13+
name,
14+
label,
15+
language,
16+
forwardedRef,
17+
...props
18+
}) {
19+
const [field, meta] = useField(name)
20+
21+
return (
22+
<FormControl isInvalid={meta.error && meta.touched}>
23+
<FormLabel htmlFor={name} fontWeight="bold">
24+
{label} ({language})
25+
</FormLabel>
26+
<Input
27+
{...field}
28+
{...props}
29+
id={name}
30+
name={name}
31+
ref={forwardedRef}
32+
placeholder={`${label} (${language})`}
33+
/>
34+
<FormErrorMessage>{meta.error}</FormErrorMessage>
35+
</FormControl>
36+
)
37+
})
38+
39+
OrganizationCreateField.propTypes = {
40+
name: string.isRequired,
41+
forwardedRef: oneOfType([func, shape({ current: elementType })]),
42+
}
43+
44+
const withForwardedRef = React.forwardRef((props, ref) => {
45+
return <OrganizationCreateField {...props} forwardedRef={ref} />
46+
})
47+
withForwardedRef.displayName = 'OrganizationCreateField'
48+
49+
export default withForwardedRef

0 commit comments

Comments
 (0)