refactor
This commit is contained in:
@@ -96,7 +96,7 @@ const ApiTokensSection = ({
|
||||
const [newTokenExpires, setNewTokenExpires] = useState('');
|
||||
const [newTokenCapabilitySetId, setNewTokenCapabilitySetId] = useState<string>('');
|
||||
const [formError, setFormError] = useState<string | null>(null);
|
||||
const supportsClipboardWrite = typeof navigator !== 'undefined' && Boolean(navigator?.clipboard?.writeText);
|
||||
const supportsClipboardWrite = Boolean(navigator.clipboard?.writeText);
|
||||
const [canCopyToken, setCanCopyToken] = useState<boolean>(supportsClipboardWrite);
|
||||
const [copyFeedback, setCopyFeedback] = useState<CopyFeedbackState | null>(null);
|
||||
|
||||
@@ -125,12 +125,13 @@ const ApiTokensSection = ({
|
||||
const capabilitySelectionOptions = useMemo<CapabilitySelectionOption[]>(() => (
|
||||
Array.isArray(capabilities)
|
||||
? capabilities.map((capability) => {
|
||||
if (typeof capability !== 'string') {
|
||||
return { value: String(capability ?? ''), label: String(capability ?? '') };
|
||||
const capabilityText = `${capability ?? ''}`;
|
||||
if (!capabilityText.includes(':')) {
|
||||
return { value: capability, label: capabilityText };
|
||||
}
|
||||
const [namespace, action] = capability.split(':');
|
||||
const [namespace, action] = capabilityText.split(':');
|
||||
if (!namespace || !action) {
|
||||
return { value: capability, label: capability };
|
||||
return { value: capability, label: capabilityText };
|
||||
}
|
||||
const formattedNamespace = `${namespace.charAt(0).toUpperCase()}${namespace.slice(1)}`;
|
||||
const formattedAction = action.replace(/_/g, ' ');
|
||||
@@ -193,9 +194,6 @@ const ApiTokensSection = ({
|
||||
});
|
||||
|
||||
try {
|
||||
if (typeof navigator === 'undefined') {
|
||||
throw new Error('Clipboard API unavailable');
|
||||
}
|
||||
await navigator.clipboard.writeText(createdToken);
|
||||
showSuccess();
|
||||
return;
|
||||
@@ -214,8 +212,7 @@ const ApiTokensSection = ({
|
||||
|
||||
useEffect(() => {
|
||||
setCopyFeedback(null);
|
||||
const hasClipboard = typeof navigator !== 'undefined' && Boolean(navigator?.clipboard?.writeText);
|
||||
setCanCopyToken(hasClipboard);
|
||||
setCanCopyToken(Boolean(navigator.clipboard?.writeText));
|
||||
}, [createdToken]);
|
||||
|
||||
const handleNewCapabilitySetChange = useCallback((event: ChangeEvent<HTMLSelectElement>) => {
|
||||
|
||||
@@ -8,6 +8,7 @@ import React, {
|
||||
import type { SettingsSectionConfig } from '../SettingsModal';
|
||||
import { IconX } from '../../ui/icons';
|
||||
import CapabilityDropdown, { CapabilityDropdownOption } from '../components/CapabilityDropdown';
|
||||
import { isPlainObject } from '../../utils/typeGuards';
|
||||
|
||||
type CapabilityValue = string | number;
|
||||
type CapabilitySetId = string | number;
|
||||
@@ -54,12 +55,15 @@ interface CapabilitySetsSectionProps {
|
||||
|
||||
type CapabilityOptionInput = CapabilityDropdownOption | CapabilityValue | null | undefined;
|
||||
|
||||
const isCapabilityOption = (option: CapabilityOptionInput): option is CapabilityDropdownOption =>
|
||||
isPlainObject(option);
|
||||
|
||||
const resolveCapabilityValue = (option: CapabilityOptionInput): CapabilityValue | null => {
|
||||
if (option == null) {
|
||||
return null;
|
||||
}
|
||||
if (typeof option === 'string' || typeof option === 'number') {
|
||||
return option;
|
||||
if (!isCapabilityOption(option)) {
|
||||
return option as CapabilityValue;
|
||||
}
|
||||
if (option.value != null) {
|
||||
return option.value as CapabilityValue;
|
||||
@@ -99,12 +103,13 @@ const CapabilitySetsSection: React.FC<CapabilitySetsSectionProps> = ({
|
||||
|
||||
const capabilitySelectionOptions = useMemo<CapabilityDropdownOption[]>(() => (
|
||||
(capabilities ?? []).map((capability) => {
|
||||
if (typeof capability !== 'string') {
|
||||
return { value: capability, label: String(capability) };
|
||||
const capabilityLabel = `${capability ?? ''}`;
|
||||
if (!capabilityLabel.includes(':')) {
|
||||
return { value: capability, label: capabilityLabel };
|
||||
}
|
||||
const [namespace, action] = capability.split(':');
|
||||
const [namespace, action] = capabilityLabel.split(':');
|
||||
if (!namespace || !action) {
|
||||
return { value: capability, label: capability };
|
||||
return { value: capability, label: capabilityLabel };
|
||||
}
|
||||
const formattedNamespace = `${namespace.charAt(0).toUpperCase()}${namespace.slice(1)}`;
|
||||
const formattedAction = action.replace(/_/g, ' ');
|
||||
@@ -161,7 +166,7 @@ const CapabilitySetsSection: React.FC<CapabilitySetsSectionProps> = ({
|
||||
label: set.label || set.slug || set.id,
|
||||
capabilities: Array.isArray(set.capabilities) ? set.capabilities : [],
|
||||
isSystem: Boolean(set?.is_system),
|
||||
version: typeof set?.cap_version === 'number' ? set.cap_version : null,
|
||||
version: Number.isFinite(set?.cap_version) ? Number(set.cap_version) : null,
|
||||
})),
|
||||
[capabilitySets],
|
||||
);
|
||||
@@ -492,7 +497,7 @@ const CapabilitySetsSection: React.FC<CapabilitySetsSectionProps> = ({
|
||||
: '—'}
|
||||
</td>
|
||||
<td>{isSystem ? 'Yes' : 'No'}</td>
|
||||
<td>{typeof set.cap_version === 'number' ? set.cap_version : '—'}</td>
|
||||
<td>{Number.isFinite(set.cap_version) ? Number(set.cap_version) : '—'}</td>
|
||||
<td className="settings-table__actions">
|
||||
{isSystem ? (
|
||||
<span className="settings-status">System set</span>
|
||||
|
||||
Reference in New Issue
Block a user