1
0
mirror of https://github.com/LaCasemate/fab-manager.git synced 2025-01-18 07:52:23 +01:00

(ui) disabled fields mapped from the sso

This commit is contained in:
Sylvain 2022-05-09 10:12:27 +02:00
parent b9b8150e28
commit 55e76e1523
6 changed files with 66 additions and 19 deletions

View File

@ -93,7 +93,7 @@ export const FabTextEditor: React.ForwardRefRenderFunction<FabTextEditorRef, Fab
<>
{label && <label onClick={focusEditor} className="fab-textEditor-label">{label}</label>}
<div className="fab-textEditor">
<MenuBar editor={editor} paragraphTools={paragraphTools} video={video} image={image} />
<MenuBar editor={editor} paragraphTools={paragraphTools} video={video} image={image} disabled={readOnly} />
<EditorContent editor={editor} />
<div className="fab-textEditor-character-count">
{editor?.storage.characterCount.characters()} / {limit}

View File

@ -9,12 +9,13 @@ interface MenuBarProps {
paragraphTools?: boolean,
video?: boolean,
image?: boolean,
disabled?: boolean,
}
/**
* This component is the menu bar for the WYSIWYG text editor
*/
export const MenuBar: React.FC<MenuBarProps> = ({ editor, paragraphTools, video, image }) => {
export const MenuBar: React.FC<MenuBarProps> = ({ editor, paragraphTools, video, image, disabled = false }) => {
const { t } = useTranslation('shared');
const [submenu, setSubmenu] = useState('');
@ -140,12 +141,13 @@ export const MenuBar: React.FC<MenuBarProps> = ({ editor, paragraphTools, video,
return (
<>
<div className='fab-textEditor-menu'>
<div className={`fab-textEditor-menu ${disabled ? 'fab-textEditor-menu--disabled' : ''}`}>
{ paragraphTools &&
(<>
<button
type='button'
onClick={() => editor.chain().focus().toggleHeading({ level: 3 }).run()}
disabled={disabled}
className={editor.isActive('heading', { level: 3 }) ? 'is-active' : ''}
>
<TextAa size={24} />
@ -153,6 +155,7 @@ export const MenuBar: React.FC<MenuBarProps> = ({ editor, paragraphTools, video,
<button
type='button'
onClick={() => editor.chain().focus().toggleBulletList().run()}
disabled={disabled}
className={editor.isActive('bulletList') ? 'is-active' : ''}
>
<ListBullets size={24} />
@ -160,6 +163,7 @@ export const MenuBar: React.FC<MenuBarProps> = ({ editor, paragraphTools, video,
<button
type='button'
onClick={() => editor.chain().focus().toggleBlockquote().run()}
disabled={disabled}
className={editor.isActive('blockquote') ? 'is-active' : ''}
>
<Quotes size={24} />
@ -170,6 +174,7 @@ export const MenuBar: React.FC<MenuBarProps> = ({ editor, paragraphTools, video,
<button
type='button'
onClick={() => editor.chain().focus().toggleBold().run()}
disabled={disabled}
className={editor.isActive('bold') ? 'is-active' : ''}
>
<TextBolder size={24} />
@ -177,6 +182,7 @@ export const MenuBar: React.FC<MenuBarProps> = ({ editor, paragraphTools, video,
<button
type='button'
onClick={() => editor.chain().focus().toggleItalic().run()}
disabled={disabled}
className={editor.isActive('italic') ? 'is-active' : ''}
>
<TextItalic size={24} />
@ -184,6 +190,7 @@ export const MenuBar: React.FC<MenuBarProps> = ({ editor, paragraphTools, video,
<button
type='button'
onClick={() => editor.chain().focus().toggleUnderline().run()}
disabled={disabled}
className={editor.isActive('underline') ? 'is-active' : ''}
>
<TextUnderline size={24} />
@ -191,6 +198,7 @@ export const MenuBar: React.FC<MenuBarProps> = ({ editor, paragraphTools, video,
<button
type='button'
onClick={() => toggleSubmenu('link')}
disabled={disabled}
className={`ignore-onclickoutside ${editor.isActive('link') ? 'is-active' : ''}`}
>
<LinkSimpleHorizontal size={24} />
@ -200,6 +208,7 @@ export const MenuBar: React.FC<MenuBarProps> = ({ editor, paragraphTools, video,
(<>
<button
type='button'
disabled={disabled}
onClick={() => toggleSubmenu('video')}
>
<VideoCamera size={24} />
@ -210,6 +219,7 @@ export const MenuBar: React.FC<MenuBarProps> = ({ editor, paragraphTools, video,
(<>
<button
type='button'
disabled={disabled}
onClick={() => toggleSubmenu('image')}
>
<Image size={24} />

View File

@ -12,10 +12,11 @@ interface EditSocialsProps<TFieldValues> {
register: UseFormRegister<TFieldValues>,
setValue: UseFormSetValue<User>,
networks: SocialNetwork[],
formState: FormState<TFieldValues>
formState: FormState<TFieldValues>,
disabled: boolean|((id: string) => boolean),
}
export const EditSocials = <TFieldValues extends FieldValues>({ register, setValue, networks, formState }: EditSocialsProps<TFieldValues>) => {
export const EditSocials = <TFieldValues extends FieldValues>({ register, setValue, networks, formState, disabled }: EditSocialsProps<TFieldValues>) => {
const { t } = useTranslation('shared');
// regular expression to validate the the input fields
const urlRegex = /^(https?:\/\/)([\da-z.-]+)\.([-a-z\d.]{2,30})([/\w .-]*)*\/?$/;
@ -66,6 +67,7 @@ export const EditSocials = <TFieldValues extends FieldValues>({ register, setVal
formState={formState}
defaultValue={network.url}
label={network.name}
disabled={disabled}
placeholder={t('app.shared.text_editor.url_placeholder')}
icon={<img src={`${Icons}#${network.name}`}></img>}
addOn={<Trash size={16} />}

View File

@ -1,4 +1,4 @@
import React from 'react';
import React, { useEffect } from 'react';
import { UseFormRegister } from 'react-hook-form';
import { FieldValues } from 'react-hook-form/dist/types/fields';
import { FieldPath } from 'react-hook-form/dist/types/path';
@ -6,26 +6,39 @@ import { useTranslation } from 'react-i18next';
interface GenderInputProps<TFieldValues> {
register: UseFormRegister<TFieldValues>,
disabled?: boolean|((id: string) => boolean),
}
/**
* Input component to set the gender for the user
*/
export const GenderInput = <TFieldValues extends FieldValues>({ register }: GenderInputProps<TFieldValues>) => {
export const GenderInput = <TFieldValues extends FieldValues>({ register, disabled = false }: GenderInputProps<TFieldValues>) => {
const { t } = useTranslation('shared');
const [isDisabled, setIsDisabled] = React.useState<boolean>(false);
useEffect(() => {
if (typeof disabled === 'function') {
setIsDisabled(disabled('statistic_profile_attributes.gender'));
} else {
setIsDisabled(disabled);
}
}, [disabled]);
return (
<div className="gender-input">
<label>
<p>{t('app.shared.gender_input.man')}</p>
<input type="radio"
value="true"
disabled={isDisabled}
{...register('statistic_profile_attributes.gender' as FieldPath<TFieldValues>)} />
</label>
<label>
<p>{t('app.shared.gender_input.woman')}</p>
<input type="radio"
value="false"
disabled={isDisabled}
{...register('statistic_profile_attributes.gender' as FieldPath<TFieldValues>)} />
</label>
</div>

View File

@ -1,4 +1,4 @@
import React from 'react';
import React, { useEffect, useState } from 'react';
import { react2angular } from 'react2angular';
import { SubmitHandler, useForm, useWatch } from 'react-hook-form';
import { isNil as _isNil } from 'lodash';
@ -17,6 +17,7 @@ import { AvatarInput } from './avatar-input';
import { FabButton } from '../base/fab-button';
import { EditSocials } from '../socials/edit-socials';
import UserLib from '../../lib/user';
import AuthProviderAPI from '../../api/auth-provider';
declare const Application: IApplication;
@ -39,7 +40,14 @@ export const UserProfileForm: React.FC<UserProfileFormProps> = ({ action, size,
const { handleSubmit, register, control, formState, setValue } = useForm<User>({ defaultValues: { ...user } });
const output = useWatch<User>({ control });
const [isOrganization, setIsOrganization] = React.useState<boolean>(!_isNil(user.invoicing_profile_attributes.organization_attributes));
const [isOrganization, setIsOrganization] = useState<boolean>(!_isNil(user.invoicing_profile_attributes.organization_attributes));
const [isLocalDatabaseProvider, setIsLocalDatabaseProvider] = useState<boolean>(false);
useEffect(() => {
AuthProviderAPI.active().then(data => {
setIsLocalDatabaseProvider(data.providable_type === 'DatabaseProvider');
});
});
/**
* Callback triggered when the form is submitted: process with the user creation or update.
@ -54,7 +62,10 @@ export const UserProfileForm: React.FC<UserProfileFormProps> = ({ action, size,
* Check if the given field path should be disabled because it's mapped to the SSO API.
*/
const isDisabled = function (id: string) {
// TODO: check if AuthenticationProvider is not LocalDatabase
if (isLocalDatabaseProvider) {
return false;
}
return user.mapped_from_sso?.includes(UserFieldMapping[id]);
};
@ -72,7 +83,7 @@ export const UserProfileForm: React.FC<UserProfileFormProps> = ({ action, size,
<div className="fields-group">
<div className="personnal-data">
<h4>{t('app.shared.user_profile_form.personal_data')}</h4>
<GenderInput register={register} />
<GenderInput register={register} disabled={isDisabled} />
<div className="names">
<FormInput id="profile_attributes.last_name"
register={register}
@ -129,14 +140,15 @@ export const UserProfileForm: React.FC<UserProfileFormProps> = ({ action, size,
disabled={isDisabled}
formState={formState}
label={t('app.shared.user_profile_form.email_address')} />
{/* TODO: no password change if sso */}
{action === 'update' && <ChangePassword register={register}
onError={onError}
currentFormPassword={output.password}
formState={formState} />}
{action === 'create' && <PasswordInput register={register}
currentFormPassword={output.password}
formState={formState} />}
{isLocalDatabaseProvider && <div className="password">
{ action === 'update' && <ChangePassword register={register}
onError={onError}
currentFormPassword={output.password}
formState={formState} />}
{action === 'create' && <PasswordInput register={register}
currentFormPassword={output.password}
formState={formState} />}
</div>}
</div>
<div className="organization-data">
<h4>{t('app.shared.user_profile_form.organization_data')}</h4>
@ -145,6 +157,7 @@ export const UserProfileForm: React.FC<UserProfileFormProps> = ({ action, size,
label={t('app.shared.user_profile_form.declare_organization')}
tooltip={t('app.shared.user_profile_form.declare_organization_help')}
defaultValue={isOrganization}
disabled={isDisabled('invoicing_profile_attributes.organization_attributes.name')}
onChange={setIsOrganization} />
{isOrganization && <div className="organization-fields">
<FormInput id="invoicing_profile_attributes.organization_attributes.id"
@ -200,6 +213,7 @@ export const UserProfileForm: React.FC<UserProfileFormProps> = ({ action, size,
<div className='account-networks'>
<h4>{t('app.shared.user_profile_form.account_networks')}</h4>
<EditSocials register={register}
disabled={isDisabled}
networks={userNetworks}
setValue={setValue}
formState={formState} />

View File

@ -45,6 +45,14 @@
background-color: var(--gray-soft-dark);
border-radius: 1px;
}
&--disabled {
opacity: 0.5;
button:hover {
background-color: transparent;
}
}
}
// tiptap class for the editor