Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Information card styling #41

Merged
merged 12 commits into from
Jun 27, 2023
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@

### Refactoring

- Changed button title from "Create New Credentials" to "New Credentials". (INDIGO 230609, [!42](https://github.com/TeskaLabs/seacat-admin-webui/pull/42))
- Changed button title from "Create New Credentials" to "New Credentials". (INDIGO 230609, [!42](https://github.com/TeskaLabs/seacat-admin-webui/pull/42))

### Bugfix

- Fix CredentialsInfoCard, card will not resize when an error occurs in an input, disable `Save` button if hint about wrong input is present, error hint message be cleaned when user click on `Cancel` button (INDIGO 230623, [!41](https://github.com/TeskaLabs/seacat-admin-webui/pull/41))

## v23.23-alpha2

Expand Down
21 changes: 12 additions & 9 deletions src/modules/auth/credentials/CredentialsCreateContainer.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import React, { useState, useEffect } from 'react';
import { useSelector } from 'react-redux';
import { useParams, Link } from 'react-router-dom';
import { useForm } from "react-hook-form";
import { useTranslation } from 'react-i18next';
import classnames from 'classnames';
Expand Down Expand Up @@ -29,7 +28,7 @@ function CredentialsCreateContainer(props) {
let SeaCatAuthAPI = props.app.axiosCreate('seacat_auth');
const { t, i18n } = useTranslation();

const { handleSubmit, register, formState: { errors }, getValues, setValue, reset, resetField } = useForm({
const { handleSubmit, register, formState: { errors }, getValues, setValue, reset, resetField, trigger, watch } = useForm({
defaultValues: {
'passwordlink': true,
}
Expand All @@ -44,6 +43,9 @@ function CredentialsCreateContainer(props) {
const resources = useSelector(state => state.auth?.resources);
const tenant = useSelector(state => state.tenant?.current);

const emailValue = watch('email');
const phoneValue = watch('phone');

useEffect(() => {
retrieveProviders();
}, []);
Expand Down Expand Up @@ -238,9 +240,9 @@ function CredentialsCreateContainer(props) {
{(activeTab == "create") && (config !== undefined) && config.creation.map((item, idx) => {
switch(item.type) {
case 'username': return(<UserNameField key={idx} register={register} config={item} getValues={getValues} errors={errors} required={item.policy === "required"} />)
case 'email': return(<EmailField key={idx} register={register} config={item} getValues={getValues} errors={errors} required={item.policy === "required"} />)
case 'email': return(<EmailField key={idx} register={register} config={item} getValues={getValues} errors={errors} required={item.policy === "required"} trigger={trigger} phoneValue={phoneValue} />)
case 'password': return(<PasswordField key={idx} register={register} config={item} getValues={getValues} errors={errors} />)
case 'phone': return(<PhoneField key={idx} register={register} config={item} getValues={getValues} setValue={setValue} errors={errors} required={item.policy === "required"} />)
case 'phone': return(<PhoneField key={idx} register={register} config={item} getValues={getValues} setValue={setValue} errors={errors} required={item.policy === "required"} trigger={trigger} emailValue={emailValue} />)
case 'passwordlink': return(<PasswordLinkField key={idx} register={register} config={item} getValues={getValues} errors={errors}/>)
default: return(<div key={idx}>Unknown item: "{item.type}"</div>)
}
Expand All @@ -251,11 +253,11 @@ function CredentialsCreateContainer(props) {
<TabPane tabId="invite">
<CardBody>
{(activeTab == "invite") &&
<>
<EmailField register={register} getValues={getValues} errors={errors} required={true} />
<UserNameField register={register} getValues={getValues} errors={errors} required={false} />
<PhoneField register={register} getValues={getValues} setValue={setValue} errors={errors} required={false} />
</>}
<>
<EmailField register={register} getValues={getValues} errors={errors} required={true} trigger={trigger} phoneValue={phoneValue} />
<UserNameField register={register} getValues={getValues} errors={errors} required={false} />
<PhoneField register={register} getValues={getValues} setValue={setValue} errors={errors} required={false} trigger={trigger} emailValue={emailValue} />
</>}
</CardBody>
</TabPane>
</TabContent>
Expand All @@ -280,3 +282,4 @@ function CredentialsCreateContainer(props) {
}

export default CredentialsCreateContainer;

31 changes: 23 additions & 8 deletions src/modules/auth/credentials/CredentialsDetailContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
} from './FormFields';

import ReactJson from 'react-json-view';
import { DateTime, ButtonWithAuthz, CellContentLoader } from 'asab-webui';
import { DateTime, ButtonWithAuthz } from 'asab-webui';

import CredentialsRolesCard from './CredentialsRolesCard';
import CredentialsTenantsCard from './CredentialsTenantsCard';
Expand Down Expand Up @@ -407,12 +407,16 @@ export default CredentialsDetailContainer;


function CredentialsInfoCard(props) {
const { handleSubmit, register, formState: { errors }, getValues, setValue } = useForm();
const { t, i18n } = useTranslation();
const { handleSubmit, register, formState: { errors }, getValues, setValue, clearErrors, watch, trigger } = useForm();
const { t } = useTranslation();
const [ editMode, setEditMode ] = useState(false);
const [ onUpdate, setOnUpdate ] = useState(false);
const disableEmail = props.updateFeatures.some(feature => feature.type === "email") ? false : true;
const disablePhone = props.updateFeatures.some(feature => feature.type === "phone") ? false : true;
const disableSaveButton = errors.email || errors.phone;

const emailValue = watch('email');
const phoneValue = watch('phone');

if (props.data != null && onUpdate === false) {
setValue("email", props.data.email);
Expand Down Expand Up @@ -476,19 +480,29 @@ function CredentialsInfoCard(props) {
</div>
</CardHeader>

<CardBody>
<CardBody className="card-body-height">
<fieldset disabled={editMode ? "": "disabled"}>
<EmailField register={register} getValues={getValues} errors={errors} disable={disableEmail}/>
<PhoneField register={register} getValues={getValues} setValue={setValue} errors={errors} disable={disablePhone}/>
<EmailField register={register} getValues={getValues} errors={errors} disable={disableEmail} phoneValue={phoneValue} trigger={trigger}/>
<PhoneField register={register} getValues={getValues} setValue={setValue} errors={errors} disable={disablePhone} emailValue={emailValue} trigger={trigger}/>
</fieldset>
</CardBody>

<CardFooter>
{editMode ?
<React.Fragment>
<ButtonGroup>
<Button color="primary" type="submit">{t("Save")}</Button>
<Button color="outline-primary" type="button" onClick={(e) => (setEditMode(false), setOnUpdate(false))}>{t("Cancel")}</Button>
<Button color="primary" type="submit" disabled={disableSaveButton}>{t("Save")}</Button>
<Button
color="outline-primary"
type="button"
onClick={(e) => (
setEditMode(false),
setOnUpdate(false),
clearErrors(["email", "phone"])
)}
>
{t("Cancel")}
</Button>
</ButtonGroup>
</React.Fragment>
:
Expand All @@ -511,3 +525,4 @@ function CredentialsInfoCard(props) {

);
}

49 changes: 36 additions & 13 deletions src/modules/auth/credentials/FormFields.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import React, { useState } from 'react';
import React, {useState} from 'react';
import {
FormGroup, Input, Label,
Button, InputGroupAddon, InputGroup, FormFeedback, FormText
Button, InputGroupAddon, InputGroup,
FormFeedback, FormText
} from 'reactstrap';
import { useTranslation } from 'react-i18next';
import {useTranslation} from 'react-i18next';

// TODO: Validation on phone number
export function PhoneField(props) {
Expand All @@ -12,14 +13,21 @@ export function PhoneField(props) {
if (props.getValues("phone") == undefined) {
props.setValue("phone", "");
}

const validatePhone = (value) => {
if (!props.emailValue) {
return value !== "" || t("FormFields|Phone cannot be empty!");
} else {
return value !== "" || props.emailValue !== "" || t("FormFields|Phone cannot be empty!");
}
};


const reg = props.register(
"phone",
{
validate: {
emptyInput: value => (
props.getValues("email") === undefined ?
props.getValues("phone") !== "" :
props.getValues("phone") !== "" || props.getValues("email") !== "") || t("FormFields|Phone cannot be empty!"),
emptyInput: validatePhone,
regexValidation: value => (/^(?=.*[0-9])[+ 0-9]+$/).test(value) || value.length < 1 || t('FormFields|Invalid phone number format'),
lengthValidation: value => value.length >= 9 || value.length < 1 || t('FormFields|Phone number is too short')
},
Expand All @@ -39,7 +47,11 @@ export function PhoneField(props) {
maxLength="17"
disabled={disable}
invalid={props.errors.phone}
onChange={reg.onChange}
onChange={(e) => {
reg.onChange(e);
props.trigger("email");
props.trigger("phone");
}}
onBlur={reg.onBlur}
innerRef={reg.ref}
/>
Expand All @@ -51,14 +63,20 @@ export function PhoneField(props) {
export function EmailField(props) {
const { t } = useTranslation();
const disable = props.disable == undefined ? false : props.disable;

const validateEmail = (value) => {
if (!props.phoneValue) {
return value !== "" || t("FormFields|Email cannot be empty!");
} else {
return value !== "" || props.phoneValue !== "" || t("FormFields|Email cannot be empty!");
}
};

const reg = props.register(
"email", {
required: props.required ? t("FormFields|Email cannot be empty!") : false,
validate: {
emptyInput: value => (
props.getValues("phone") === undefined ?
props.getValues("email") !== "" :
props.getValues("phone") !== "" || props.getValues("email") !== "") || t("FormFields|Email cannot be empty!"),
emptyInput: validateEmail,
}
}
);
Expand All @@ -80,7 +98,11 @@ export function EmailField(props) {
autoComplete="email"
disabled={disable}
invalid={props.errors.email}
onChange={reg.onChange}
onChange={(e) => {
reg.onChange(e);
props.trigger("email");
props.trigger("phone");
}}
onBlur={reg.onBlur}
innerRef={reg.ref}
/>
Expand Down Expand Up @@ -240,3 +262,4 @@ export function PasswordLinkField(props) {
</FormGroup>
)
}

4 changes: 4 additions & 0 deletions src/modules/auth/credentials/credentials.scss
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,10 @@

.cred-info-card {
grid-area: i;
.card-body-height{
height: 250px;
}

}

.general-info-card {
Expand Down