Skip to content

Commit

Permalink
Chore: Convert apps/meteor/client/views/admin/settings/inputs folder (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
juliajforesti authored May 16, 2022
1 parent 75c7f4d commit 99a3651
Show file tree
Hide file tree
Showing 24 changed files with 389 additions and 155 deletions.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { Field } from '@rocket.chat/fuselage';
import { ServerMethods } from '@rocket.chat/ui-contexts';
import { ComponentMeta, ComponentStory } from '@storybook/react';
import React from 'react';

import type keys from '../../../../../packages/rocketchat-i18n/i18n/en.i18n.json';
import ActionSettingInput from './ActionSettingInput';

export default {
Expand All @@ -15,22 +17,22 @@ const Template: ComponentStory<typeof ActionSettingInput> = (args) => <ActionSet
export const Default = Template.bind({});
Default.args = {
_id: 'setting_id',
actionText: 'Action text',
value: 'methodName',
actionText: 'Action text' as keyof typeof keys,
value: 'methodName' as keyof ServerMethods,
};

export const Disabled = Template.bind({});
Disabled.args = {
_id: 'setting_id',
actionText: 'Action text',
value: 'methodName',
actionText: 'Action text' as keyof typeof keys,
value: 'methodName' as keyof ServerMethods,
disabled: true,
};

export const WithinChangedSection = Template.bind({});
WithinChangedSection.args = {
_id: 'setting_id',
actionText: 'Action text',
value: 'methodName',
actionText: 'Action text' as keyof typeof keys,
value: 'methodName' as keyof ServerMethods,
sectionChanged: true,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { Button, Field } from '@rocket.chat/fuselage';
import { useMethod, ServerMethods, useToastMessageDispatch, useTranslation } from '@rocket.chat/ui-contexts';
import React, { ReactElement } from 'react';

import type keys from '../../../../../packages/rocketchat-i18n/i18n/en.i18n.json';

type ActionSettingInputProps = {
_id: string;
actionText: keyof typeof keys;
value: keyof ServerMethods;
disabled: boolean;
sectionChanged: boolean;
};
function ActionSettingInput({ _id, actionText, value, disabled, sectionChanged }: ActionSettingInputProps): ReactElement {
const t = useTranslation();

const dispatchToastMessage = useToastMessageDispatch();
const actionMethod = useMethod(value);

const handleClick = async (): Promise<void> => {
try {
const data: { message: keyof typeof keys; params: string[] } = await actionMethod();

dispatchToastMessage({ type: 'success', message: t(data.message, ...data.params) });
} catch (error) {
dispatchToastMessage({ type: 'error', message: String(error) });
}
};

return (
<>
<Field.Row>
<Button data-qa-setting-id={_id} disabled={disabled || sectionChanged} primary onClick={handleClick}>
{t(actionText)}
</Button>
</Field.Row>
{sectionChanged && <Field.Hint>{t('Save_to_enable_this_action')}</Field.Hint>}
</>
);
}

export default ActionSettingInput;
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export const WithValue = Template.bind({});
WithValue.args = {
_id: 'setting_id',
label: 'Label',
value: { src: 'https://rocket.chat/images/logo.svg' },
value: { url: 'https://rocket.chat/images/logo.svg' },
};

export const WithFileConstraints = Template.bind({});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,49 +1,57 @@
import { Button, Field, Icon } from '@rocket.chat/fuselage';
import { useToastMessageDispatch, useMethod, useTranslation } from '@rocket.chat/ui-contexts';
import { Random } from 'meteor/random';
import React from 'react';
import React, { ChangeEventHandler, DragEvent, ReactElement } from 'react';

import './AssetSettingInput.css';

function AssetSettingInput({ _id, label, value = {}, asset, fileConstraints = {} }) {
type AssetSettingInputProps = {
_id: string;
label: string;
value?: { url: string };
asset?: any;
fileConstraints?: { extensions: string[] };
};

function AssetSettingInput({ _id, label, value, asset, fileConstraints }: AssetSettingInputProps): ReactElement {
const t = useTranslation();

const dispatchToastMessage = useToastMessageDispatch();
const setAsset = useMethod('setAsset');
const unsetAsset = useMethod('unsetAsset');

const handleUpload = (event) => {
event = event.originalEvent || event;
const isDataTransferEvent = <T,>(event: T): event is T & DragEvent<HTMLInputElement> =>
Boolean('dataTransfer' in event && (event as any).dataTransfer.files);

const handleUpload: ChangeEventHandler<HTMLInputElement> = (event): void => {
let { files } = event.target;

if (!files || files.length === 0) {
if (event.dataTransfer && event.dataTransfer.files) {
if (isDataTransferEvent(event)) {
files = event.dataTransfer.files;
} else {
files = [];
}
}

Object.values(files).forEach((blob) => {
Object.values(files ?? []).forEach((blob) => {
dispatchToastMessage({ type: 'info', message: t('Uploading_file') });
const reader = new FileReader();
reader.readAsBinaryString(blob);
reader.onloadend = async () => {
reader.onloadend = async (): Promise<void> => {
try {
await setAsset(reader.result, blob.type, asset);
dispatchToastMessage({ type: 'success', message: t('File_uploaded') });
} catch (error) {
dispatchToastMessage({ type: 'error', message: error });
dispatchToastMessage({ type: 'error', message: String(error) });
}
};
});
};

const handleDeleteButtonClick = async () => {
const handleDeleteButtonClick = async (): Promise<void> => {
try {
await unsetAsset(asset);
} catch (error) {
dispatchToastMessage({ type: 'error', message: error });
dispatchToastMessage({ type: 'error', message: String(error) });
}
};

Expand All @@ -54,15 +62,15 @@ function AssetSettingInput({ _id, label, value = {}, asset, fileConstraints = {}
</Field.Label>
<Field.Row>
<div className='settings-file-preview'>
{value.url ? (
{value?.url ? (
<div className='preview' style={{ backgroundImage: `url(${value.url}?_dc=${Random.id()})` }} />
) : (
<div className='preview no-file background-transparent-light secondary-font-color'>
<Icon name='upload' />
</div>
)}
<div className='action'>
{value.url ? (
{value?.url ? (
<Button onClick={handleDeleteButtonClick}>
<Icon name='trash' />
{t('Delete')}
Expand All @@ -73,7 +81,7 @@ function AssetSettingInput({ _id, label, value = {}, asset, fileConstraints = {}
<input
className='AssetSettingInput__input'
type='file'
accept={fileConstraints.extensions && fileConstraints.extensions.length && `.${fileConstraints.extensions.join(', .')}`}
accept={`.${fileConstraints?.extensions?.join(', .')}`}
onChange={handleUpload}
/>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,31 @@
import { Field, ToggleSwitch } from '@rocket.chat/fuselage';
import React from 'react';
import React, { ReactElement, SyntheticEvent } from 'react';

import ResetSettingButton from '../ResetSettingButton';

function BooleanSettingInput({ _id, label, disabled, readonly, value, hasResetButton, onChangeValue, onResetButtonClick }) {
const handleChange = (event) => {
type BooleanSettingInputProps = {
_id: string;
label: string;
disabled: boolean;
readonly: boolean;
value: boolean;
hasResetButton: boolean;
onChangeValue: (value: boolean) => void;
onResetButtonClick: () => void;
};
function BooleanSettingInput({
_id,
label,
disabled,
readonly,
value,
hasResetButton,
onChangeValue,
onResetButtonClick,
}: BooleanSettingInputProps): ReactElement {
const handleChange = (event: SyntheticEvent<HTMLInputElement>): void => {
const value = event.currentTarget.checked;
onChangeValue && onChangeValue(value);
onChangeValue?.(value);
};

return (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,29 @@
import { useMutableCallback } from '@rocket.chat/fuselage-hooks';
import React, { useEffect, useRef, useState } from 'react';
import React, { ReactElement, useEffect, useRef, useState } from 'react';

const defaultGutters = ['CodeMirror-linenumbers', 'CodeMirror-foldgutter'];

type CodeMirrorProps = {
id: string;
placeholder?: string;
disabled?: boolean;
autoComplete?: string | undefined;
lineNumbers?: boolean;
lineWrapping?: boolean;
mode?: string;
gutters?: string[];
foldGutter?: boolean;
matchBrackets?: boolean;
autoCloseBrackets?: boolean;
matchTags?: boolean;
showTrailingSpace?: boolean;
highlightSelectionMatches?: boolean;
readOnly: boolean;
value: string;
defaultValue?: string;
onChange: (value: string) => void;
};

function CodeMirror({
lineNumbers = true,
lineWrapping = true,
Expand All @@ -19,22 +40,24 @@ function CodeMirror({
defaultValue,
onChange,
...props
}) {
}: CodeMirrorProps): ReactElement {
const [value, setValue] = useState(valueProp || defaultValue);

const textAreaRef = useRef();
const editorRef = useRef();
const textAreaRef = useRef<HTMLTextAreaElement>(null);
const editorRef = useRef<HTMLFormElement | null>(null);
const handleChange = useMutableCallback(onChange);

useEffect(() => {
if (editorRef.current) {
return;
}

const setupCodeMirror = async () => {
const CodeMirror = await import('codemirror/lib/codemirror.js');
const setupCodeMirror = async (): Promise<void> => {
const jsPath = 'codemirror/lib/codemirror.js';
const CodeMirror = await import(jsPath);
await import('../../../../../app/ui/client/lib/codeMirror/codeMirror');
await import('codemirror/lib/codemirror.css');
const cssPath = 'codemirror/lib/codemirror.css';
await import(cssPath);

if (!textAreaRef.current) {
return;
Expand All @@ -54,7 +77,7 @@ function CodeMirror({
readOnly,
});

editorRef.current.on('change', (doc) => {
editorRef?.current?.on('change', (doc: HTMLFormElement) => {
const value = doc.getValue();
setValue(value);
handleChange(value);
Expand All @@ -63,7 +86,7 @@ function CodeMirror({

setupCodeMirror();

return () => {
return (): void => {
if (!editorRef.current) {
return;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,25 @@
import { Box, Button, Field, Flex } from '@rocket.chat/fuselage';
import { useToggle } from '@rocket.chat/fuselage-hooks';
import { useTranslation } from '@rocket.chat/ui-contexts';
import React from 'react';
import React, { ReactElement } from 'react';

import ResetSettingButton from '../ResetSettingButton';
import CodeMirror from './CodeMirror';

type CodeSettingInputProps = {
_id: string;
label: string;
value?: string;
code: string;
placeholder?: string;
readonly: boolean;
autocomplete: boolean;
disabled: boolean;
hasResetButton: boolean;
onChangeValue: (value: string) => void;
onResetButtonClick: () => void;
};

function CodeSettingInput({
_id,
label,
Expand All @@ -18,12 +32,12 @@ function CodeSettingInput({
hasResetButton,
onChangeValue,
onResetButtonClick,
}) {
}: CodeSettingInputProps): ReactElement {
const t = useTranslation();

const [fullScreen, toggleFullScreen] = useToggle(false);

const handleChange = (value) => {
const handleChange = (value: string): void => {
onChangeValue(value);
};

Expand Down Expand Up @@ -51,7 +65,7 @@ function CodeSettingInput({
onChange={handleChange}
/>
<div className='buttons'>
<Button primary onClick={() => toggleFullScreen()}>
<Button primary onClick={(): void => toggleFullScreen()}>
{fullScreen ? t('Exit_Full_Screen') : t('Full_Screen')}
</Button>
</div>
Expand Down
Loading

0 comments on commit 99a3651

Please sign in to comment.