mirror of
https://github.com/shuaiplus/nodewarden.git
synced 2026-06-20 13:00:39 +00:00
feat: refactor vault component helpers to use dedicated functions for options retrieval
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import ConfirmDialog from '@/components/ConfirmDialog';
|
||||
import type { CustomFieldType, Folder } from '@/lib/types';
|
||||
import { FIELD_TYPE_OPTIONS, toBooleanFieldValue } from '@/components/vault/vault-page-helpers';
|
||||
import { getFieldTypeOptions, toBooleanFieldValue } from '@/components/vault/vault-page-helpers';
|
||||
import { t } from '@/lib/i18n';
|
||||
|
||||
interface VaultDialogsProps {
|
||||
@@ -61,6 +61,7 @@ interface VaultDialogsProps {
|
||||
}
|
||||
|
||||
export default function VaultDialogs(props: VaultDialogsProps) {
|
||||
const fieldTypeOptions = getFieldTypeOptions();
|
||||
return (
|
||||
<>
|
||||
<ConfirmDialog
|
||||
@@ -75,7 +76,7 @@ export default function VaultDialogs(props: VaultDialogsProps) {
|
||||
<label className="field">
|
||||
<span>{t('txt_field_type')}</span>
|
||||
<select className="input" value={props.fieldType} onInput={(e) => props.onFieldTypeChange(Number((e.currentTarget as HTMLSelectElement).value) as CustomFieldType)}>
|
||||
{FIELD_TYPE_OPTIONS.map((option) => (
|
||||
{fieldTypeOptions.map((option) => (
|
||||
<option key={option.value} value={option.value}>
|
||||
{option.label}
|
||||
</option>
|
||||
|
||||
@@ -21,13 +21,13 @@ import { CSS } from '@dnd-kit/utilities';
|
||||
import type { Cipher, Folder, VaultDraft, VaultDraftField } from '@/lib/types';
|
||||
import { t } from '@/lib/i18n';
|
||||
import {
|
||||
CREATE_TYPE_OPTIONS,
|
||||
cipherTypeLabel,
|
||||
createEmptyLoginUri,
|
||||
formatAttachmentSize,
|
||||
formatHistoryTime,
|
||||
getCreateTypeOptions,
|
||||
getWebsiteMatchOptions,
|
||||
toBooleanFieldValue,
|
||||
WEBSITE_MATCH_OPTIONS,
|
||||
} from '@/components/vault/vault-page-helpers';
|
||||
|
||||
interface VaultEditorProps {
|
||||
@@ -77,6 +77,7 @@ interface SortableWebsiteRowProps {
|
||||
}
|
||||
|
||||
function SortableWebsiteRow(props: SortableWebsiteRowProps) {
|
||||
const websiteMatchOptions = getWebsiteMatchOptions();
|
||||
const { attributes, listeners, setActivatorNodeRef, setNodeRef, transform, transition, isDragging } = useSortable({
|
||||
id: props.id,
|
||||
});
|
||||
@@ -117,7 +118,7 @@ function SortableWebsiteRow(props: SortableWebsiteRowProps) {
|
||||
props.onUpdateMatch(props.index, raw === '' ? null : Number(raw));
|
||||
}}
|
||||
>
|
||||
{WEBSITE_MATCH_OPTIONS.map((option) => (
|
||||
{websiteMatchOptions.map((option) => (
|
||||
<option key={`website-match-${String(option.value)}`} value={option.value == null ? '' : String(option.value)}>
|
||||
{option.label}
|
||||
</option>
|
||||
@@ -134,6 +135,7 @@ function SortableWebsiteRow(props: SortableWebsiteRowProps) {
|
||||
}
|
||||
|
||||
export default function VaultEditor(props: VaultEditorProps) {
|
||||
const createTypeOptions = getCreateTypeOptions();
|
||||
const uriIdSeedRef = useRef(0);
|
||||
const [uriItemIds, setUriItemIds] = useState<string[]>([]);
|
||||
const [activeUriId, setActiveUriId] = useState<string | null>(null);
|
||||
@@ -232,7 +234,7 @@ export default function VaultEditor(props: VaultEditorProps) {
|
||||
if (nextType === 5) props.onSeedSshDefaults();
|
||||
}}
|
||||
>
|
||||
{CREATE_TYPE_OPTIONS.map((option) => (
|
||||
{createTypeOptions.map((option) => (
|
||||
<option key={option.type} value={option.type}>
|
||||
{option.label}
|
||||
</option>
|
||||
|
||||
@@ -6,9 +6,9 @@ import LoadingState from '@/components/LoadingState';
|
||||
import type { Cipher } from '@/lib/types';
|
||||
import { t } from '@/lib/i18n';
|
||||
import {
|
||||
CREATE_TYPE_OPTIONS,
|
||||
CreateTypeIcon,
|
||||
VAULT_SORT_OPTIONS,
|
||||
getCreateTypeOptions,
|
||||
getVaultSortOptions,
|
||||
VaultListIcon,
|
||||
type SidebarFilter,
|
||||
type VaultSortMode,
|
||||
@@ -106,6 +106,8 @@ const CipherListItem = memo(function CipherListItem(props: CipherListItemProps)
|
||||
});
|
||||
|
||||
export default function VaultListPanel(props: VaultListPanelProps) {
|
||||
const createTypeOptions = getCreateTypeOptions();
|
||||
const vaultSortOptions = getVaultSortOptions();
|
||||
const createMenu = (
|
||||
<div className="create-menu-wrap mobile-fab-wrap" ref={props.createMenuRef}>
|
||||
<button
|
||||
@@ -119,7 +121,7 @@ export default function VaultListPanel(props: VaultListPanelProps) {
|
||||
</button>
|
||||
{props.createMenuOpen && (
|
||||
<div className="create-menu">
|
||||
{CREATE_TYPE_OPTIONS.map((option) => (
|
||||
{createTypeOptions.map((option) => (
|
||||
<button key={option.type} type="button" className="create-menu-item" onClick={() => props.onStartCreate(option.type)}>
|
||||
<CreateTypeIcon type={option.type} />
|
||||
<span>{option.label}</span>
|
||||
@@ -171,7 +173,7 @@ export default function VaultListPanel(props: VaultListPanelProps) {
|
||||
</button>
|
||||
{props.sortMenuOpen && (
|
||||
<div className="sort-menu">
|
||||
{VAULT_SORT_OPTIONS.map((option) => (
|
||||
{vaultSortOptions.map((option) => (
|
||||
<button
|
||||
key={option.value}
|
||||
type="button"
|
||||
|
||||
@@ -21,7 +21,7 @@ import {
|
||||
} from 'lucide-preact';
|
||||
import type { Folder } from '@/lib/types';
|
||||
import { t } from '@/lib/i18n';
|
||||
import { FOLDER_SORT_OPTIONS, type SidebarFilter, type VaultSortMode } from '@/components/vault/vault-page-helpers';
|
||||
import { getFolderSortOptions, type SidebarFilter, type VaultSortMode } from '@/components/vault/vault-page-helpers';
|
||||
|
||||
interface VaultSidebarProps {
|
||||
folders: Folder[];
|
||||
@@ -43,6 +43,7 @@ interface VaultSidebarProps {
|
||||
}
|
||||
|
||||
export default function VaultSidebar(props: VaultSidebarProps) {
|
||||
const folderSortOptions = getFolderSortOptions();
|
||||
const nameCollator = useMemo(
|
||||
() => new Intl.Collator(undefined, { sensitivity: 'base', numeric: true }),
|
||||
[]
|
||||
@@ -143,7 +144,7 @@ export default function VaultSidebar(props: VaultSidebarProps) {
|
||||
</button>
|
||||
{props.folderSortMenuOpen && (
|
||||
<div className="sort-menu">
|
||||
{FOLDER_SORT_OPTIONS.map((option) => (
|
||||
{folderSortOptions.map((option) => (
|
||||
<button
|
||||
key={option.value}
|
||||
type="button"
|
||||
|
||||
@@ -28,45 +28,56 @@ interface TypeOption {
|
||||
label: string;
|
||||
}
|
||||
|
||||
export const CREATE_TYPE_OPTIONS: TypeOption[] = [
|
||||
{ type: 1, label: t('txt_login') },
|
||||
{ type: 3, label: t('txt_card') },
|
||||
{ type: 4, label: t('txt_identity') },
|
||||
{ type: 2, label: t('txt_note') },
|
||||
{ type: 5, label: t('txt_ssh_key') },
|
||||
];
|
||||
export function getCreateTypeOptions(): TypeOption[] {
|
||||
return [
|
||||
{ type: 1, label: t('txt_login') },
|
||||
{ type: 3, label: t('txt_card') },
|
||||
{ type: 4, label: t('txt_identity') },
|
||||
{ type: 2, label: t('txt_note') },
|
||||
{ type: 5, label: t('txt_ssh_key') },
|
||||
];
|
||||
}
|
||||
|
||||
export const VAULT_SORT_STORAGE_KEY = 'nodewarden.vault.sort.v1';
|
||||
export const FOLDER_SORT_STORAGE_KEY = 'nodewarden.folder-sort.v1';
|
||||
export const MOBILE_LAYOUT_QUERY = '(max-width: 1180px)';
|
||||
export const VAULT_LIST_ROW_HEIGHT = 74;
|
||||
export const VAULT_LIST_OVERSCAN = 10;
|
||||
export const VAULT_SORT_OPTIONS: Array<{ value: VaultSortMode; label: string }> = [
|
||||
{ value: 'edited', label: t('txt_sort_last_edited') },
|
||||
{ value: 'created', label: t('txt_sort_created') },
|
||||
{ value: 'name', label: t('txt_sort_name') },
|
||||
];
|
||||
export const FOLDER_SORT_OPTIONS: Array<{ value: VaultSortMode; label: string }> = [
|
||||
{ value: 'edited', label: t('txt_sort_last_edited') },
|
||||
{ value: 'created', label: t('txt_sort_created') },
|
||||
{ value: 'name', label: t('txt_sort_name') },
|
||||
];
|
||||
export function getVaultSortOptions(): Array<{ value: VaultSortMode; label: string }> {
|
||||
return [
|
||||
{ value: 'edited', label: t('txt_sort_last_edited') },
|
||||
{ value: 'created', label: t('txt_sort_created') },
|
||||
{ value: 'name', label: t('txt_sort_name') },
|
||||
];
|
||||
}
|
||||
|
||||
export const FIELD_TYPE_OPTIONS: Array<{ value: CustomFieldType; label: string }> = [
|
||||
{ value: 0, label: t('txt_text') },
|
||||
{ value: 1, label: t('txt_hidden') },
|
||||
{ value: 2, label: t('txt_boolean') },
|
||||
];
|
||||
export function getFolderSortOptions(): Array<{ value: VaultSortMode; label: string }> {
|
||||
return [
|
||||
{ value: 'edited', label: t('txt_sort_last_edited') },
|
||||
{ value: 'created', label: t('txt_sort_created') },
|
||||
{ value: 'name', label: t('txt_sort_name') },
|
||||
];
|
||||
}
|
||||
|
||||
export const WEBSITE_MATCH_OPTIONS: Array<{ value: number | null; label: string }> = [
|
||||
{ value: null, label: t('txt_uri_match_default_base_domain') },
|
||||
{ value: 0, label: t('txt_uri_match_base_domain') },
|
||||
{ value: 1, label: t('txt_uri_match_host') },
|
||||
{ value: 3, label: t('txt_uri_match_exact') },
|
||||
{ value: 5, label: t('txt_uri_match_never') },
|
||||
{ value: 2, label: t('txt_uri_match_starts_with') },
|
||||
{ value: 4, label: t('txt_uri_match_regular_expression') },
|
||||
];
|
||||
export function getFieldTypeOptions(): Array<{ value: CustomFieldType; label: string }> {
|
||||
return [
|
||||
{ value: 0, label: t('txt_text') },
|
||||
{ value: 1, label: t('txt_hidden') },
|
||||
{ value: 2, label: t('txt_boolean') },
|
||||
];
|
||||
}
|
||||
|
||||
export function getWebsiteMatchOptions(): Array<{ value: number | null; label: string }> {
|
||||
return [
|
||||
{ value: null, label: t('txt_uri_match_default_base_domain') },
|
||||
{ value: 0, label: t('txt_uri_match_base_domain') },
|
||||
{ value: 1, label: t('txt_uri_match_host') },
|
||||
{ value: 3, label: t('txt_uri_match_exact') },
|
||||
{ value: 5, label: t('txt_uri_match_never') },
|
||||
{ value: 2, label: t('txt_uri_match_starts_with') },
|
||||
{ value: 4, label: t('txt_uri_match_regular_expression') },
|
||||
];
|
||||
}
|
||||
|
||||
export const TOTP_PERIOD_SECONDS = 30;
|
||||
export const TOTP_RING_RADIUS = 14;
|
||||
@@ -156,7 +167,7 @@ export function createEmptyLoginUri(): VaultDraftLoginUri {
|
||||
|
||||
export function websiteMatchLabel(value: number | null | undefined): string {
|
||||
const normalized = typeof value === 'number' && Number.isFinite(value) ? value : null;
|
||||
return WEBSITE_MATCH_OPTIONS.find((option) => option.value === normalized)?.label || t('txt_uri_match_default_base_domain');
|
||||
return getWebsiteMatchOptions().find((option) => option.value === normalized)?.label || t('txt_uri_match_default_base_domain');
|
||||
}
|
||||
|
||||
function valueOrFallback(value: string | null | undefined): string {
|
||||
|
||||
Reference in New Issue
Block a user