Implement some inputs

alpha/blocketchat
Tasso Evangelista 7 years ago
parent a066b0dd40
commit 0ba137617e
  1. 104
      client/components/admin/settings/Field.js
  2. 18
      client/components/admin/settings/ResetSettingButton.js
  3. 43
      client/components/admin/settings/Section.js
  4. 68
      client/components/admin/settings/SettingField.js
  5. 207
      client/components/admin/settings/inputs.js
  6. 39
      client/components/admin/settings/inputs/BooleanSettingInput.js
  7. 42
      client/components/admin/settings/inputs/GenericSettingInput.js
  8. 55
      client/components/admin/settings/inputs/StringSettingInput.js
  9. 22
      package-lock.json
  10. 2
      package.json

@ -1,104 +0,0 @@
import React from 'react';
import { Button } from '../../basic/Button';
import { Icon } from '../../basic/Icon';
import { MarkdownText } from '../../basic/MarkdownText';
import { RawText } from '../../basic/RawText';
import { useTranslation } from '../../providers/TranslationProvider';
import { useFieldActions } from './EditingState';
function GenericSettingInput({ _id, value, placeholder, readonly, autocomplete, disabled, onChange }) {
const handleChange = (event) => {
const { value } = event.currentTarget;
onChange({ value });
};
return <input type='text' className='rc-input__element' name={_id} value={value} placeholder={placeholder}
disabled={disabled} readOnly={readonly} autoComplete={autocomplete === false ? 'off' : undefined}
onChange={handleChange} />;
}
function BooleanSettingInput({ _id, disabled, readonly, autocomplete, value, onChange }) {
const t = useTranslation();
const handleChange = (event) => {
const value = event.currentTarget.value === '1';
onChange({ value });
};
return <>
<label>
<input type='radio' name={_id} value='1' checked={value === true} disabled={disabled} readOnly={readonly}
autoComplete={autocomplete === false ? 'off' : undefined} onChange={handleChange} /> {t('True')}
</label>
<label>
<input type='radio' name={_id} value='0' checked={value === false} disabled={disabled} readOnly={readonly}
autoComplete={autocomplete === false ? 'off' : undefined} onChange={handleChange} /> {t('False')}
</label>
</>;
}
export function Field({ field }) {
const t = useTranslation();
const { update, reset, disabled } = useFieldActions(field);
const inputProps = { ...field, disabled, onChange: update };
const {
_id,
disableReset,
readonly,
type,
value,
packageValue,
blocked,
changed,
i18nLabel,
i18nDescription,
alert,
} = field;
const hasResetButton = !disableReset && !readonly && type !== 'asset' && value !== packageValue && !blocked;
const onResetButtonClick = () => {
reset();
};
return <div className={['input-line', 'double-col', changed && 'setting-changed'].filter(Boolean).join(' ')}>
<label className='setting-label' title={_id}>{(i18nLabel && t(i18nLabel)) || (_id || t(_id))}</label>
<div className='setting-field'>
{(type === 'boolean' && <BooleanSettingInput {...inputProps} />)
|| <GenericSettingInput {...inputProps} />}
{/* {setting.type === 'string' && <StringSettingInput setting={setting} />} */}
{/* {setting.type === 'relativeUrl' && <RelativeUrlSettingInput setting={setting} />} */}
{/* {setting.type === 'password' && <PasswordSettingInput setting={setting} />} */}
{/* {setting.type === 'int' && <IntSettingInput setting={setting} />} */}
{/* {setting.type === 'select' && <SelectSettingInput setting={setting} />} */}
{/* {setting.type === 'language' && <LanguageSettingInput setting={setting} />} */}
{/* {setting.type === 'color' && <ColorSettingInput setting={setting} />} */}
{/* {setting.type === 'font' && <FontSettingInput setting={setting} />} */}
{/* {setting.type === 'code' && <CodeSettingInput setting={setting} />} */}
{/* {setting.type === 'action' && <ActionSettingInput setting={setting} didSectionChange={didSectionChange} />} */}
{/* {setting.type === 'asset' && <AssetSettingInput setting={setting} />} */}
{/* {setting.type === 'roomPick' && <RoomPickSettingInput setting={setting} />} */}
{t.has(i18nDescription) && <div className='settings-description secondary-font-color'>
<MarkdownText>{t(i18nDescription)}</MarkdownText>
</div>}
{alert && <div className='settings-alert pending-color pending-background pending-border'>
<Icon icon='icon-attention' />
<RawText>{t(alert)}</RawText>
</div>}
</div>
{hasResetButton && <Button
aria-label={t('Reset')}
children={<Icon icon='icon-ccw' className='color-error-contrast' />}
className='reset-setting'
data-setting={_id}
cancel
onClick={onResetButtonClick}
/>}
</div>;
}

