Skip to content

Commit

Permalink
Fix postMessage in embedded Contact form (#2673)
Browse files Browse the repository at this point in the history
* Fix postMessage in embedded Contact form

[CORE-532]

* Separate embedded form

Add thank you

* Screaming snake case

* Fix layout issues

* Link to subjects page instead of errata
  • Loading branch information
RoyEJohnson authored Oct 16, 2024
1 parent be1ae78 commit 097a0de
Show file tree
Hide file tree
Showing 8 changed files with 209 additions and 73 deletions.
2 changes: 1 addition & 1 deletion src/app/components/shell/shell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ function AppContext({children}: React.PropsWithChildren<object>) {
);
}

const importContact = () => import('~/pages/contact/contact.js');
const importContact = () => import('~/pages/contact/embedded.js');

function EmbeddedApp() {
return (
Expand Down
28 changes: 0 additions & 28 deletions src/app/pages/contact/contact.scss
Original file line number Diff line number Diff line change
Expand Up @@ -60,34 +60,6 @@

form {
color: os-color(blue);

textarea {
height: auto;
resize: none;
}

> .form-content > label {
display: block;
height: $form-element-height;
margin-bottom: $form-element-height;

&.auto-height {
height: auto;
}
}
}

.btn {
@include button();
margin-bottom: $form-element-height;
}

[type="submit"] {
@extend %primary;

float: none;
margin: 0;
padding: 0 5rem;
}

address {
Expand Down
44 changes: 44 additions & 0 deletions src/app/pages/contact/embedded.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import React from 'react';
import Form from './form';
import './embedded.scss';

// File is js because it is dynamically imported (and minimal)
export default function EmbeddedForm() {
const [submitted, setSubmitted] = React.useState(false);

if (submitted) {
return <ThankYou />;
}

return (
<main id="maincontent" className="embedded-contact">
<h1>Report an issue</h1>
<div>
Need to suggest a content correction instead? Find the book
on our{' '}
<a href="/subjects" target="_blank">
subjects page
</a>.
{' '}You can submit errata from the details page for the book.
</div>
<Form setSubmitted={setSubmitted} />
</main>
);
}

function ThankYou() {
const signalDone = React.useCallback(
() => window.parent.postMessage('CONTACT_FORM_SUBMITTED', '*'),
[]
);

return (
<main id="maincontent" className="embedded-contact">
<h1>Thanks for contacting us.</h1>
<div>Someone from our team will follow up with you soon.</div>
<button type="button" className="btn primary" onClick={signalDone}>
Done
</button>
</main>
);
}
30 changes: 30 additions & 0 deletions src/app/pages/contact/embedded.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
@import 'pattern-library/core/pattern-library/headers';

.embedded-contact {
max-width: calc(100vw - 6rem);
width: $text-content-max;
margin: 3rem auto;
display: flex;
flex-direction: column;
gap: 2rem;

h1 {
@include set-font(h3);
margin: 0;
}

form {
@include wider-than($tablet-max) {
padding-left: 4rem;
}
}

button:not(.clear-file) {
@include button();

&.primary {
@extend %primary;
align-self: flex-start;
}
}
}
88 changes: 63 additions & 25 deletions src/app/pages/contact/form.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import DropdownSelect from '~/components/select/drop-down/drop-down';
import {useNavigate, useLocation} from 'react-router-dom';
import { FileButton } from '../errata-form/form/FileUploader';
import useUserContext from '~/contexts/user';
import './form.scss';

const options = [
'General',
Expand All @@ -20,8 +21,6 @@ const options = [
'OpenStax Polska'
].map((s) => ({label: s, value: s}));

options[0].selected = true;

const assignableOptions = [
'Getting Started',
'Assignment',
Expand Down Expand Up @@ -59,29 +58,57 @@ function LabeledInputWithInvalidMessage({
);
}

function useAfterSubmit() {
const navigate = useNavigate();
function useIsEmbedded() {
const {pathname} = useLocation();

return pathname.includes('embedded');
}

function useAfterSubmit(setSubmitted) {
const navigate = useNavigate();
const isEmbedded = useIsEmbedded();

return React.useCallback(
() => {
if (pathname.includes('embedded')) {
window.parent.postMessage('contact form submitted');
if (isEmbedded) {
setSubmitted(true);
} else {
navigate('/confirmation/contact');
}
},
[navigate, pathname]
[navigate, isEmbedded, setSubmitted]
);
}

function useSubjectWithInitialization() {
const isEmbedded = useIsEmbedded();
const initialValue = isEmbedded ? 'OpenStax Assignable' : 'General';
const subjectState = useState(initialValue);

// useEffect runs too late
React.useMemo(
() => {
for (const o of options) {
if (o.value === initialValue) {
o.selected = true;
} else {
delete o.selected;
}
}
},
[initialValue]
);

return subjectState;
}

// This is an interim site; normally we can leave postTo null and the default
// in the salesforceForm will be right.
const newPostSite = 'https://hooks.zapier.com/hooks/catch/175480/3n62dhe/';

export default function ContactForm() {
export default function ContactForm({setSubmitted}) {
const [showInvalidMessages, setShowInvalidMessages] = useState(false);
const [subject, setSubject] = useState('General');
const [subject, setSubject] = useSubjectWithInitialization();
const assignableSelected = React.useMemo(
() => subject === 'OpenStax Assignable',
[subject]
Expand All @@ -94,15 +121,11 @@ export default function ContactForm() {
() => (subject === 'OpenStax Polska') ? '/apps/cms/api/mail/send_mail' : newPostSite,
[subject]
);
const onChangeSubject = React.useCallback(
(value) => setSubject(value),
[]
);
const beforeSubmit = React.useCallback(
() => setShowInvalidMessages(true),
[setShowInvalidMessages]
);
const afterSubmit = useAfterSubmit();
const afterSubmit = useAfterSubmit(setSubmitted);
const searchParams = new window.URLSearchParams(window.location.search);
const bodyParams = searchParams.getAll('body').join('\n');
const {userStatus} = useUserContext();
Expand All @@ -115,33 +138,48 @@ export default function ContactForm() {
<input type="hidden" name="user_id" value={userUuid} />
<input type="hidden" name="support_context" value={bodyParams} />
<label>
What is your question about?
<div className="label-text">
What is your question about?
</div>
<DropdownSelect
name="subject" options={options}
onValueUpdate={onChangeSubject}
name="subject"
options={options}
onValueUpdate={setSubject}
/>
</label>
{
assignableSelected && <label>What Assignable topic in particular?
<DropdownSelect
name="feature" options={assignableOptions}
/>
assignableSelected && <label>
<div className="label-text">
What Assignable topic in particular?
</div>
<DropdownSelect
name="feature" options={assignableOptions}
/>
</label>
}
<LabeledInputWithInvalidMessage showMessage={showInvalidMessages}>
Your Name
<div className="label-text">
Your Name
</div>
<input name="name" type="text" size="20" required />
</LabeledInputWithInvalidMessage>
<LabeledInputWithInvalidMessage showMessage={showInvalidMessages}>
Your Email Address
<div className="label-text">
Your Email Address
</div>
<input name="email" type="email" required />
</LabeledInputWithInvalidMessage>
<LabeledInputWithInvalidMessage className="auto-height" showMessage={showInvalidMessages}>
Your Message
<div className="label-text">
Your Message
</div>
<textarea cols="50" name="description" rows="6" required />
</LabeledInputWithInvalidMessage>
<div className="label-text">
Please add a screenshot or any other file that helps explain your request.
</div>
<FileButton name="attachment" />
<input type="submit" value="Send" className="btn btn-orange" onClick={beforeSubmit} />
<input type="submit" className="btn btn-orange" onClick={beforeSubmit} />
</SalesforceForm>
);
}
46 changes: 46 additions & 0 deletions src/app/pages/contact/form.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
@import 'pattern-library/core/pattern-library/headers';
@import '../errata-form/form/FileUploader';

form {
textarea {
height: auto;
resize: none;
}

> .form-content > label {
display: block;
height: $form-element-height;
margin-bottom: $form-element-height;

&.auto-height {
height: auto;
}

}

.file-button {
@include file-button();
margin-bottom: $normal-margin;
}

.label-text {
@include set-font(h4);
margin-bottom: 0.5rem;
}

.btn,
.btn[type="submit"] {
@include button();
width: 12rem;
padding: 0;

}

[type="submit"] {
@extend %primary;

float: none;
margin: 0;
padding: 0 5rem;
}
}
22 changes: 22 additions & 0 deletions src/app/pages/errata-form/form/FileUploader.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
@mixin file-button() {
align-items: center;
display: grid;
grid-gap: 1rem;
grid-template-columns: repeat(3, auto) 1fr;

&.empty {
order: 1;

+ .file-button.empty {
display: none;
}
}

.clear-file {
appearance: none;
background-color: inherit;
color: inherit;
justify-self: left;

}
}
22 changes: 3 additions & 19 deletions src/app/pages/errata-form/form/form.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
@import 'pattern-library/core/pattern-library/headers';
@import './FileUploader';

.banned-notice {
padding: $normal-margin;
Expand Down Expand Up @@ -87,8 +88,7 @@
}
}

.button-group,
.file-button {
.button-group {
align-items: center;
display: grid;
grid-gap: 1rem;
Expand All @@ -99,23 +99,7 @@
}

.file-button {
grid-template-columns: auto auto 1fr;

&.empty {
order: 1;

+ .file-button.empty {
display: none;
}
}
}

.clear-file {
appearance: none;
background-color: inherit;
color: inherit;
justify-self: left;

@include file-button();
}

.btn {
Expand Down

0 comments on commit 097a0de

Please sign in to comment.