feat(lib): add optional request password button to login page (#334)

* add optional request password button to login page

* fix linting

* fix linting

* added field to backend config
This commit is contained in:
Anton Tranelis 2025-08-26 14:43:31 +02:00 committed by GitHub
parent 1ef562cf3c
commit a599eddca6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 87 additions and 8 deletions

View File

@ -168,7 +168,15 @@ function App() {
<Routes>
<Route path='/*' element={<MapContainer map={map} layers={layers} />}>
<Route path='invite/:id' element={<InvitePage inviteApi={inviteApi} />} />
<Route path='login' element={<LoginPage inviteApi={inviteApi} />} />
<Route
path='login'
element={
<LoginPage
showRequestPassword={map.show_request_password}
inviteApi={inviteApi}
/>
}
/>
<Route path='signup' element={<SignupPage />} />
<Route
path='reset-password'

View File

@ -0,0 +1,45 @@
{
"collection": "maps",
"field": "show_request_password",
"type": "boolean",
"meta": {
"collection": "maps",
"conditions": null,
"display": null,
"display_options": null,
"field": "show_request_password",
"group": null,
"hidden": false,
"interface": "boolean",
"note": null,
"options": null,
"readonly": false,
"required": false,
"sort": 18,
"special": [
"cast-boolean"
],
"translations": null,
"validation": null,
"validation_message": null,
"width": "full"
},
"schema": {
"name": "show_request_password",
"table": "maps",
"data_type": "boolean",
"default_value": false,
"max_length": null,
"numeric_precision": null,
"numeric_scale": null,
"is_nullable": true,
"is_unique": false,
"is_indexed": false,
"is_primary_key": false,
"is_generated": false,
"generation_expression": null,
"has_auto_increment": false,
"foreign_key_table": null,
"foreign_key_column": null
}
}

View File

@ -1955,6 +1955,7 @@ type maps {
url: String
zoom: Int
hide_signup: Boolean
show_request_password: Boolean
layers(filter: layers_maps_filter, sort: [String], limit: Int, offset: Int, page: Int, search: String): [layers_maps]
layers_func: count_functions
}
@ -2002,6 +2003,7 @@ type maps_aggregated_count {
url: Int
zoom: Int
hide_signup: Int
show_request_password: Int
layers: Int
}
@ -2676,6 +2678,7 @@ type version_maps {
url: String
zoom: Int
hide_signup: Boolean
show_request_password: Boolean
layers: JSON
}
@ -3225,6 +3228,7 @@ input create_maps_input {
url: String
zoom: Int
hide_signup: Boolean
show_request_password: Boolean
layers: [create_layers_maps_input]
}
@ -4205,6 +4209,7 @@ input maps_filter {
url: string_filter_operators
zoom: number_filter_operators
hide_signup: boolean_filter_operators
show_request_password: boolean_filter_operators
layers: layers_maps_quantifier_filter
layers_func: count_function_filter_operators
_and: [maps_filter]
@ -4770,6 +4775,7 @@ input update_maps_input {
url: String
zoom: Int
hide_signup: Boolean
show_request_password: Boolean
layers: [update_layers_maps_input]
}

View File

@ -23103,6 +23103,10 @@
"nullable": true,
"type": "boolean"
},
"show_request_password": {
"nullable": true,
"type": "boolean"
},
"layers": {
"nullable": true,
"type": "array",

View File

@ -2040,6 +2040,7 @@ type maps {
url: String
zoom: Int
hide_signup: Boolean
show_request_password: Boolean
layers(filter: layers_maps_filter, sort: [String], limit: Int, offset: Int, page: Int, search: String): [layers_maps]
layers_func: count_functions
}
@ -2785,6 +2786,7 @@ input create_maps_input {
url: String
zoom: Int
hide_signup: Boolean
show_request_password: Boolean
layers: [create_layers_maps_input]
}
@ -3749,6 +3751,7 @@ input maps_filter {
url: string_filter_operators
zoom: number_filter_operators
hide_signup: boolean_filter_operators
show_request_password: boolean_filter_operators
layers: layers_maps_quantifier_filter
layers_func: count_function_filter_operators
_and: [maps_filter]
@ -4308,6 +4311,7 @@ input update_maps_input {
url: String
zoom: Int
hide_signup: Boolean
show_request_password: Boolean
layers: [update_layers_maps_input]
}

View File

@ -11,12 +11,13 @@ import type { InviteApi } from '#types/InviteApi'
interface Props {
inviteApi: InviteApi
showRequestPassword?: boolean
}
/**
* @category Auth
*/
export function LoginPage({ inviteApi }: Props) {
export function LoginPage({ inviteApi, showRequestPassword }: Props) {
const [email, setEmail] = useState<string>('')
const [password, setPassword] = useState<string>('')
@ -106,11 +107,13 @@ export function LoginPage({ inviteApi }: Props) {
className='tw:input tw:input-bordered tw:w-full tw:max-w-xs'
/>
<div className='tw:text-right tw:text-primary'>
{!showRequestPassword && (
<Link to='/reset-password'>
<span className='tw:text-sm tw:inline-block tw:hover:text-primary tw:hover:underline tw:hover:cursor-pointer tw:transition tw:duration-200'>
Forgot Password?
</span>
</Link>
)}
</div>
<div className='tw:card-actions'>
<button
@ -124,6 +127,14 @@ export function LoginPage({ inviteApi }: Props) {
>
{loading ? <span className='tw:loading tw:loading-spinner'></span> : 'Login'}
</button>
{showRequestPassword && (
<>
<div className='tw:divider tw:w-full'>OR</div>
<Link to='/reset-password' className='tw:w-full'>
<button className='tw:btn tw:btn-primary tw:btn-block'>{'Request Password'}</button>
</Link>
</>
)}
</div>
</MapOverlayPage>
)

View File

@ -37,7 +37,7 @@ export function RequestPasswordPage({ resetUrl }: { resetUrl: string }) {
return (
<MapOverlayPage backdrop className='tw:max-w-xs tw:h-fit'>
<h2 className='tw:text-2xl tw:font-semibold tw:mb-2 tw:text-center'>Reset Password</h2>
<h2 className='tw:text-2xl tw:font-semibold tw:mb-2 tw:text-center'>Request Password</h2>
<input
type='email'
placeholder='E-Mail'

View File

@ -20,5 +20,6 @@ export interface UtopiaMapProps {
expandLayerControl?: boolean
tileServerUrl?: string
tileServerAttribution?: string
show_request_password?: boolean
hideSignup?: boolean
}