@ -0,0 +1,18 @@
import { Text } from '@rocket.chat/fuselage';
import React from 'react';
import { Icon } from '../../basic/Icon';
import { useTranslation } from '../../providers/TranslationProvider';
export function ResetSettingButton({ onClick }) {
const t = useTranslation();
return <Text
aria-label={t('Reset')}
dangerColor
title={t('Reset')}
onClick={onClick}
>
<Icon icon='icon-ccw' />
</Text>;
}

@ -1,9 +1,14 @@
import { Accordion, Button, Paragraph } from '@rocket.chat/fuselage';
import { Accordion, Button, FieldGroup, Paragraph } from '@rocket.chat/fuselage';
import React from 'react';
import styled from 'styled-components';
import { useTranslation } from '../../providers/TranslationProvider';
import { useBulkActions } from './EditingState';
import { Field } from './Field';
import { SettingField } from './SettingField';
const Wrapper = styled.div`
max-width: 543px;
`;
export function Section({ children, hasReset = true, help, section, solo }) {
const t = useTranslation();
@ -14,21 +19,23 @@ export function Section({ children, hasReset = true, help, section, solo }) {
};
return <Accordion.Item noncollapsible={solo || !section.name} title={section.name && t(section.name)}>
{help && <Paragraph hintColor>{help}</Paragraph>}
<div className='section-content border-component-color'>
{section.fields.map((field) => <Field key={field._id} field={field} />)}
{hasReset && <Button
children={t('Reset_section_settings')}
className='reset-group'
danger
data-section={section.name}
ghost
onClick={handleResetSectionClick}
/>}
{children}
</div>
<Wrapper>
{help && <Paragraph hintColor>{help}</Paragraph>}
<FieldGroup>
{section.fields.map((field) => <SettingField key={field._id} field={field} />)}
{hasReset && section.changed && <Button
children={t('Reset_section_settings')}
className='reset-group'
danger
data-section={section.name}
ghost
onClick={handleResetSectionClick}
/>}
{children}
</FieldGroup>
</Wrapper>
</Accordion.Item>;
}

@ -0,0 +1,68 @@
import {
Callout,
Field,
} from '@rocket.chat/fuselage';
import React from 'react';
import { MarkdownText } from '../../basic/MarkdownText';
import { RawText } from '../../basic/RawText';
import { useTranslation } from '../../providers/TranslationProvider';
import { useFieldActions } from './EditingState';
import { GenericSettingInput } from './inputs/GenericSettingInput';
import { BooleanSettingInput } from './inputs/BooleanSettingInput';
import { StringSettingInput } from './inputs/StringSettingInput';
export function SettingField({ field }) {
const t = useTranslation();
const { update, reset, disabled } = useFieldActions(field);
const {
_id,
disableReset,
readonly,
type,
value,
packageValue,
blocked,
i18nLabel,
i18nDescription,
alert,
} = field;
const label = (i18nLabel && t(i18nLabel)) || (_id || t(_id));
const hint = t.has(i18nDescription) && <MarkdownText>{t(i18nDescription)}</MarkdownText>;
const callout = alert && <RawText>{t(alert)}</RawText>;
const hasResetButton = !disableReset && !readonly && type !== 'asset' && value !== packageValue && !blocked;
const onResetButtonClick = () => {
reset();
};
const inputProps = {
...field,
label,
disabled,
onChange: update,
hasResetButton,
onResetButtonClick,
};
return <Field>
{(type === 'boolean' && <BooleanSettingInput {...inputProps} />)
|| (type === 'string' && <StringSettingInput {...inputProps} />)
// || (type === 'relativeUrl' && <RelativeUrlSettingInput {...inputProps} />)
// || (type === 'password' && <PasswordSettingInput {...inputProps} />)
// || (type === 'int' && <IntSettingInput {...inputProps} />)
// || (type === 'select' && <SelectSettingInput {...inputProps} />)
// || (type === 'language' && <LanguageSettingInput {...inputProps} />)
// || (type === 'color' && <ColorSettingInput {...inputProps} />)
// || (type === 'font' && <FontSettingInput {...inputProps} />)
// || (type === 'code' && <CodeSettingInput {...inputProps} />)
// || (type === 'action' && <ActionSettingInput {...inputProps} />)
// || (type === 'asset' && <AssetSettingInput {...inputProps} />)
// || (type === 'roomPick' && <RoomPickSettingInput {...inputProps} />)
|| <GenericSettingInput {...inputProps} />}
{hint && <Field.Hint>{hint}</Field.Hint>}
{callout && <Callout type='warning' title={callout} />}
</Field>;
}

