R: Decouple setters from onChange events
Some checks are pending
Frontend CI / build (22.x) (push) Waiting to run

This commit is contained in:
Ivan 2024-11-21 00:26:16 +03:00
parent 1d1727c43f
commit 72634e80fa
28 changed files with 138 additions and 131 deletions

View File

@ -11,11 +11,11 @@ interface SelectMultiGrammemeProps
extends Omit<SelectMultiProps<IGrammemeOption>, 'value' | 'onChange'>, extends Omit<SelectMultiProps<IGrammemeOption>, 'value' | 'onChange'>,
CProps.Styling { CProps.Styling {
value: IGrammemeOption[]; value: IGrammemeOption[];
setValue: React.Dispatch<React.SetStateAction<IGrammemeOption[]>>; onChangeValue: (newValue: IGrammemeOption[]) => void;
placeholder?: string; placeholder?: string;
} }
function SelectMultiGrammeme({ value, setValue, ...restProps }: SelectMultiGrammemeProps) { function SelectMultiGrammeme({ value, onChangeValue, ...restProps }: SelectMultiGrammemeProps) {
const [options, setOptions] = useState<IGrammemeOption[]>([]); const [options, setOptions] = useState<IGrammemeOption[]>([]);
useEffect(() => { useEffect(() => {
@ -29,7 +29,7 @@ function SelectMultiGrammeme({ value, setValue, ...restProps }: SelectMultiGramm
<SelectMulti <SelectMulti
options={options} options={options}
value={value} value={value}
onChange={newValue => setValue([...newValue].sort(compareGrammemeOptions))} onChange={newValue => onChangeValue([...newValue].sort(compareGrammemeOptions))}
{...restProps} {...restProps}
/> />
); );

View File

@ -157,7 +157,7 @@ function DataTable<TData extends RowData>({
enableRowSelection={enableRowSelection} enableRowSelection={enableRowSelection}
enableSorting={enableSorting} enableSorting={enableSorting}
headPosition={headPosition} headPosition={headPosition}
setLastSelected={setLastSelected} resetLastSelected={() => setLastSelected(undefined)}
/> />
) : null} ) : null}
@ -168,7 +168,7 @@ function DataTable<TData extends RowData>({
conditionalRowStyles={conditionalRowStyles} conditionalRowStyles={conditionalRowStyles}
enableRowSelection={enableRowSelection} enableRowSelection={enableRowSelection}
lastSelected={lastSelected} lastSelected={lastSelected}
setLastSelected={setLastSelected} onChangeLastSelected={setLastSelected}
onRowClicked={onRowClicked} onRowClicked={onRowClicked}
onRowDoubleClicked={onRowDoubleClicked} onRowDoubleClicked={onRowDoubleClicked}
/> />

View File

@ -4,12 +4,12 @@ import CheckboxTristate from '@/components/ui/CheckboxTristate';
interface SelectAllProps<TData> { interface SelectAllProps<TData> {
table: Table<TData>; table: Table<TData>;
setLastSelected: React.Dispatch<React.SetStateAction<string | undefined>>; resetLastSelected: () => void;
} }
function SelectAll<TData>({ table, setLastSelected }: SelectAllProps<TData>) { function SelectAll<TData>({ table, resetLastSelected }: SelectAllProps<TData>) {
function handleChange(value: boolean | null) { function handleChange(value: boolean | null) {
setLastSelected(undefined); resetLastSelected();
table.toggleAllPageRowsSelected(value !== false); table.toggleAllPageRowsSelected(value !== false);
} }

View File

@ -4,12 +4,12 @@ import Checkbox from '@/components/ui/Checkbox';
interface SelectRowProps<TData> { interface SelectRowProps<TData> {
row: Row<TData>; row: Row<TData>;
setLastSelected: React.Dispatch<React.SetStateAction<string | undefined>>; onChangeLastSelected: (newValue: string | undefined) => void;
} }
function SelectRow<TData>({ row, setLastSelected }: SelectRowProps<TData>) { function SelectRow<TData>({ row, onChangeLastSelected }: SelectRowProps<TData>) {
function handleChange(value: boolean) { function handleChange(value: boolean) {
setLastSelected(row.id); onChangeLastSelected(row.id);
row.toggleSelected(value); row.toggleSelected(value);
} }

View File

@ -14,7 +14,7 @@ interface TableBodyProps<TData> {
conditionalRowStyles?: IConditionalStyle<TData>[]; conditionalRowStyles?: IConditionalStyle<TData>[];
lastSelected: string | undefined; lastSelected: string | undefined;
setLastSelected: React.Dispatch<React.SetStateAction<string | undefined>>; onChangeLastSelected: (newValue: string | undefined) => void;
onRowClicked?: (rowData: TData, event: CProps.EventMouse) => void; onRowClicked?: (rowData: TData, event: CProps.EventMouse) => void;
onRowDoubleClicked?: (rowData: TData, event: CProps.EventMouse) => void; onRowDoubleClicked?: (rowData: TData, event: CProps.EventMouse) => void;
@ -27,7 +27,7 @@ function TableBody<TData>({
enableRowSelection, enableRowSelection,
conditionalRowStyles, conditionalRowStyles,
lastSelected, lastSelected,
setLastSelected, onChangeLastSelected,
onRowClicked, onRowClicked,
onRowDoubleClicked onRowDoubleClicked
}: TableBodyProps<TData>) { }: TableBodyProps<TData>) {
@ -49,9 +49,9 @@ function TableBody<TData>({
newSelection[row.id] = !target.getIsSelected(); newSelection[row.id] = !target.getIsSelected();
}); });
table.setRowSelection(prev => ({ ...prev, ...newSelection })); table.setRowSelection(prev => ({ ...prev, ...newSelection }));
setLastSelected(undefined); onChangeLastSelected(undefined);
} else { } else {
setLastSelected(target.id); onChangeLastSelected(target.id);
target.toggleSelected(!target.getIsSelected()); target.toggleSelected(!target.getIsSelected());
} }
} }
@ -83,7 +83,7 @@ function TableBody<TData>({
> >
{enableRowSelection ? ( {enableRowSelection ? (
<td key={`select-${row.id}`} className='pl-3 pr-1 align-middle border-y'> <td key={`select-${row.id}`} className='pl-3 pr-1 align-middle border-y'>
<SelectRow row={row} setLastSelected={setLastSelected} /> <SelectRow row={row} onChangeLastSelected={onChangeLastSelected} />
</td> </td>
) : null} ) : null}
{row.getVisibleCells().map((cell: Cell<TData, unknown>) => ( {row.getVisibleCells().map((cell: Cell<TData, unknown>) => (

View File

@ -8,7 +8,7 @@ interface TableHeaderProps<TData> {
headPosition?: string; headPosition?: string;
enableRowSelection?: boolean; enableRowSelection?: boolean;
enableSorting?: boolean; enableSorting?: boolean;
setLastSelected: React.Dispatch<React.SetStateAction<string | undefined>>; resetLastSelected: () => void;
} }
function TableHeader<TData>({ function TableHeader<TData>({
@ -16,7 +16,7 @@ function TableHeader<TData>({
headPosition, headPosition,
enableRowSelection, enableRowSelection,
enableSorting, enableSorting,
setLastSelected resetLastSelected
}: TableHeaderProps<TData>) { }: TableHeaderProps<TData>) {
return ( return (
<thead <thead
@ -30,7 +30,7 @@ function TableHeader<TData>({
<tr key={headerGroup.id}> <tr key={headerGroup.id}>
{enableRowSelection ? ( {enableRowSelection ? (
<th className='pl-3 pr-1 align-middle'> <th className='pl-3 pr-1 align-middle'>
<SelectAll table={table} setLastSelected={setLastSelected} /> <SelectAll table={table} resetLastSelected={resetLastSelected} />
</th> </th>
) : null} ) : null}
{headerGroup.headers.map((header: Header<TData, unknown>) => ( {headerGroup.headers.map((header: Header<TData, unknown>) => (

View File

@ -103,15 +103,15 @@ function DlgCreateOperation({ hideWindow, oss, onCreate, initialInputs }: DlgCre
<TabInputOperation <TabInputOperation
oss={oss} oss={oss}
alias={alias} alias={alias}
setAlias={setAlias} onChangeAlias={setAlias}
comment={comment} comment={comment}
setComment={setComment} onChangeComment={setComment}
title={title} title={title}
setTitle={setTitle} onChangeTitle={setTitle}
attachedID={attachedID} attachedID={attachedID}
setAttachedID={setAttachedID} onChangeAttachedID={setAttachedID}
createSchema={createSchema} createSchema={createSchema}
setCreateSchema={setCreateSchema} onChangeCreateSchema={setCreateSchema}
/> />
</TabPanel> </TabPanel>
), ),
@ -124,11 +124,11 @@ function DlgCreateOperation({ hideWindow, oss, onCreate, initialInputs }: DlgCre
<TabSynthesisOperation <TabSynthesisOperation
oss={oss} oss={oss}
alias={alias} alias={alias}
setAlias={setAlias} onChangeAlias={setAlias}
comment={comment} comment={comment}
setComment={setComment} onChangeComment={setComment}
title={title} title={title}
setTitle={setTitle} onChangeTitle={setTitle}
inputs={inputs} inputs={inputs}
setInputs={setInputs} setInputs={setInputs}
/> />

View File

@ -18,29 +18,29 @@ import { sortItemsForOSS } from '@/models/ossAPI';
interface TabInputOperationProps { interface TabInputOperationProps {
oss: IOperationSchema; oss: IOperationSchema;
alias: string; alias: string;
setAlias: React.Dispatch<React.SetStateAction<string>>; onChangeAlias: (newValue: string) => void;
title: string; title: string;
setTitle: React.Dispatch<React.SetStateAction<string>>; onChangeTitle: (newValue: string) => void;
comment: string; comment: string;
setComment: React.Dispatch<React.SetStateAction<string>>; onChangeComment: (newValue: string) => void;
attachedID: LibraryItemID | undefined; attachedID: LibraryItemID | undefined;
setAttachedID: React.Dispatch<React.SetStateAction<LibraryItemID | undefined>>; onChangeAttachedID: (newValue: LibraryItemID | undefined) => void;
createSchema: boolean; createSchema: boolean;
setCreateSchema: React.Dispatch<React.SetStateAction<boolean>>; onChangeCreateSchema: (newValue: boolean) => void;
} }
function TabInputOperation({ function TabInputOperation({
oss, oss,
alias, alias,
setAlias, onChangeAlias,
title, title,
setTitle, onChangeTitle,
comment, comment,
setComment, onChangeComment,
attachedID, attachedID,
setAttachedID, onChangeAttachedID,
createSchema, createSchema,
setCreateSchema onChangeCreateSchema
}: TabInputOperationProps) { }: TabInputOperationProps) {
const baseFilter = useCallback((item: ILibraryItem) => !oss.schemas.includes(item.id), [oss]); const baseFilter = useCallback((item: ILibraryItem) => !oss.schemas.includes(item.id), [oss]);
const library = useLibrary(); const library = useLibrary();
@ -48,9 +48,9 @@ function TabInputOperation({
useEffect(() => { useEffect(() => {
if (createSchema) { if (createSchema) {
setAttachedID(undefined); onChangeAttachedID(undefined);
} }
}, [createSchema, setAttachedID]); }, [createSchema, onChangeAttachedID]);
return ( return (
<AnimateFade className='cc-column'> <AnimateFade className='cc-column'>
@ -58,7 +58,7 @@ function TabInputOperation({
id='operation_title' id='operation_title'
label='Полное название' label='Полное название'
value={title} value={title}
onChange={event => setTitle(event.target.value)} onChange={event => onChangeTitle(event.target.value)}
disabled={attachedID !== undefined} disabled={attachedID !== undefined}
/> />
<div className='flex gap-6'> <div className='flex gap-6'>
@ -67,7 +67,7 @@ function TabInputOperation({
label='Сокращение' label='Сокращение'
className='w-[16rem]' className='w-[16rem]'
value={alias} value={alias}
onChange={event => setAlias(event.target.value)} onChange={event => onChangeAlias(event.target.value)}
disabled={attachedID !== undefined} disabled={attachedID !== undefined}
/> />
@ -77,7 +77,7 @@ function TabInputOperation({
noResize noResize
rows={3} rows={3}
value={comment} value={comment}
onChange={event => setComment(event.target.value)} onChange={event => onChangeComment(event.target.value)}
disabled={attachedID !== undefined} disabled={attachedID !== undefined}
/> />
</div> </div>
@ -90,13 +90,13 @@ function TabInputOperation({
noHover noHover
noPadding noPadding
icon={<IconReset size='1.25rem' className='icon-primary' />} icon={<IconReset size='1.25rem' className='icon-primary' />}
onClick={() => setAttachedID(undefined)} onClick={() => onChangeAttachedID(undefined)}
disabled={attachedID == undefined} disabled={attachedID == undefined}
/> />
</div> </div>
<Checkbox <Checkbox
value={createSchema} value={createSchema}
setValue={setCreateSchema} setValue={onChangeCreateSchema}
label='Создать новую схему' label='Создать новую схему'
titleHtml='Создать пустую схему для загрузки' titleHtml='Создать пустую схему для загрузки'
/> />
@ -106,7 +106,7 @@ function TabInputOperation({
items={sortedItems} items={sortedItems}
value={attachedID} value={attachedID}
itemType={LibraryItemType.RSFORM} itemType={LibraryItemType.RSFORM}
onSelectValue={setAttachedID} onSelectValue={onChangeAttachedID}
rows={8} rows={8}
baseFilter={baseFilter} baseFilter={baseFilter}
/> />

View File

@ -10,11 +10,11 @@ import PickMultiOperation from '../../components/select/PickMultiOperation';
interface TabSynthesisOperationProps { interface TabSynthesisOperationProps {
oss: IOperationSchema; oss: IOperationSchema;
alias: string; alias: string;
setAlias: React.Dispatch<React.SetStateAction<string>>; onChangeAlias: (newValue: string) => void;
title: string; title: string;
setTitle: React.Dispatch<React.SetStateAction<string>>; onChangeTitle: (newValue: string) => void;
comment: string; comment: string;
setComment: React.Dispatch<React.SetStateAction<string>>; onChangeComment: (newValue: string) => void;
inputs: OperationID[]; inputs: OperationID[];
setInputs: React.Dispatch<React.SetStateAction<OperationID[]>>; setInputs: React.Dispatch<React.SetStateAction<OperationID[]>>;
} }
@ -22,11 +22,11 @@ interface TabSynthesisOperationProps {
function TabSynthesisOperation({ function TabSynthesisOperation({
oss, oss,
alias, alias,
setAlias, onChangeAlias,
title, title,
setTitle, onChangeTitle,
comment, comment,
setComment, onChangeComment,
inputs, inputs,
setInputs setInputs
}: TabSynthesisOperationProps) { }: TabSynthesisOperationProps) {
@ -36,7 +36,7 @@ function TabSynthesisOperation({
id='operation_title' id='operation_title'
label='Полное название' label='Полное название'
value={title} value={title}
onChange={event => setTitle(event.target.value)} onChange={event => onChangeTitle(event.target.value)}
/> />
<div className='flex gap-6'> <div className='flex gap-6'>
<TextInput <TextInput
@ -44,7 +44,7 @@ function TabSynthesisOperation({
label='Сокращение' label='Сокращение'
className='w-[16rem]' className='w-[16rem]'
value={alias} value={alias}
onChange={event => setAlias(event.target.value)} onChange={event => onChangeAlias(event.target.value)}
/> />
<TextArea <TextArea
@ -53,7 +53,7 @@ function TabSynthesisOperation({
noResize noResize
rows={3} rows={3}
value={comment} value={comment}
onChange={event => setComment(event.target.value)} onChange={event => onChangeComment(event.target.value)}
/> />
</div> </div>

View File

@ -141,11 +141,11 @@ function DlgEditOperation({ hideWindow, oss, target, onSubmit }: DlgEditOperatio
<TabPanel> <TabPanel>
<TabOperation <TabOperation
alias={alias} alias={alias}
setAlias={setAlias} onChangeAlias={setAlias}
comment={comment} comment={comment}
setComment={setComment} onChangeComment={setComment}
title={title} title={title}
setTitle={setTitle} onChangeTitle={setTitle}
/> />
</TabPanel> </TabPanel>
), ),

View File

@ -4,21 +4,21 @@ import AnimateFade from '@/components/wrap/AnimateFade';
interface TabOperationProps { interface TabOperationProps {
alias: string; alias: string;
setAlias: React.Dispatch<React.SetStateAction<string>>; onChangeAlias: (newValue: string) => void;
title: string; title: string;
setTitle: React.Dispatch<React.SetStateAction<string>>; onChangeTitle: (newValue: string) => void;
comment: string; comment: string;
setComment: React.Dispatch<React.SetStateAction<string>>; onChangeComment: (newValue: string) => void;
} }
function TabOperation({ alias, setAlias, title, setTitle, comment, setComment }: TabOperationProps) { function TabOperation({ alias, onChangeAlias, title, onChangeTitle, comment, onChangeComment }: TabOperationProps) {
return ( return (
<AnimateFade className='cc-column'> <AnimateFade className='cc-column'>
<TextInput <TextInput
id='operation_title' id='operation_title'
label='Полное название' label='Полное название'
value={title} value={title}
onChange={event => setTitle(event.target.value)} onChange={event => onChangeTitle(event.target.value)}
/> />
<div className='flex gap-6'> <div className='flex gap-6'>
<TextInput <TextInput
@ -26,7 +26,7 @@ function TabOperation({ alias, setAlias, title, setTitle, comment, setComment }:
label='Сокращение' label='Сокращение'
className='w-[16rem]' className='w-[16rem]'
value={alias} value={alias}
onChange={event => setAlias(event.target.value)} onChange={event => onChangeAlias(event.target.value)}
/> />
<TextArea <TextArea
@ -35,7 +35,7 @@ function TabOperation({ alias, setAlias, title, setTitle, comment, setComment }:
noResize noResize
rows={3} rows={3}
value={comment} value={comment}
onChange={event => setComment(event.target.value)} onChange={event => onChangeComment(event.target.value)}
/> />
</div> </div>
</AnimateFade> </AnimateFade>

View File

@ -45,7 +45,12 @@ function DlgEditReference({ hideWindow, schema, initial, onSave }: DlgEditRefere
const entityPanel = useMemo( const entityPanel = useMemo(
() => ( () => (
<TabPanel> <TabPanel>
<TabEntityReference initial={initial} schema={schema} setReference={setReference} setIsValid={setIsValid} /> <TabEntityReference
initial={initial}
schema={schema}
onChangeReference={setReference}
onChangeValid={setIsValid}
/>
</TabPanel> </TabPanel>
), ),
[initial, schema] [initial, schema]
@ -54,7 +59,7 @@ function DlgEditReference({ hideWindow, schema, initial, onSave }: DlgEditRefere
const syntacticPanel = useMemo( const syntacticPanel = useMemo(
() => ( () => (
<TabPanel> <TabPanel>
<TabSyntacticReference initial={initial} setReference={setReference} setIsValid={setIsValid} /> <TabSyntacticReference initial={initial} onChangeReference={setReference} onChangeValid={setIsValid} />
</TabPanel> </TabPanel>
), ),
[initial] [initial]

View File

@ -21,11 +21,11 @@ import { IReferenceInputState } from './DlgEditReference';
interface TabEntityReferenceProps { interface TabEntityReferenceProps {
initial: IReferenceInputState; initial: IReferenceInputState;
schema: IRSForm; schema: IRSForm;
setIsValid: React.Dispatch<React.SetStateAction<boolean>>; onChangeValid: (newValue: boolean) => void;
setReference: React.Dispatch<React.SetStateAction<string>>; onChangeReference: (newValue: string) => void;
} }
function TabEntityReference({ initial, schema, setIsValid, setReference }: TabEntityReferenceProps) { function TabEntityReference({ initial, schema, onChangeValid, onChangeReference }: TabEntityReferenceProps) {
const [selectedCst, setSelectedCst] = useState<IConstituenta | undefined>(undefined); const [selectedCst, setSelectedCst] = useState<IConstituenta | undefined>(undefined);
const [alias, setAlias] = useState(''); const [alias, setAlias] = useState('');
const [term, setTerm] = useState(''); const [term, setTerm] = useState('');
@ -43,9 +43,9 @@ function TabEntityReference({ initial, schema, setIsValid, setReference }: TabEn
// Produce result // Produce result
useEffect(() => { useEffect(() => {
setIsValid(alias !== '' && selectedGrams.length > 0); onChangeValid(alias !== '' && selectedGrams.length > 0);
setReference(`@{${alias}|${selectedGrams.map(gram => gram.value).join(',')}}`); onChangeReference(`@{${alias}|${selectedGrams.map(gram => gram.value).join(',')}}`);
}, [alias, selectedGrams, setIsValid, setReference]); }, [alias, selectedGrams, onChangeValid, onChangeReference]);
// Update term when alias changes // Update term when alias changes
useEffect(() => { useEffect(() => {
@ -105,7 +105,7 @@ function TabEntityReference({ initial, schema, setIsValid, setReference }: TabEn
className='flex-grow' className='flex-grow'
menuPlacement='top' menuPlacement='top'
value={selectedGrams} value={selectedGrams}
setValue={setSelectedGrams} onChangeValue={setSelectedGrams}
/> />
</div> </div>
</AnimateFade> </AnimateFade>

View File

@ -11,11 +11,11 @@ import { IReferenceInputState } from './DlgEditReference';
interface TabSyntacticReferenceProps { interface TabSyntacticReferenceProps {
initial: IReferenceInputState; initial: IReferenceInputState;
setIsValid: React.Dispatch<React.SetStateAction<boolean>>; onChangeValid: (newValue: boolean) => void;
setReference: React.Dispatch<React.SetStateAction<string>>; onChangeReference: (newValue: string) => void;
} }
function TabSyntacticReference({ initial, setIsValid, setReference }: TabSyntacticReferenceProps) { function TabSyntacticReference({ initial, onChangeValid, onChangeReference }: TabSyntacticReferenceProps) {
const [nominal, setNominal] = useState(''); const [nominal, setNominal] = useState('');
const [offset, setOffset] = useState(1); const [offset, setOffset] = useState(1);
@ -39,9 +39,9 @@ function TabSyntacticReference({ initial, setIsValid, setReference }: TabSyntact
}, [initial]); }, [initial]);
useEffect(() => { useEffect(() => {
setIsValid(nominal !== '' && offset !== 0); onChangeValid(nominal !== '' && offset !== 0);
setReference(`@{${offset}|${nominal}}`); onChangeReference(`@{${offset}|${nominal}}`);
}, [nominal, offset, setIsValid, setReference]); }, [nominal, offset, onChangeValid, onChangeReference]);
return ( return (
<AnimateFade className='flex flex-col gap-2'> <AnimateFade className='flex flex-col gap-2'>

View File

@ -170,7 +170,7 @@ function DlgEditWordForms({ hideWindow, target, onSave }: DlgEditWordFormsProps)
placeholder='Выберите граммемы' placeholder='Выберите граммемы'
className='min-w-[15rem] h-fit' className='min-w-[15rem] h-fit'
value={inputGrams} value={inputGrams}
setValue={setInputGrams} onChangeValue={setInputGrams}
/> />
</div> </div>

View File

@ -150,8 +150,8 @@ function LibraryPage() {
const viewLocations = useMemo( const viewLocations = useMemo(
() => ( () => (
<ViewSideLocation <ViewSideLocation
active={options.location} activeLocation={options.location}
setActive={options.setLocation} onChangeActiveLocation={options.setLocation}
subfolders={subfolders} subfolders={subfolders}
folderTree={library.folders} folderTree={library.folders}
toggleFolderMode={toggleFolderMode} toggleFolderMode={toggleFolderMode}
@ -200,11 +200,11 @@ function LibraryPage() {
filtered={items.length} filtered={items.length}
hasCustomFilter={hasCustomFilter} hasCustomFilter={hasCustomFilter}
query={query} query={query}
setQuery={setQuery} onChangeQuery={setQuery}
path={path} path={path}
setPath={setPath} onChangePath={setPath}
head={head} head={head}
setHead={setHead} onChangeHead={setHead}
isVisible={isVisible} isVisible={isVisible}
isOwned={isOwned} isOwned={isOwned}
toggleOwned={toggleOwned} toggleOwned={toggleOwned}
@ -212,7 +212,7 @@ function LibraryPage() {
isEditor={isEditor} isEditor={isEditor}
toggleEditor={toggleEditor} toggleEditor={toggleEditor}
filterUser={filterUser} filterUser={filterUser}
setFilterUser={setFilterUser} onChangeFilterUser={setFilterUser}
resetFilter={resetFilter} resetFilter={resetFilter}
folderMode={options.folderMode} folderMode={options.folderMode}
toggleFolderMode={toggleFolderMode} toggleFolderMode={toggleFolderMode}

View File

@ -36,11 +36,11 @@ interface ToolbarSearchProps {
hasCustomFilter: boolean; hasCustomFilter: boolean;
query: string; query: string;
setQuery: React.Dispatch<React.SetStateAction<string>>; onChangeQuery: (newValue: string) => void;
path: string; path: string;
setPath: React.Dispatch<React.SetStateAction<string>>; onChangePath: (newValue: string) => void;
head: LocationHead | undefined; head: LocationHead | undefined;
setHead: React.Dispatch<React.SetStateAction<LocationHead | undefined>>; onChangeHead: (newValue: LocationHead | undefined) => void;
folderMode: boolean; folderMode: boolean;
toggleFolderMode: () => void; toggleFolderMode: () => void;
@ -52,7 +52,7 @@ interface ToolbarSearchProps {
isEditor: boolean | undefined; isEditor: boolean | undefined;
toggleEditor: () => void; toggleEditor: () => void;
filterUser: UserID | undefined; filterUser: UserID | undefined;
setFilterUser: React.Dispatch<React.SetStateAction<UserID | undefined>>; onChangeFilterUser: (newValue: UserID | undefined) => void;
resetFilter: () => void; resetFilter: () => void;
} }
@ -63,11 +63,11 @@ function ToolbarSearch({
hasCustomFilter, hasCustomFilter,
query, query,
setQuery, onChangeQuery,
path, path,
setPath, onChangePath,
head, head,
setHead, onChangeHead,
folderMode, folderMode,
toggleFolderMode, toggleFolderMode,
@ -79,7 +79,7 @@ function ToolbarSearch({
isEditor, isEditor,
toggleEditor, toggleEditor,
filterUser, filterUser,
setFilterUser, onChangeFilterUser,
resetFilter resetFilter
}: ToolbarSearchProps) { }: ToolbarSearchProps) {
@ -95,9 +95,9 @@ function ToolbarSearch({
const handleChange = useCallback( const handleChange = useCallback(
(newValue: LocationHead | undefined) => { (newValue: LocationHead | undefined) => {
headMenu.hide(); headMenu.hide();
setHead(newValue); onChangeHead(newValue);
}, },
[headMenu, setHead] [headMenu, onChangeHead]
); );
const handleToggleFolder = useCallback(() => { const handleToggleFolder = useCallback(() => {
@ -170,7 +170,7 @@ function ToolbarSearch({
className='min-w-[15rem] text-sm' className='min-w-[15rem] text-sm'
items={users} items={users}
value={filterUser} value={filterUser}
onSelectValue={setFilterUser} onSelectValue={onChangeFilterUser}
/> />
</motion.div> </motion.div>
</Dropdown> </Dropdown>
@ -191,7 +191,7 @@ function ToolbarSearch({
noBorder noBorder
className={clsx('min-w-[7rem] sm:min-w-[10rem] max-w-[20rem]', folderMode && 'flex-grow')} className={clsx('min-w-[7rem] sm:min-w-[10rem] max-w-[20rem]', folderMode && 'flex-grow')}
value={query} value={query}
onChange={setQuery} onChange={onChangeQuery}
/> />
{!folderMode ? ( {!folderMode ? (
<div ref={headMenu.ref} className='flex items-center h-full py-1 select-none'> <div ref={headMenu.ref} className='flex items-center h-full py-1 select-none'>
@ -250,7 +250,7 @@ function ToolbarSearch({
noBorder noBorder
className='w-[4.5rem] sm:w-[5rem] flex-grow' className='w-[4.5rem] sm:w-[5rem] flex-grow'
value={path} value={path}
onChange={setPath} onChange={onChangePath}
/> />
) : null} ) : null}
</div> </div>

View File

@ -22,8 +22,8 @@ import { information } from '@/utils/labels';
interface ViewSideLocationProps { interface ViewSideLocationProps {
folderTree: FolderTree; folderTree: FolderTree;
subfolders: boolean; subfolders: boolean;
active: string; activeLocation: string;
setActive: React.Dispatch<React.SetStateAction<string>>; onChangeActiveLocation: (newValue: string) => void;
toggleFolderMode: () => void; toggleFolderMode: () => void;
toggleSubfolders: () => void; toggleSubfolders: () => void;
onRenameLocation: () => void; onRenameLocation: () => void;
@ -31,9 +31,9 @@ interface ViewSideLocationProps {
function ViewSideLocation({ function ViewSideLocation({
folderTree, folderTree,
active, activeLocation,
subfolders, subfolders,
setActive: setActive, onChangeActiveLocation,
toggleFolderMode, toggleFolderMode,
toggleSubfolders, toggleSubfolders,
onRenameLocation onRenameLocation
@ -44,16 +44,18 @@ function ViewSideLocation({
const windowSize = useWindowSize(); const windowSize = useWindowSize();
const canRename = useMemo(() => { const canRename = useMemo(() => {
if (active.length <= 3 || !user) { if (activeLocation.length <= 3 || !user) {
return false; return false;
} }
if (user.is_staff) { if (user.is_staff) {
return true; return true;
} }
const owned = items.filter(item => item.owner == user.id); const owned = items.filter(item => item.owner == user.id);
const located = owned.filter(item => item.location == active || item.location.startsWith(`${active}/`)); const located = owned.filter(
item => item.location == activeLocation || item.location.startsWith(`${activeLocation}/`)
);
return located.length !== 0; return located.length !== 0;
}, [active, user, items]); }, [activeLocation, user, items]);
const animations = useMemo(() => animateSideMinWidth(windowSize.isSmall ? '10rem' : '15rem'), [windowSize]); const animations = useMemo(() => animateSideMinWidth(windowSize.isSmall ? '10rem' : '15rem'), [windowSize]);
const maxHeight = useMemo(() => calculateHeight('4.5rem'), [calculateHeight]); const maxHeight = useMemo(() => calculateHeight('4.5rem'), [calculateHeight]);
@ -68,10 +70,10 @@ function ViewSideLocation({
.then(() => toast.success(information.pathReady)) .then(() => toast.success(information.pathReady))
.catch(console.error); .catch(console.error);
} else { } else {
setActive(target.getPath()); onChangeActiveLocation(target.getPath());
} }
}, },
[setActive] [onChangeActiveLocation]
); );
return ( return (
@ -109,7 +111,7 @@ function ViewSideLocation({
</div> </div>
</div> </div>
<SelectLocation <SelectLocation
value={active} value={activeLocation}
folderTree={folderTree} folderTree={folderTree}
prefix={prefixes.folders_list} prefix={prefixes.folders_list}
onClick={handleClickFolder} onClick={handleClickFolder}

View File

@ -15,7 +15,7 @@ import OssStats from './OssStats';
interface EditorOssCardProps { interface EditorOssCardProps {
isModified: boolean; isModified: boolean;
setIsModified: React.Dispatch<React.SetStateAction<boolean>>; setIsModified: (newValue: boolean) => void;
onDestroy: () => void; onDestroy: () => void;
} }

View File

@ -18,7 +18,7 @@ import { useOssEdit } from '../OssEditContext';
interface FormOSSProps { interface FormOSSProps {
id?: string; id?: string;
isModified: boolean; isModified: boolean;
setIsModified: React.Dispatch<React.SetStateAction<boolean>>; setIsModified: (newValue: boolean) => void;
} }
function FormOSS({ id, isModified, setIsModified }: FormOSSProps) { function FormOSS({ id, isModified, setIsModified }: FormOSSProps) {

View File

@ -6,7 +6,7 @@ import OssFlow from './OssFlow';
interface EditorOssGraphProps { interface EditorOssGraphProps {
isModified: boolean; isModified: boolean;
setIsModified: React.Dispatch<React.SetStateAction<boolean>>; setIsModified: (newValue: boolean) => void;
} }
function EditorOssGraph({ isModified, setIsModified }: EditorOssGraphProps) { function EditorOssGraph({ isModified, setIsModified }: EditorOssGraphProps) {

View File

@ -34,7 +34,7 @@ import ToolbarOssGraph from './ToolbarOssGraph';
interface OssFlowProps { interface OssFlowProps {
isModified: boolean; isModified: boolean;
setIsModified: React.Dispatch<React.SetStateAction<boolean>>; setIsModified: (newValue: boolean) => void;
} }
function OssFlow({ isModified, setIsModified }: OssFlowProps) { function OssFlow({ isModified, setIsModified }: OssFlowProps) {

View File

@ -55,7 +55,7 @@ export interface IOssEditContext extends ILibraryItemEditor {
isAttachedToOSS: boolean; isAttachedToOSS: boolean;
showTooltip: boolean; showTooltip: boolean;
setShowTooltip: React.Dispatch<React.SetStateAction<boolean>>; setShowTooltip: (newValue: boolean) => void;
setOwner: (newOwner: UserID) => void; setOwner: (newOwner: UserID) => void;
setAccessPolicy: (newPolicy: AccessPolicy) => void; setAccessPolicy: (newPolicy: AccessPolicy) => void;

View File

@ -21,7 +21,7 @@ const SIDELIST_LAYOUT_THRESHOLD = 1000; // px
interface EditorConstituentaProps { interface EditorConstituentaProps {
activeCst?: IConstituenta; activeCst?: IConstituenta;
isModified: boolean; isModified: boolean;
setIsModified: React.Dispatch<React.SetStateAction<boolean>>; setIsModified: (newValue: boolean) => void;
onOpenEdit: (cstID: ConstituentaID) => void; onOpenEdit: (cstID: ConstituentaID) => void;
} }

View File

@ -31,7 +31,7 @@ interface FormConstituentaProps {
isModified: boolean; isModified: boolean;
toggleReset: boolean; toggleReset: boolean;
setIsModified: React.Dispatch<React.SetStateAction<boolean>>; setIsModified: (newValue: boolean) => void;
onRename: () => void; onRename: () => void;
onEditTerm: () => void; onEditTerm: () => void;
@ -225,9 +225,9 @@ function FormConstituenta({
activeCst={state} activeCst={state}
disabled={disabled || state.is_inherited} disabled={disabled || state.is_inherited}
toggleReset={toggleReset} toggleReset={toggleReset}
onChange={newValue => setExpression(newValue)} onChangeExpression={newValue => setExpression(newValue)}
setTypification={setTypification} onChangeTypification={setTypification}
setLocalParse={setLocalParse} onChangeLocalParse={setLocalParse}
onOpenEdit={onOpenEdit} onOpenEdit={onOpenEdit}
/> />
</AnimateFade> </AnimateFade>

View File

@ -2,7 +2,7 @@
import { ReactCodeMirrorRef } from '@uiw/react-codemirror'; import { ReactCodeMirrorRef } from '@uiw/react-codemirror';
import { AnimatePresence } from 'framer-motion'; import { AnimatePresence } from 'framer-motion';
import React, { useCallback, useLayoutEffect, useMemo, useRef, useState } from 'react'; import { useCallback, useLayoutEffect, useMemo, useRef, useState } from 'react';
import { toast } from 'react-toastify'; import { toast } from 'react-toastify';
import BadgeHelp from '@/components/info/BadgeHelp'; import BadgeHelp from '@/components/info/BadgeHelp';
@ -39,9 +39,9 @@ interface EditorRSExpressionProps {
disabled?: boolean; disabled?: boolean;
toggleReset?: boolean; toggleReset?: boolean;
setTypification: (typification: string) => void; onChangeTypification: (typification: string) => void;
setLocalParse: React.Dispatch<React.SetStateAction<IExpressionParse | undefined>>; onChangeLocalParse: (typification: IExpressionParse | undefined) => void;
onChange: (newValue: string) => void; onChangeExpression: (newValue: string) => void;
onOpenEdit?: (cstID: ConstituentaID) => void; onOpenEdit?: (cstID: ConstituentaID) => void;
} }
@ -50,9 +50,9 @@ function EditorRSExpression({
disabled, disabled,
value, value,
toggleReset, toggleReset,
setTypification, onChangeTypification,
setLocalParse, onChangeLocalParse,
onChange, onChangeExpression,
onOpenEdit, onOpenEdit,
...restProps ...restProps
}: EditorRSExpressionProps) { }: EditorRSExpressionProps) {
@ -74,20 +74,20 @@ function EditorRSExpression({
}, [activeCst, resetParse, toggleReset]); }, [activeCst, resetParse, toggleReset]);
function handleChange(newValue: string) { function handleChange(newValue: string) {
onChange(newValue); onChangeExpression(newValue);
setIsModified(newValue !== activeCst.definition_formal); setIsModified(newValue !== activeCst.definition_formal);
} }
function handleCheckExpression(callback?: (parse: IExpressionParse) => void) { function handleCheckExpression(callback?: (parse: IExpressionParse) => void) {
parser.checkConstituenta(value, activeCst, parse => { parser.checkConstituenta(value, activeCst, parse => {
setLocalParse(parse); onChangeLocalParse(parse);
if (parse.errors.length > 0) { if (parse.errors.length > 0) {
onShowError(parse.errors[0], parse.prefixLen); onShowError(parse.errors[0], parse.prefixLen);
} else { } else {
rsInput.current?.view?.focus(); rsInput.current?.view?.focus();
} }
setIsModified(false); setIsModified(false);
setTypification( onChangeTypification(
labelTypification({ labelTypification({
isValid: parse.parseResult, isValid: parse.parseResult,
resultType: parse.typification, resultType: parse.typification,

View File

@ -15,7 +15,7 @@ import ToolbarRSFormCard from './ToolbarRSFormCard';
interface EditorRSFormCardProps { interface EditorRSFormCardProps {
isModified: boolean; isModified: boolean;
setIsModified: React.Dispatch<React.SetStateAction<boolean>>; setIsModified: (newValue: boolean) => void;
onDestroy: () => void; onDestroy: () => void;
} }

View File

@ -18,7 +18,7 @@ import ToolbarVersioning from './ToolbarVersioning';
interface FormRSFormProps { interface FormRSFormProps {
id?: string; id?: string;
isModified: boolean; isModified: boolean;
setIsModified: React.Dispatch<React.SetStateAction<boolean>>; setIsModified: (newValue: boolean) => void;
} }
function FormRSForm({ id, isModified, setIsModified }: FormRSFormProps) { function FormRSForm({ id, isModified, setIsModified }: FormRSFormProps) {