Skip to content

Commit d09ab1a

Browse files
Error messages display correctly (#4)
* Error messages display correctly * Helper function on flow and demoflow * First and last name required fix on settings page * Removed unused code * Smaller changes * Use submodule in entry * Drone build for submodules * removed submodules * Drone * Removed submodules * Comment for submodules
1 parent ea750d9 commit d09ab1a

File tree

8 files changed

+67
-55
lines changed

8 files changed

+67
-55
lines changed

pages/login.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ const Login: NextPage = () => {
141141
</span>
142142
</fieldset>
143143
<p className="text-description" id="description">
144-
{selectedRole === 'engineer' ? 'Administers the project and works on programmatic tasks such as labeling automation or filter settings.' : selectedRole === 'expert' ? 'Working on reference manual labels, which can be used by the engineering team to estimate the data quality.' : 'Working on manual labels as if they were heuristics. They can be switched on/off by the engineering team, so that the engineers can in- or exclude them during weak supervision.'}
144+
{selectedRole === 'engineer' ? 'Administers the project and works on programmatic tasks such as labeling automation or filter settings.' : selectedRole === 'expert' ? 'Working on reference manual labels, which can be used by the engineering team to estimate the data quality.' : 'Working on manual labels as if they were heuristics. They can be switched on/off by the engineering team, so that the engineers can in - or exclude them during weak supervision.'}
145145
</p>
146146
<p className="text-description" id="sub-description">
147147
{selectedRole === 'engineer' ? 'They have access to all features of the application, including the Python SDK.' : selectedRole === 'expert' ? 'They have access to the labeling view only.' : 'They have access to a task-minimized labeling view only. Engineers can revoke their access to the labeling view.'}

pages/registration.tsx

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import ory from "@/pkg/sdk"
99
import { handleFlowError } from "@/pkg/errors"
1010
import { Flow } from "@/pkg"
1111
import { MiscInfo } from "@/services/basic-fetch/misc"
12+
import { prepareFirstLastNameAsRequired } from "@/util/helper-functions"
1213

1314
// Renders the registration page
1415
const Registration: NextPage = () => {
@@ -17,6 +18,7 @@ const Registration: NextPage = () => {
1718
// The "flow" represents a registration process and contains
1819
// information about the form we need to render (e.g. username + password)
1920
const [initialFlow, setInitialFlow]: any = useState<RegistrationFlow>()
21+
const [changedFlow, setChangedFlow]: any = useState<RegistrationFlow>()
2022

2123
// Get ?flow=... from the URL
2224
const { flow: flowId, return_to: returnTo } = router.query;
@@ -56,21 +58,11 @@ const Registration: NextPage = () => {
5658
if (initialFlow.ui.nodes[1].meta.label) {
5759
initialFlow.ui.nodes[1].meta.label.text = "Email address"
5860
}
59-
if (initialFlow.ui.nodes[3].attributes.name === "traits.name.first") {
60-
initialFlow.ui.nodes[3].attributes.required = true
61-
}
62-
if (initialFlow.ui.nodes[4].attributes.name === "traits.name.last") {
63-
initialFlow.ui.nodes[4].attributes.required = true
64-
}
65-
setInitialFlow(initialFlow);
61+
initialFlow.ui.nodes = prepareFirstLastNameAsRequired(3, 4, initialFlow);
62+
setChangedFlow(initialFlow);
6663
}, [initialFlow])
6764

6865
const onSubmit = async (values: UpdateRegistrationFlowBody) => {
69-
await router
70-
// On submission, add the flow ID to the URL but do not navigate. This prevents the user loosing
71-
// his data when she/he reloads the page.
72-
.push(`/registration?flow=${initialFlow?.id}`, undefined, { shallow: true })
73-
7466
ory
7567
.updateRegistrationFlow({
7668
flow: String(initialFlow?.id),
@@ -103,7 +95,7 @@ const Registration: NextPage = () => {
10395
<KernLogo />
10496
<div id="signup">
10597
<h2 className="title">{MiscInfo.isManaged ? 'Start your 14-day free trial' : 'Sign up for a local account'}</h2>
106-
<Flow onSubmit={onSubmit} flow={initialFlow} />
98+
<Flow onSubmit={onSubmit} flow={changedFlow} />
10799
<div className="link-container">
108100
<a className="link" data-testid="forgot-password" href="/auth/login">Go back to login</a>
109101
</div>

pages/settings.tsx

Lines changed: 26 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { SettingsFlow, UpdateSettingsFlowBody } from "@ory/client"
1+
import { SettingsFlow, UiNode, UpdateSettingsFlowBody } from "@ory/client"
22
import { AxiosError } from "axios"
33
import type { NextPage } from "next"
44
import Head from "next/head"
@@ -9,10 +9,11 @@ import { Flow, Messages } from "../pkg"
99
import { handleFlowError } from "../pkg/errors"
1010
import ory from "../pkg/sdk"
1111
import { KernLogo } from "@/pkg/ui/Icons"
12+
import { prepareFirstLastNameAsRequired } from "@/util/helper-functions"
1213

1314
const Settings: NextPage = () => {
14-
const [initialFlow, setInitialFlow] = useState<SettingsFlow>()
15-
const [changedFlow, setChangedFlow] = useState<SettingsFlow>()
15+
const [initialFlow, setInitialFlow]: any = useState<SettingsFlow>()
16+
const [changedFlow, setChangedFlow]: any = useState<SettingsFlow>()
1617
const [containsTotp, setContainsTotp] = useState<boolean>(false)
1718
const [containsBackupCodes, setContainsBackupCodes] = useState<boolean>(false)
1819

@@ -53,8 +54,9 @@ const Settings: NextPage = () => {
5354
if (initialFlow.ui.nodes[1].meta.label) {
5455
initialFlow.ui.nodes[1].meta.label.text = "Email address";
5556
}
56-
const checkIfTotp = initialFlow.ui.nodes.find((node) => node.group === "totp");
57-
const checkIfBackupCodes = initialFlow.ui.nodes.find((node) => node.group === "lookup_secret");
57+
initialFlow.ui.nodes = prepareFirstLastNameAsRequired(2, 3, initialFlow);
58+
const checkIfTotp = initialFlow.ui.nodes.find((node: UiNode) => node.group === "totp");
59+
const checkIfBackupCodes = initialFlow.ui.nodes.find((node: UiNode) => node.group === "lookup_secret");
5860
if (checkIfTotp) {
5961
setContainsTotp(true);
6062
}
@@ -65,33 +67,26 @@ const Settings: NextPage = () => {
6567
}, [initialFlow])
6668

6769
const onSubmit = (values: UpdateSettingsFlowBody) =>
68-
router
69-
// On submission, add the flow ID to the URL but do not navigate. This prevents the user loosing
70-
// his data when she/he reloads the page.
71-
.push(`/settings?flow=${initialFlow?.id}`, undefined, { shallow: true })
72-
.then(() =>
73-
ory
74-
.updateSettingsFlow({
75-
flow: String(initialFlow?.id),
76-
updateSettingsFlowBody: values,
77-
})
78-
.then(({ data }) => {
79-
// The settings have been saved and the flow was updated. Let's show it to the user!
80-
setInitialFlow(data)
81-
})
82-
.catch(handleFlowError(router, "settings", setInitialFlow))
83-
.catch(async (err: AxiosError) => {
84-
// If the previous handler did not catch the error it's most likely a form validation error
85-
if (err.response?.status === 400) {
86-
// Yup, it is!
87-
setInitialFlow(err.response?.data)
88-
return
89-
}
90-
91-
return Promise.reject(err)
92-
}),
93-
)
70+
ory
71+
.updateSettingsFlow({
72+
flow: String(initialFlow?.id),
73+
updateSettingsFlowBody: values,
74+
})
75+
.then(({ data }) => {
76+
// The settings have been saved and the flow was updated. Let's show it to the user!
77+
setInitialFlow(data)
78+
})
79+
.catch(handleFlowError(router, "settings", setInitialFlow))
80+
.catch(async (err: AxiosError) => {
81+
// If the previous handler did not catch the error it's most likely a form validation error
82+
if (err.response?.status === 400) {
83+
// Yup, it is!
84+
setInitialFlow(err.response?.data)
85+
return
86+
}
9487

88+
return Promise.reject(err)
89+
})
9590
return (
9691
<>
9792
<Head>

pkg/ui/DemoFlow.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { Component, FormEvent, MouseEvent } from "react"
1616

1717
import { Messages } from "./Messages"
1818
import { Node } from "./Node"
19+
import { refactorFlowWithMoreMessages } from "@/util/helper-functions"
1920

2021
export type Values = Partial<
2122
| UpdateLoginFlowBody
@@ -168,8 +169,8 @@ export class DemoFlow<T extends Values> extends Component<Props<T>, State<T>> {
168169
}
169170

170171
render() {
171-
const { hideGlobalMessages, flow } = this.props
172172
const { values, isLoading } = this.state
173+
const flow = refactorFlowWithMoreMessages(this.props.flow)
173174

174175
// Filter the nodes - only show the ones we want
175176
const nodes = this.filterNodes()
@@ -188,7 +189,7 @@ export class DemoFlow<T extends Values> extends Component<Props<T>, State<T>> {
188189
method={flow.ui.method}
189190
onSubmit={this.handleSubmit}
190191
>
191-
{!hideGlobalMessages ? <Messages messages={flow.ui.messages} /> : null}
192+
{!this.props.hideGlobalMessages ? <Messages messages={flow.ui.messages} /> : null}
192193
{nodes.map((node, k) => {
193194

194195

pkg/ui/Flow.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { Component, FormEvent, MouseEvent } from "react"
1616

1717
import { Messages } from "./Messages"
1818
import { Node } from "./Node"
19+
import { refactorFlowWithMoreMessages } from "@/util/helper-functions"
1920

2021
export type Values = Partial<
2122
| UpdateLoginFlowBody
@@ -168,8 +169,8 @@ export class Flow<T extends Values> extends Component<Props<T>, State<T>> {
168169
}
169170

170171
render() {
171-
const { hideGlobalMessages, flow } = this.props
172172
const { values, isLoading } = this.state
173+
const flow = refactorFlowWithMoreMessages(this.props.flow)
173174

174175
// Filter the nodes - only show the ones we want
175176
const nodes = this.filterNodes()
@@ -187,7 +188,7 @@ export class Flow<T extends Values> extends Component<Props<T>, State<T>> {
187188
method={flow.ui.method}
188189
onSubmit={this.handleSubmit}
189190
>
190-
{!hideGlobalMessages ? <Messages messages={flow.ui.messages} /> : null}
191+
{!this.props.hideGlobalMessages ? <Messages messages={flow.ui.messages} /> : null}
191192
{nodes.map((node, k) => {
192193
const id = getNodeId(node) as keyof Values
193194
return <Node

pkg/ui/NodeInputDefault.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { TextInput } from "@ory/themes"
22

33
import { NodeInputProps } from "./helpers"
44
import { getNodeLabel } from "@ory/integrations/ui"
5+
import { Message } from "./Messages"
56

67
export function NodeInputDefault<T>(props: NodeInputProps) {
78
const { node, attributes, value = "", setValue, disabled } = props
@@ -37,10 +38,8 @@ export function NodeInputDefault<T>(props: NodeInputProps) {
3738
}
3839
subtitle={
3940
<>
40-
{node.messages.map(({ text, id }, k) => (
41-
<span key={`${id}-${k}`} data-testid={`ui/message/${id}`}>
42-
{text}
43-
</span>
41+
{node.messages.forEach((message: any) => (
42+
<Message message={message} />
4443
))}
4544
</>
4645
}

services/basic-fetch/util.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export function jsonFetchWrapper(url: string, fetchType: FetchType, onResult?: (
1313
alertUser();
1414
return;
1515
}
16+
// can't use submodule because of drone build issues. Copied instead
1617
if (!headers) headers = {};
1718
headers["Content-Type"] = "application/json";
1819

@@ -31,8 +32,6 @@ export function jsonFetchWrapper(url: string, fetchType: FetchType, onResult?: (
3132
});
3233

3334
if (onResult && !hasError) myFetch.then(result => onResult(result));
34-
35-
3635
}
3736

3837

util/helper-functions.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,29 @@ export function getValuePassword(selectedRole: any) {
2020
value = 'c34540903b9f';
2121
}
2222
return value;
23+
}
24+
25+
export function refactorFlowWithMoreMessages(flow: any) {
26+
if (flow !== undefined && flow.ui.messages == undefined) {
27+
const messages: any[] = [];
28+
flow.ui.nodes.forEach((node: any) => {
29+
if (node.messages.length > 0) {
30+
node.messages.forEach((message: any) => {
31+
messages.push(message);
32+
});
33+
}
34+
});
35+
flow.ui = { ...flow?.ui, messages: messages };
36+
}
37+
return flow;
38+
}
39+
40+
export function prepareFirstLastNameAsRequired(firstNameIdx: number, lastNameIdx: number, initialFlow: any) {
41+
if (initialFlow.ui.nodes[firstNameIdx].attributes.name === "traits.name.first") {
42+
initialFlow.ui.nodes[firstNameIdx].attributes.required = true
43+
}
44+
if (initialFlow.ui.nodes[lastNameIdx].attributes.name === "traits.name.last") {
45+
initialFlow.ui.nodes[lastNameIdx].attributes.required = true
46+
}
47+
return initialFlow.ui.nodes;
2348
}

0 commit comments

Comments
 (0)