@ -10,20 +10,19 @@ import { useReactiveValue } from '../../../hooks/useReactiveValue';
import { Button } from '../../basic/Button';
import { handleError } from '../../../../app/utils/client';
export function StringSettingInput({ setting, onUpdate }) {
const {
_id,
multiline,
value,
placeholder,
readonly,
autocomplete,
disabled,
} = setting;
export function StringSettingInput({
_id,
multiline,
value,
placeholder,
readonly,
autocomplete,
disabled,
onChange,
}) {
const handleChange = (event) => {
const { value } = event.currentTarget;
onUpdate({ value });
onChange({ value });
};
if (multiline) {
@ -53,74 +52,70 @@ export function StringSettingInput({ setting, onUpdate }) {
/>;
}
export function RelativeUrlSettingInput({ setting, onUpdate }) {
const {
_id,
value,
placeholder,
readonly,
autocomplete,
disabled,
} = setting;
export function RelativeUrlSettingInput({
_id,
value,
placeholder,
readonly,
autocomplete,
disabled,
onChange,
}) {
const handleChange = (event) => {
const { value } = event.currentTarget;
onUpdate({ value });
onChange({ value });
};
return <input type='url' className='rc-input__element' name={_id} value={Meteor.absoluteUrl(value)} placeholder={placeholder} disabled={disabled} readOnly={readonly} autoComplete={autocomplete === false ? 'off' : undefined} onChange={handleChange} />;
}
export function PasswordSettingInput({ setting, onUpdate }) {
const {
_id,
value,
placeholder,
readonly,
autocomplete,
disabled,
} = setting;
export function PasswordSettingInput({
_id,
value,
placeholder,
readonly,
autocomplete,
disabled,
onChange,
}) {
const handleChange = (event) => {
const { value } = event.currentTarget;
onUpdate({ value });
onChange({ value });
};
return <input type='password' className='rc-input__element' name={_id} value={value} placeholder={placeholder} disabled={disabled} readOnly={readonly} autoComplete={autocomplete === false ? 'off' : undefined} onChange={handleChange} />;
}
export function IntSettingInput({ setting, onUpdate }) {
const {
_id,
value,
placeholder,
readonly,
autocomplete,
disabled,
} = setting;
export function IntSettingInput({
_id,
value,
placeholder,
readonly,
autocomplete,
disabled,
onChange,
}) {
const handleChange = (event) => {
const value = parseInt(event.currentTarget.value, 10);
onUpdate({ value });
onChange({ value });
};
return <input type='number' className='rc-input__element' name={_id} value={value} placeholder={placeholder} disabled={disabled} readOnly={readonly} autoComplete={autocomplete === false ? 'off' : undefined} onChange={handleChange} />;
}
export function SelectSettingInput({ setting, onUpdate }) {
const {
_id,
value,
readonly,
values,
disabled,
} = setting;
export function SelectSettingInput({
_id,
value,
readonly,
values,
disabled,
onChange,
}) {
const t = useTranslation();
const handleChange = (event) => {
const { value } = event.currentTarget;
onUpdate({ value });
onChange({ value });
};
return <div className='rc-select'>
@ -133,14 +128,13 @@ export function SelectSettingInput({ setting, onUpdate }) {
</div>;
}
export function LanguageSettingInput({ setting, onUpdate }) {
const {
_id,
value,
readonly,
disabled,
} = setting;
export function LanguageSettingInput({
_id,
value,
readonly,
disabled,
onChange,
}) {
const languages = useReactiveValue(() => {
const languages = TAPi18n.getLanguages();
@ -159,7 +153,7 @@ export function LanguageSettingInput({ setting, onUpdate }) {
const handleChange = (event) => {
const { value } = event.currentTarget;
onUpdate({ value });
onChange({ value });
};
return <div className='rc-select'>
@ -172,26 +166,25 @@ export function LanguageSettingInput({ setting, onUpdate }) {
</div>;
}
export function ColorSettingInput({ setting, onUpdate }) {
const {
_id,
value,
editor,
allowedTypes,
autocomplete,
disabled,
} = setting;
export function ColorSettingInput({
_id,
value,
editor,
allowedTypes,
autocomplete,
disabled,
onChange,
}) {
const t = useTranslation();
const handleChange = (event) => {
const { value } = event.currentTarget;
onUpdate({ value });
onChange({ value });
};
const handleEditorTypeChange = (event) => {
const editor = event.currentTarget.value.trim();
onUpdate({ editor });
onChange({ editor });
};
return <>
@ -214,31 +207,28 @@ export function ColorSettingInput({ setting, onUpdate }) {
</>;
}
export function FontSettingInput({ setting, onUpdate }) {
const {
_id,
value,
placeholder,
readonly,
autocomplete,
disabled,
} = setting;
export function FontSettingInput({
_id,
value,
placeholder,
readonly,
autocomplete,
disabled,
onChange,
}) {
const handleChange = (event) => {
const { value } = event.currentTarget;
onUpdate({ value });
onChange({ value });
};
return <input type='text' className='rc-input__element' name={_id} value={value} placeholder={placeholder} disabled={disabled} readOnly={readonly} autoComplete={autocomplete === false ? 'off' : undefined} onChange={handleChange} />;
}
export function CodeSettingInput({ setting }) {
const {
_id,
i18nLabel,
disabled,
} = setting;
export function CodeSettingInput({
_id,
i18nLabel,
disabled,
}) {
const t = useTranslation();
return disabled
@ -254,13 +244,12 @@ export function CodeSettingInput({ setting }) {
</div>;
}
export function ActionSettingInput({ setting, didSectionChange }) {
const {
value,
actionText,
disabled,
} = setting;
export function ActionSettingInput({
value,
actionText,
disabled,
didSectionChange,
}) {
const t = useTranslation();
const handleClick = async () => {
@ -283,12 +272,10 @@ export function ActionSettingInput({ setting, didSectionChange }) {
: <Button primary disabled={disabled} onClick={handleClick}>{t(actionText)}</Button>;
}
export function AssetSettingInput({ setting }) {
const {
value,
fileConstraints,
} = setting;
export function AssetSettingInput({
value,
fileConstraints,
}) {
const t = useTranslation();
return value.url
? <div className='settings-file-preview'>
@ -309,11 +296,7 @@ export function AssetSettingInput({ setting }) {
</div>;
}
export function RoomPickSettingInput({ setting }) {
const {
_id,
} = setting;
export function RoomPickSettingInput({ _id }) {
// const collection = usePrivateSettingsCollection();
const [selectedRooms] = useState({});

@ -0,0 +1,39 @@
import {
Field,
Label,
ToggleSwitch,
} from '@rocket.chat/fuselage';
import React from 'react';
import { ResetSettingButton } from '../ResetSettingButton';
export function BooleanSettingInput({
_id,
label,
disabled,
readonly,
autocomplete,
value,
onChange,
hasResetButton,
onResetButtonClick,
}) {
const handleChange = (event) => {
const value = event.currentTarget.checked;
onChange({ value });
};
return <Field.Row>
<Label position='end' text={label} title={_id}>
<ToggleSwitch
value='true'
checked={value === true}
disabled={disabled}
readOnly={readonly}
autoComplete={autocomplete === false ? 'off' : undefined}
onChange={handleChange}
/>
</Label>
{hasResetButton && <ResetSettingButton onClick={onResetButtonClick} />}
</Field.Row>;
}

@ -0,0 +1,42 @@
import {
Field,
Label,
TextInput,
} from '@rocket.chat/fuselage';
import React from 'react';
import { ResetSettingButton } from '../ResetSettingButton';
export function GenericSettingInput({
_id,
label,
value,
placeholder,
readonly,
autocomplete,
disabled,
onChange,
hasResetButton,
onResetButtonClick,
}) {
const handleChange = (event) => {
const { value } = event.currentTarget;
onChange({ value });
};
return <>
<Field.Row>
<Label htmlFor={_id} text={label} title={_id} />
{hasResetButton && <ResetSettingButton onClick={onResetButtonClick} />}
</Field.Row>
<TextInput
id={_id}
value={value}
placeholder={placeholder}
disabled={disabled}
readOnly={readonly}
autoComplete={autocomplete === false ? 'off' : undefined}
onChange={handleChange}
/>
</>;
}

@ -0,0 +1,55 @@
import {
Field,
Label,
TextAreaInput,
TextInput,
} from '@rocket.chat/fuselage';
import React from 'react';
import { ResetSettingButton } from '../ResetSettingButton';
export function StringSettingInput({
_id,
label,
disabled,
multiline,
placeholder,
readonly,
autocomplete,
value,
onChange,
hasResetButton,
onResetButtonClick,
}) {
const handleChange = (event) => {
const { value } = event.currentTarget;
onChange({ value });
};
return <>
<Field.Row>
<Label htmlFor={_id} text={label} title={_id} />
{hasResetButton && <ResetSettingButton onClick={onResetButtonClick} />}
</Field.Row>
{multiline
? <TextAreaInput
id={_id}
rows={4}
value={value}
placeholder={placeholder}
disabled={disabled}
readOnly={readonly}
autoComplete={autocomplete === false ? 'off' : undefined}
onChange={handleChange}
/>
: <TextInput
id={_id}
value={value}
placeholder={placeholder}
disabled={disabled}
readOnly={readonly}
autoComplete={autocomplete === false ? 'off' : undefined}
onChange={handleChange}
/> }
</>;
}

22
package-lock.json generated

@ -2370,19 +2370,19 @@
}
},
"@rocket.chat/fuselage": {
"version": "0.2.0-alpha.13",
"resolved": "https://registry.npmjs.org/@rocket.chat/fuselage/-/fuselage-0.2.0-alpha.13.tgz",
"integrity": "sha512-sWdUNfUBwCUetNPGPP1k2BJdLYvypfwQ+k3aiapHz+MFw4ugtTgwHG7ulW5ygbGrijGHv6pDE6+U68FcCxzZOg==",
"version": "0.2.0-dev.46",
"resolved": "https://registry.npmjs.org/@rocket.chat/fuselage/-/fuselage-0.2.0-dev.46.tgz",
"integrity": "sha512-XxIG+hRUuEi9iL4yKfpXHpDrgiB+hrJ00faErDjgjF59YVjXo+pODVcqNJTl4UpOvdLitRpqAPm17ZIppV+msA==",
"requires": {
"@rocket.chat/fuselage-tokens": "^0.2.0-alpha.13",
"@rocket.chat/icons": "^0.2.0-alpha.13",
"@rocket.chat/fuselage-tokens": "^0.2.0-dev.46+56baa80",
"@rocket.chat/icons": "^0.2.0-dev.46+56baa80",
"invariant": "^2.2.4"
},
"dependencies": {
"@rocket.chat/icons": {
"version": "0.2.0-alpha.13",
"resolved": "https://registry.npmjs.org/@rocket.chat/icons/-/icons-0.2.0-alpha.13.tgz",
"integrity": "sha512-woGEqtzyU/j+IQLgg7Cj6N7phTifUyC3TAbFdU/3XhzChRDbC7kxx8QjHAQgsLpri9JZWtm24YLEYJNpdGFQ4Q=="
"version": "0.2.0-dev.46",
"resolved": "https://registry.npmjs.org/@rocket.chat/icons/-/icons-0.2.0-dev.46.tgz",
"integrity": "sha512-a04ggaeXxDErOWN1j61A9lRM0tE2yg5P/TBr0QAHQle07H/1g9ZNZlHWV/BLEnUimDmts/yvHo5l1ofSyVnsEQ=="
}
}
},
@ -2392,9 +2392,9 @@
"integrity": "sha512-LdLpDVkNhKRxXzNrtMy+Lqyo34+BVeBFYf93gLTSCSauNwtLouNiOQXJphHz2CZKsE+FJ3M1FeXUTEJ2QOZpzg=="
},
"@rocket.chat/fuselage-tokens": {
"version": "0.2.0-alpha.13",
"resolved": "https://registry.npmjs.org/@rocket.chat/fuselage-tokens/-/fuselage-tokens-0.2.0-alpha.13.tgz",
"integrity": "sha512-0Vagl3+i6aR5FA7uqCsf5am+M+cB4EMCZGs+Lcw5PAfKl7We3TjpZBUIpAJbNsiG/OsmRSSpL0SiaSfuPF7/Bw=="
"version": "0.2.0-dev.46",
"resolved": "https://registry.npmjs.org/@rocket.chat/fuselage-tokens/-/fuselage-tokens-0.2.0-dev.46.tgz",
"integrity": "sha512-lh4L/Ju5RCW+LzIdQwAFeKd5eKzsiZyOLFJYx8WuA7No50/7eJO4Kcz+OJPHG+PvuVFdTbF557QhWH1ZvuazHQ=="
},
"@rocket.chat/icons": {
"version": "0.2.0-alpha.9",

@ -151,7 +151,7 @@
"@google-cloud/storage": "^2.3.1",
"@google-cloud/vision": "^0.23.0",
"@rocket.chat/apps-engine": "^1.7.0",
"@rocket.chat/fuselage": "^0.2.0-alpha.13",
"@rocket.chat/fuselage": "^0.2.0-dev.46",
"@rocket.chat/fuselage-hooks": "^0.2.0-dev.32",
"@rocket.chat/icons": "^0.2.0-alpha.9",
"@slack/client": "^4.8.0",

Loading…
Cancel
Save