use-debounce#useDebounce TypeScript Examples
The following examples show how to use
use-debounce#useDebounce.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: FormAutosave.tsx From firetable with Apache License 2.0 | 6 votes |
export default function FormAutosave({ control, handleSave }: IAutosaveProps) {
const values = useWatch({ control });
const [debouncedValue] = useDebounce(values, 1000, {
equalityFn: _isEqual,
});
useEffect(() => {
handleSave(debouncedValue);
}, [debouncedValue]);
return null;
}
Example #2
Source File: Tooltip.tsx From posthog-foss with MIT License | 6 votes |
/** Extension of Ant Design's Tooltip that enables a delay.
*
* Caveat: doesn't work with disabled elements due to lack of workaround that Ant Design uses.
* See https://github.com/ant-design/ant-design/blob/master/components/tooltip/index.tsx#L82-L130.
*/
// CAUTION: Any changes here will affect tooltips across the entire app.
export function Tooltip({
children,
visible,
isDefaultTooltip = false,
delayMs = DEFAULT_DELAY_MS,
...props
}: TooltipProps): JSX.Element {
const [localVisible, setVisible] = useState(visible)
const [debouncedLocalVisible] = useDebounce(visible ?? localVisible, delayMs)
if (!isDefaultTooltip && !('mouseEnterDelay' in props)) {
// If not preserving default behavior and mouseEnterDelay is not already provided, we use a custom default here
props.mouseEnterDelay = delayMs
}
// If child is not a valid element (string or string + ReactNode, Fragment), antd wraps children in a span.
// See https://github.com/ant-design/ant-design/blob/master/components/tooltip/index.tsx#L226
const child = React.isValidElement(children) ? children : <span>{children}</span>
return props.title ? (
<AntdTooltip {...props} visible={isDefaultTooltip ? visible : localVisible && debouncedLocalVisible}>
{React.cloneElement(child, {
onMouseEnter: () => setVisible(true),
onMouseLeave: () => setVisible(false),
})}
</AntdTooltip>
) : (
child
)
}
Example #3
Source File: Autosave.tsx From firetable with Apache License 2.0 | 5 votes |
export default function Autosave({
control,
docRef,
row,
reset,
dirtyFields,
}: IAutosaveProps) {
const { tableState, updateCell } = useFiretableContext();
const values = useWatch({ control });
const [debouncedValue] = useDebounce(getEditables(values, tableState), 1000, {
equalityFn: _isEqual,
});
useEffect(() => {
if (!row || !row.ref) return;
if (row.ref.id !== docRef.id) return;
if (!updateCell) return;
// Get only fields that have had their value updated by the user
const updatedValues = _pickBy(
_pickBy(debouncedValue, (_, key) => dirtyFields[key]),
(value, key) => !_isEqual(value, row[key])
);
console.log(debouncedValue, row);
console.log(updatedValues, dirtyFields);
if (Object.keys(updatedValues).length === 0) return;
// Update the document
Object.entries(updatedValues).forEach(([key, value]) =>
updateCell(
row.ref,
key,
value,
// After the cell is updated, set this field to be not dirty
// so it doesn’t get updated again when a different field in the form
// is updated + make sure the new value is kept after reset
() => reset({ ...values, [key]: value })
)
);
}, [debouncedValue]);
return null;
}
Example #4
Source File: ObjectsPanel.tsx From react-design-editor with MIT License | 5 votes |
function ObjectsPanel() {
const [search, setSearch] = useState('')
const [objects, setObjects] = useState<any[]>([])
const [value] = useDebounce(search, 1000)
const { canvas } = useCanvasContext()
useEffect(() => {
getImages('love')
.then((data: any) => setObjects(data))
.catch(console.log)
}, [])
useEffect(() => {
if (value) {
getImages(value)
.then((data: any) => setObjects(data))
.catch(console.log)
}
}, [value])
const renderItems = () => {
return objects.map(obj => {
return (
<div className="object-item-container" onClick={() => downloadImage(obj.uuid)} key={obj.uuid}>
<img className="object-item" src={obj.urls.thumb} />
</div>
)
})
}
const downloadImage = uuid => {
getImage(uuid)
.then(url => {
fabric.loadSVGFromURL(url, (objects, options) => {
const object = fabric.util.groupSVGElements(objects, options)
//@ts-ignore
const workarea = canvas.getObjects().find(obj => obj.id === 'workarea')
canvas.add(object)
object.scaleToHeight(300)
object.center()
object.clipPath = workarea
canvas.renderAll()
})
})
.catch(console.log)
}
return (
<>
<div style={{ padding: '1rem 2rem' }}>
<InputGroup>
<InputLeftElement pointerEvents="none" children={<SearchIcon color="gray.300" />} />
<Input
onChange={e => setSearch(e.target.value)}
style={{ background: '#fff' }}
type="tel"
placeholder="Search objects"
/>
</InputGroup>
</div>
<div style={{ padding: '0 2rem' }} className="objects-list">
{renderItems()}
</div>
</>
)
}
Example #5
Source File: index.tsx From excalideck with MIT License | 5 votes |
export default function SlideMiniatureImage({ deck, slide }: Props) {
const containerRef = useRef<HTMLDivElement>(null);
const [debouncedDeck] = useDebounce(
deck,
SLIDE_MINIATURE_IMAGE_RENDER_DEBOUNCE
);
const [debouncedSlide] = useDebounce(
slide,
SLIDE_MINIATURE_IMAGE_RENDER_DEBOUNCE
);
useEffect(() => {
// When no canvas has been rendered yet (i.e. it's the first render),
// and there is a cached canvas, render it
if (!isCanvasRendered(containerRef)) {
const cachedSlideCanvas = slideCanvasCache.get(debouncedSlide.id);
if (cachedSlideCanvas) {
renderCanvas(containerRef, cachedSlideCanvas);
}
}
// Update the canvas cache and re-render the canvas. This operation is
// deferred to avoid blocking other more important work, like switching
// view
setTimeout(() => {
const cachedSlideCanvas = slideCanvasCache.get(debouncedSlide.id);
const updatedSlideCanvas = canvasSlideRenderer.renderSlide(
debouncedDeck,
debouncedSlide.id
);
if (updatedSlideCanvas !== cachedSlideCanvas) {
renderCanvas(containerRef, updatedSlideCanvas);
slideCanvasCache.set(debouncedSlide.id, updatedSlideCanvas);
}
}, 0);
}, [debouncedDeck, debouncedSlide]);
const slideAspectRatio =
deck.printableArea.width / deck.printableArea.height;
const miniatureAspectRatio = 3 / 2;
return (
<div
ref={containerRef}
className={clsx(
"SlideMiniatureImage",
slideAspectRatio < miniatureAspectRatio
? "HeightCappedSlideMiniatureImage"
: "WidthCappedSlideMiniatureImage"
)}
/>
);
}
Example #6
Source File: ConnectTableSelect.tsx From firetable with Apache License 2.0 | 4 votes |
export default function ConnectTableSelect({
value = [],
onChange,
column,
row,
config,
disabled,
className,
TextFieldProps = {},
onClose,
loadBeforeOpen,
}: IConnectTableSelectProps) {
// Store a local copy of the value so the dropdown doesn’t automatically close
// when the user selects a new item and we allow for multiple selections
const [localValue, setLocalValue] = useState(
Array.isArray(value) ? value : []
);
const filters = config.filters
? config.filters.replace(/\{\{(.*?)\}\}/g, replacer(row))
: "";
const algoliaIndex = config.index;
const [algoliaSearchKeys, setAlgoliaSearchKeys] = useAlgoliaSearchKeys<any>(
{}
);
const [algoliaState, requestDispatch, , setAlgoliaConfig] = useAlgolia(
process.env.REACT_APP_ALGOLIA_APP_ID!,
process.env.REACT_APP_ALGOLIA_SEARCH_API_KEY ?? "",
// Don’t choose the index until the user opens the dropdown if !loadBeforeOpen
loadBeforeOpen ? algoliaIndex : "",
{ filters }
);
const setAlgoliaSearchKey = async (algoliaIndex: string) => {
const requestedAt = Date.now() / 1000;
if (
algoliaSearchKeys &&
(algoliaSearchKeys?.[algoliaIndex] as any)?.key &&
requestedAt <
(algoliaSearchKeys?.[algoliaIndex] as any).requestedAt + 3600
) {
//'use existing key'
setAlgoliaConfig({
indexName: algoliaIndex,
searchKey: (algoliaSearchKeys?.[algoliaIndex] as any).key,
});
} else {
//'get new key'
const resp = await getAlgoliaSearchKey(algoliaIndex);
const key = resp.data.data;
if (key) {
const newKey = {
key,
requestedAt,
};
setAlgoliaSearchKeys(
algoliaSearchKeys
? { ...algoliaSearchKeys, [algoliaIndex]: newKey }
: { [algoliaIndex]: newKey }
);
setAlgoliaConfig({ indexName: algoliaIndex, searchKey: key });
}
}
};
useEffect(() => {
if (!process.env.REACT_APP_ALGOLIA_SEARCH_API_KEY)
setAlgoliaSearchKey(algoliaIndex);
}, [algoliaIndex]);
const options = algoliaState.hits.map((hit) => ({
label: config.primaryKeys?.map((key: string) => hit[key]).join(" "),
value: hit.objectID,
}));
// Pass a list of objectIDs to MultiSelect
const sanitisedValue = localValue.map(
(item) => item.docPath.split("/")[item.docPath.split("/").length - 1]
);
const handleChange = (_newValue) => {
// Ensure we return an array
const newValue = Array.isArray(_newValue)
? _newValue
: _newValue !== null
? [_newValue]
: [];
// Calculate new value
const newLocalValue = newValue.map((objectID) => {
// If this objectID is already in the previous value, use that previous
// value’s snapshot (in case it points to an object not in the current
// Algolia query)
const existingMatch = _find(localValue, {
docPath: `${algoliaIndex}/${objectID}`,
});
if (existingMatch) return existingMatch;
// If this is a completely new selection, grab the snapshot from the
// current Algolia query
const match = _find(algoliaState.hits, { objectID });
const { _highlightResult, ...snapshot } = match;
// Use snapshotFields to limit snapshots
let partialSnapshot = snapshot;
if (
Array.isArray(config.snapshotFields) &&
config.snapshotFields.length > 0
)
partialSnapshot = _pick(snapshot, config.snapshotFields);
return {
snapshot: partialSnapshot,
docPath: `${algoliaIndex}/${snapshot.objectID}`,
};
});
// If !multiple, we MUST change the value (bypassing localValue),
// otherwise `setLocalValue` won’t be called in time for the new
// `localValue` to be read by `handleSave`
if (config.multiple === false) onChange(newLocalValue);
// Otherwise, `setLocalValue` until user closes dropdown
else setLocalValue(newLocalValue);
};
// Save when user closes dropdown
const handleSave = () => {
if (config.multiple !== false) onChange(localValue);
if (onClose) onClose();
};
// Change MultiSelect input field to search Algolia directly
const [search, setSearch] = useState("");
const [debouncedSearch] = useDebounce(search, 1000);
useEffect(() => {
requestDispatch({ query: debouncedSearch });
}, [debouncedSearch]);
return (
<MultiSelect
value={config.multiple === false ? sanitisedValue[0] : sanitisedValue}
onChange={handleChange}
onOpen={() => {
setAlgoliaConfig({
indexName: algoliaIndex,
});
requestDispatch({ filters });
}}
onClose={handleSave}
options={options}
TextFieldProps={{
className,
hiddenLabel: true,
...TextFieldProps,
}}
label={column?.name}
labelPlural={config.searchLabel}
multiple={(config.multiple ?? true) as any}
{...({
AutocompleteProps: {
loading: algoliaState.loading,
loadingText: <Loading />,
inputValue: search,
onInputChange: (_, value, reason) => {
if (reason === "input") setSearch(value);
},
filterOptions: () => options,
},
} as any)}
countText={`${localValue.length} of ${
algoliaState.response?.nbHits ?? "?"
}`}
disabled={disabled}
/>
);
}
Example #7
Source File: ImageSettings.tsx From freedeck-configurator with GNU General Public License v3.0 | 4 votes |
ImageSettings: React.FC<{
setImageSettings: (settings: IDisplay["imageSettings"]) => void;
setTextSettings: (settings: IDisplay["textSettings"]) => void;
setTextWithIconSettings: (settings: IDisplay["textWithIconSettings"]) => void;
textOnly: boolean;
imageSettings: IDisplay["imageSettings"];
textWithIconSettings: IDisplay["textWithIconSettings"];
textSettings: IDisplay["textSettings"];
}> = ({
setImageSettings,
setTextSettings,
setTextWithIconSettings,
textOnly,
imageSettings,
textWithIconSettings,
textSettings,
}) => {
const [localText, setLocalText] = useState<string>(textSettings.text);
const [localWhite, setLocalWhite] = useState<number>(
imageSettings.whiteThreshold
);
const [localBlack, setLocalBlack] = useState<number>(
imageSettings.blackThreshold
);
const [localBrightness, setLocalBrightness] = useState<number>(
imageSettings.brightness
);
const [localContrast, setLocalContrast] = useState<number>(
imageSettings.contrast
);
const [localIconWidth, setLocalIconWidth] = useState<number>(
textWithIconSettings.iconWidthMultiplier
);
const [debouncedText] = useDebounce(localText, 33, {
maxWait: 33,
leading: true,
});
const [debouncedWhite] = useDebounce(localWhite, 33, {
maxWait: 33,
leading: true,
});
const [debouncedBlack] = useDebounce(localBlack, 33, {
maxWait: 33,
leading: true,
});
const [debouncedBrightness] = useDebounce(localBrightness, 33, {
maxWait: 33,
leading: true,
});
const [debouncedContrast] = useDebounce(localContrast, 33, {
maxWait: 33,
leading: true,
});
const [debouncedIconWidth] = useDebounce(localIconWidth, 33, {
maxWait: 33,
leading: true,
});
const setBlack = useCallback(
(blackThreshold: number) => {
setImageSettings({ ...imageSettings, blackThreshold });
},
[imageSettings, setImageSettings]
);
const setWhite = useCallback(
(whiteThreshold: number) => {
setImageSettings({ ...imageSettings, whiteThreshold });
},
[imageSettings, setImageSettings]
);
const setBrightness = useCallback(
(brightness: number) => {
setImageSettings({ ...imageSettings, brightness });
},
[imageSettings, setImageSettings]
);
const setContrast = useCallback(
(contrast: number) => {
setImageSettings({ ...imageSettings, contrast });
},
[imageSettings, setImageSettings]
);
const setInvert = useCallback(
(invert: boolean) => {
setImageSettings({ ...imageSettings, invert });
},
[imageSettings, setImageSettings]
);
const setDither = useCallback(
(dither: any) => {
setImageSettings({ ...imageSettings, dither });
},
[imageSettings, setImageSettings]
);
const setfontName = useCallback(
(font: string) => {
setTextSettings({ ...textSettings, font });
},
[textSettings, setTextSettings]
);
const setText = useCallback(
(text: string) => {
setTextSettings({ ...textSettings, text });
},
[setTextSettings, textSettings]
);
const setIconWidthMultiplier = useCallback(
(value: number) => {
setTextWithIconSettings({
...textWithIconSettings,
iconWidthMultiplier: value,
});
},
[setTextWithIconSettings, textWithIconSettings]
);
useEffect(() => {
setLocalText(textSettings.text);
setLocalWhite(imageSettings.whiteThreshold);
setLocalBlack(imageSettings.blackThreshold);
setLocalBrightness(imageSettings.brightness);
setLocalContrast(imageSettings.contrast);
setLocalIconWidth(textWithIconSettings.iconWidthMultiplier);
}, [imageSettings, textSettings, textWithIconSettings]);
useEffect(() => {
setText(debouncedText);
// eslint-disable-next-line
}, [debouncedText]); // dont put setText there, we will have an endless loop if you do
useEffect(() => {
setWhite(debouncedWhite);
// eslint-disable-next-line
}, [debouncedWhite]);
useEffect(() => {
setBlack(debouncedBlack);
// eslint-disable-next-line
}, [debouncedBlack]);
useEffect(() => {
setBrightness(debouncedBrightness);
// eslint-disable-next-line
}, [debouncedBrightness]);
useEffect(() => {
setContrast(debouncedContrast);
// eslint-disable-next-line
}, [debouncedContrast]);
useEffect(() => {
setIconWidthMultiplier(debouncedIconWidth);
// eslint-disable-next-line
}, [debouncedIconWidth]);
return (
<Wrapper>
<Column>
<Disabler
disable={textOnly}
title="These options are disabled. Load an image by clicking on the black box or just enter some text"
/>
<Title>Image Settings</Title>
{!imageSettings.dither ? (
<>
<Row>
<Label>White Threshold:</Label>
<Value>{imageSettings.whiteThreshold}</Value>
</Row>
<Row>
<StyledSlider
min={0}
max={128}
step={1}
value={localWhite}
onChange={(event) =>
setLocalWhite(event.currentTarget.valueAsNumber)
}
/>
</Row>
<Row>
<Label>Black Threshold:</Label>
<Value>{imageSettings.blackThreshold}</Value>
</Row>
<Row>
<StyledSlider
min={128}
max={255}
step={1}
value={localBlack}
onChange={(event) =>
setLocalBlack(event.currentTarget.valueAsNumber)
}
/>
</Row>
</>
) : (
<>
<Row>
<Label>Brightness:</Label>
<Value>{imageSettings.brightness}</Value>
</Row>
<Row>
<StyledSlider
min={-1}
max={1}
step={0.02}
value={localBrightness}
onChange={(event) =>
setLocalBrightness(event.currentTarget.valueAsNumber)
}
/>
</Row>
<Row>
<Label>Contrast:</Label>
<Value>{imageSettings.contrast}</Value>
</Row>
<Row>
<StyledSlider
min={-1}
max={1}
step={0.02}
value={localContrast}
onChange={(event) =>
setLocalContrast(event.currentTarget.valueAsNumber)
}
/>
</Row>
</>
)}
<Row>
<MicroToggle
activated={imageSettings.invert}
width="48%"
onClick={() => setInvert(!imageSettings.invert)}
>
Invert
</MicroToggle>
<MicroToggle
activated={imageSettings.dither}
width="48%"
onClick={() => setDither(!imageSettings.dither)}
>
Dither
</MicroToggle>
</Row>
<Row>
<Label>Icon width:</Label>
<Value>{textWithIconSettings.iconWidthMultiplier.toFixed(2)}</Value>
</Row>
<Row>
<StyledSlider
disabled={!textSettings.text.length}
min={0.1}
max={0.9}
step={0.01}
value={localIconWidth}
onChange={(event) =>
setLocalIconWidth(event.currentTarget.valueAsNumber)
}
/>
</Row>
</Column>
<Column>
<Title>Text</Title>
<Row>
<TextInput
placeholder={"Enter text"}
value={localText}
onChange={(e) => setLocalText(e.currentTarget.value)}
/>
</Row>
<Row>
<Label>Font:</Label>
<StyledSelect
defaultValue={textSettings.font}
onChange={(e) => setfontName(e.currentTarget.value)}
>
<option value={fontSmaller}>smaller</option>
<option value={fontSmall}>small</option>
<option value={fontMedium}>medium</option>
<option value={fontLarge}>large</option>
</StyledSelect>
</Row>
</Column>
</Wrapper>
);
}
Example #8
Source File: AddBucket.tsx From console with GNU Affero General Public License v3.0 | 4 votes |
AddBucket = ({ classes }: IAddBucketProps) => {
const dispatch = useDispatch();
const bucketName = useSelector(
(state: AppState) => state.buckets.addBucketName
);
const versioningEnabled = useSelector(
(state: AppState) => state.buckets.addBucketVersioningEnabled
);
const lockingEnabled = useSelector(
(state: AppState) => state.buckets.addBucketLockingEnabled
);
const quotaEnabled = useSelector(
(state: AppState) => state.buckets.addBucketQuotaEnabled
);
const quotaType = useSelector(
(state: AppState) => state.buckets.addBucketQuotaType
);
const quotaSize = useSelector(
(state: AppState) => state.buckets.addBucketQuotaSize
);
const quotaUnit = useSelector(
(state: AppState) => state.buckets.addBucketQuotaUnit
);
const retentionEnabled = useSelector(
(state: AppState) => state.buckets.addBucketRetentionEnabled
);
const retentionMode = useSelector(
(state: AppState) => state.buckets.addBucketRetentionMode
);
const retentionUnit = useSelector(
(state: AppState) => state.buckets.addBucketRetentionUnit
);
const retentionValidity = useSelector(
(state: AppState) => state.buckets.addBucketRetentionValidity
);
const distributedSetup = useSelector(selDistSet);
const siteReplicationInfo = useSelector(selSiteRep);
const [addLoading, setAddLoading] = useState<boolean>(false);
const [sendEnabled, setSendEnabled] = useState<boolean>(false);
const [lockingFieldDisabled, setLockingFieldDisabled] =
useState<boolean>(false);
const addRecord = (event: React.FormEvent) => {
event.preventDefault();
if (addLoading) {
return;
}
setAddLoading(true);
let request: MakeBucketRequest = {
name: bucketName,
versioning:
distributedSetup && !siteReplicationInfo.enabled
? versioningEnabled
: false,
locking: distributedSetup ? lockingEnabled : false,
};
if (distributedSetup) {
if (quotaEnabled) {
const amount = getBytes(quotaSize, quotaUnit, true);
request.quota = {
enabled: true,
quota_type: quotaType,
amount: parseInt(amount),
};
}
if (retentionEnabled) {
request.retention = {
mode: retentionMode,
unit: retentionUnit,
validity: retentionValidity,
};
}
}
api
.invoke("POST", "/api/v1/buckets", request)
.then((res) => {
setAddLoading(false);
const newBucketName = `${bucketName}`;
resetForm();
history.push(`/buckets/${newBucketName}/browse`);
})
.catch((err: ErrorResponseHandler) => {
setAddLoading(false);
dispatch(setErrorSnackMessage(err));
});
};
const [value] = useDebounce(bucketName, 1000);
useEffect(() => {
dispatch(addBucketName(value));
}, [value, dispatch]);
const resetForm = () => {
dispatch(addBucketName(""));
dispatch(addBucketVersioning(false));
dispatch(addBucketEnableObjectLocking(false));
dispatch(addBucketQuota(false));
dispatch(addBucketQuotaType("hard"));
dispatch(addBucketQuotaSize("1"));
dispatch(addBucketQuotaUnit("Ti"));
dispatch(addBucketRetention(false));
dispatch(addBucketRetentionMode("compliance"));
dispatch(addBucketRetentionUnit("days"));
dispatch(addBucketRetentionValidity(180));
};
useEffect(() => {
let valid = false;
if (bucketName.trim() !== "") {
valid = true;
}
if (quotaEnabled && valid) {
if (quotaSize.trim() === "" || parseInt(quotaSize) === 0) {
valid = false;
}
}
if (!versioningEnabled || !retentionEnabled) {
dispatch(addBucketRetention(false));
dispatch(addBucketRetentionMode("compliance"));
dispatch(addBucketRetentionUnit("days"));
dispatch(addBucketRetentionValidity(180));
}
if (retentionEnabled) {
// if retention is enabled, then objec locking should be enabled as well
dispatch(addBucketEnableObjectLocking(true));
setLockingFieldDisabled(true);
} else {
setLockingFieldDisabled(false);
}
if (
retentionEnabled &&
(Number.isNaN(retentionValidity) || retentionValidity < 1)
) {
valid = false;
}
setSendEnabled(valid);
}, [
bucketName,
retentionEnabled,
lockingEnabled,
quotaType,
quotaSize,
quotaUnit,
quotaEnabled,
dispatch,
retentionValidity,
versioningEnabled,
]);
return (
<Fragment>
<PageHeader label={<BackLink to={"/buckets"} label={"Buckets"} />} />
<PageLayout>
<FormLayout
title={"Create Bucket"}
icon={<BucketsIcon />}
helpbox={
<HelpBox
iconComponent={<BucketsIcon />}
title={"Buckets"}
help={
<Fragment>
MinIO uses buckets to organize objects. A bucket is similar to
a folder or directory in a filesystem, where each bucket can
hold an arbitrary number of objects.
<br />
<br />
<b>Versioning</b> allows to keep multiple versions of the same
object under the same key.
<br />
<br />
<b>Object Locking</b> prevents objects from being deleted.
Required to support retention and legal hold. Can only be
enabled at bucket creation.
<br />
<br />
<b>Quota</b> limits the amount of data in the bucket.
<br />
<br />
<b>Retention</b> imposes rules to prevent object deletion for
a period of time.
</Fragment>
}
/>
}
>
<form
noValidate
autoComplete="off"
onSubmit={(e: React.FormEvent<HTMLFormElement>) => {
addRecord(e);
}}
>
<Grid container marginTop={1} spacing={2}>
<Grid item xs={12}>
<InputBoxWrapper
id="bucket-name"
name="bucket-name"
autoFocus={true}
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
dispatch(addBucketName(event.target.value));
}}
label="Bucket Name"
value={bucketName}
/>
</Grid>
<Grid item xs={12}>
<SectionTitle>Features</SectionTitle>
{!distributedSetup && (
<Fragment>
<div className={classes.error}>
These features are unavailable in a single-disk setup.
<br />
Please deploy a server in{" "}
<a
href="https://docs.min.io/minio/baremetal/installation/deploy-minio-distributed.html?ref=con"
target="_blank"
rel="noreferrer"
>
Distributed Mode
</a>{" "}
to use these features.
</div>
<br />
<br />
</Fragment>
)}
</Grid>
<Grid item xs={12}>
{siteReplicationInfo.enabled && (
<Fragment>
<br />
<div className={classes.alertVersioning}>
<InfoIcon /> Versioning setting cannot be changed as
cluster replication is enabled for this site.
</div>
<br />
</Fragment>
)}
<FormSwitchWrapper
value="versioned"
id="versioned"
name="versioned"
checked={versioningEnabled}
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
dispatch(addBucketVersioning(event.target.checked));
}}
label={"Versioning"}
disabled={
!distributedSetup ||
lockingEnabled ||
siteReplicationInfo.enabled
}
/>
</Grid>
<Grid item xs={12}>
<FormSwitchWrapper
value="locking"
id="locking"
name="locking"
disabled={lockingFieldDisabled || !distributedSetup}
checked={lockingEnabled}
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
dispatch(
addBucketEnableObjectLocking(event.target.checked)
);
if (event.target.checked && !siteReplicationInfo.enabled) {
dispatch(addBucketVersioning(true));
}
}}
label={"Object Locking"}
/>
</Grid>
<Grid item xs={12}>
<FormSwitchWrapper
value="bucket_quota"
id="bucket_quota"
name="bucket_quota"
checked={quotaEnabled}
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
dispatch(addBucketQuota(event.target.checked));
}}
label={"Quota"}
disabled={!distributedSetup}
/>
</Grid>
{quotaEnabled && distributedSetup && (
<React.Fragment>
<Grid item xs={12}>
<InputBoxWrapper
type="number"
id="quota_size"
name="quota_size"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
if (e.target.validity.valid) {
dispatch(addBucketQuotaSize(e.target.value));
}
}}
label="Capacity"
value={quotaSize}
required
min="1"
pattern={"[0-9]*"}
overlayObject={
<InputUnitMenu
id={"quota_unit"}
onUnitChange={(newValue) => {
dispatch(addBucketQuotaUnit(newValue));
}}
unitSelected={quotaUnit}
unitsList={k8sScalarUnitsExcluding(["Ki"])}
disabled={false}
/>
}
/>
</Grid>
</React.Fragment>
)}
{versioningEnabled && distributedSetup && (
<Grid item xs={12}>
<FormSwitchWrapper
value="bucket_retention"
id="bucket_retention"
name="bucket_retention"
checked={retentionEnabled}
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
dispatch(addBucketRetention(event.target.checked));
}}
label={"Retention"}
/>
</Grid>
)}
{retentionEnabled && distributedSetup && (
<React.Fragment>
<Grid item xs={12}>
<RadioGroupSelector
currentSelection={retentionMode}
id="retention_mode"
name="retention_mode"
label="Mode"
onChange={(e: React.ChangeEvent<{ value: unknown }>) => {
dispatch(
addBucketRetentionMode(e.target.value as string)
);
}}
selectorOptions={[
{ value: "compliance", label: "Compliance" },
{ value: "governance", label: "Governance" },
]}
/>
</Grid>
<Grid item xs={12}>
<InputBoxWrapper
type="number"
id="retention_validity"
name="retention_validity"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
dispatch(
addBucketRetentionValidity(e.target.valueAsNumber)
);
}}
label="Validity"
value={String(retentionValidity)}
required
overlayObject={
<InputUnitMenu
id={"retention_unit"}
onUnitChange={(newValue) => {
dispatch(addBucketRetentionUnit(newValue));
}}
unitSelected={retentionUnit}
unitsList={[
{ value: "days", label: "Days" },
{ value: "years", label: "Years" },
]}
disabled={false}
/>
}
/>
</Grid>
</React.Fragment>
)}
</Grid>
<Grid item xs={12} className={classes.buttonContainer}>
<Button
type="button"
variant={"outlined"}
className={classes.clearButton}
onClick={resetForm}
>
Clear
</Button>
<Button
type="submit"
variant="contained"
color="primary"
disabled={addLoading || !sendEnabled}
>
Create Bucket
</Button>
</Grid>
{addLoading && (
<Grid item xs={12}>
<LinearProgress />
</Grid>
)}
</form>
</FormLayout>
</PageLayout>
</Fragment>
);
}
Example #9
Source File: UserSearch.tsx From knboard with MIT License | 4 votes |
UserSearch = ({ boardId, tagsValue, setTagsValue }: Props) => {
const theme = useTheme();
const [open, setOpen] = useState(false);
const [inputValue, setInputValue] = useState("");
const [loading, setLoading] = useState(false);
const [options, setOptions] = useState<UserOption[]>([]);
const [debouncedInput] = useDebounce(inputValue, 300, {
equalityFn: (a, b) => a === b,
});
useEffect(() => {
if (!open) {
setOptions([]);
setLoading(false);
}
}, [open]);
useEffect(() => {
if (inputValue) {
setLoading(true);
}
}, [inputValue]);
useEffect(() => {
const source = api.CancelToken.source();
const fetchData = async () => {
try {
const response = await api(
`${API_SEARCH_USERS}?board=${boardId}&search=${inputValue}`,
{ cancelToken: source.token }
);
setLoading(false);
setOptions(response.data);
} catch (err) {
if (!api.isCancel(err)) {
console.error(err);
}
}
};
if (inputValue === "") {
setLoading(false);
setOptions([]);
} else {
fetchData();
}
return () => {
source.cancel("unmount/debouncedInput changed");
};
}, [debouncedInput, tagsValue]);
useEffect(() => {
if (debouncedInput === inputValue) {
setLoading(false);
}
}, [debouncedInput, inputValue]);
const handleInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setInputValue(event.target.value);
};
const handleTagsChange = (_event: React.ChangeEvent<{}>, newValues: any) => {
setTagsValue(newValues);
setOptions([]);
};
return (
<Autocomplete
multiple
id="user-search"
size="small"
open={open}
onOpen={() => setOpen(true)}
onClose={() => setOpen(false)}
getOptionSelected={(option, value) => option.username === value.username}
getOptionLabel={(option) => option.username}
filterSelectedOptions
onChange={handleTagsChange}
options={options}
loading={loading}
value={tagsValue}
renderOption={(option) => <AvatarOption option={option} />}
renderInput={(params) => (
<TextField
{...params}
autoFocus
label="Search username"
variant="outlined"
onChange={handleInputChange}
InputProps={{
...params.InputProps,
endAdornment: (
<>
{loading && <CircularProgress color="inherit" size={20} />}
{params.InputProps.endAdornment}
</>
),
}}
/>
)}
renderTags={(value, getTagProps) =>
value.map((option, index) => (
<AvatarTag
key={option.id}
option={option}
{...getTagProps({ index })}
/>
))
}
css={css`
width: ${theme.breakpoints.down("xs") ? 200 : 300}px;
`}
/>
);
}