Fix type-check issues

This commit is contained in:
2025-05-18 16:36:20 +02:00
parent 3619cf4ed4
commit 60ab01b0c8
11 changed files with 41 additions and 38 deletions

View File

@@ -55,7 +55,9 @@ const MarkdownPreview: React.FC<MarkdownPreviewProps> = ({
const [filePath] = decodeURIComponent( const [filePath] = decodeURIComponent(
href.replace(`${baseUrl}/internal/`, '') href.replace(`${baseUrl}/internal/`, '')
).split('#'); ).split('#');
handleFileSelect(filePath); if (filePath) {
handleFileSelect(filePath);
}
} else if (href.startsWith(`${baseUrl}/notfound/`)) { } else if (href.startsWith(`${baseUrl}/notfound/`)) {
// For non-existent files, show a notification // For non-existent files, show a notification
const fileName = decodeURIComponent( const fileName = decodeURIComponent(
@@ -105,9 +107,6 @@ const MarkdownPreview: React.FC<MarkdownPreviewProps> = ({
</a> </a>
), ),
code: ({ children, className, ...props }: MarkdownCodeProps) => { code: ({ children, className, ...props }: MarkdownCodeProps) => {
const language = className
? className.replace('language-', '')
: null;
return ( return (
<pre className={className}> <pre className={className}>
<code {...props}>{children}</code> <code {...props}>{children}</code>

View File

@@ -30,7 +30,7 @@ const EditUserModal: React.FC<EditUserModalProps> = ({
const [formData, setFormData] = useState<UpdateUserRequest>({ const [formData, setFormData] = useState<UpdateUserRequest>({
email: '', email: '',
displayName: '', displayName: '',
role: undefined, role: UserRole.Editor,
password: '', password: '',
}); });
@@ -58,7 +58,7 @@ const EditUserModal: React.FC<EditUserModalProps> = ({
setFormData({ setFormData({
email: '', email: '',
displayName: '', displayName: '',
role: undefined, role: UserRole.Editor,
password: '', password: '',
}); });
onClose(); onClose();
@@ -88,9 +88,9 @@ const EditUserModal: React.FC<EditUserModalProps> = ({
<Select <Select
label="Role" label="Role"
required required
value={formData.role} value={formData.role ? formData.role.toString() : null}
onChange={(value) => onChange={(value) =>
setFormData({ ...formData, role: value as UserRole | undefined }) setFormData({ ...formData, role: value as UserRole })
} }
data={[ data={[
{ value: UserRole.Admin, label: 'Admin' }, { value: UserRole.Admin, label: 'Admin' },

View File

@@ -139,7 +139,7 @@ const WorkspaceSwitcher: React.FC = () => {
truncate truncate
c={ c={
isSelected isSelected
? theme.colors.blue[ ? (theme as any).colors.blue[
(theme as any).colorScheme === 'dark' (theme as any).colorScheme === 'dark'
? 0 ? 0
: 9 : 9

View File

@@ -83,7 +83,7 @@ const AccountSettings: React.FC<AccountSettingsProps> = ({
if (isInitialMount.current && user) { if (isInitialMount.current && user) {
isInitialMount.current = false; isInitialMount.current = false;
const settings: UserProfileSettings = { const settings: UserProfileSettings = {
displayName: user.displayName, displayName: user.displayName || '',
email: user.email, email: user.email,
currentPassword: '', currentPassword: '',
newPassword: '', newPassword: '',
@@ -112,7 +112,7 @@ const AccountSettings: React.FC<AccountSettingsProps> = ({
// Add display name if changed // Add display name if changed
if (state.localSettings.displayName !== state.initialSettings.displayName) { if (state.localSettings.displayName !== state.initialSettings.displayName) {
updates.displayName = state.localSettings.displayName; updates.displayName = state.localSettings.displayName || '';
} }
// Handle password change // Handle password change
@@ -132,10 +132,10 @@ const AccountSettings: React.FC<AccountSettingsProps> = ({
// If we're only changing display name or have password already provided, proceed directly // If we're only changing display name or have password already provided, proceed directly
if (!needsPasswordConfirmation || state.localSettings.currentPassword) { if (!needsPasswordConfirmation || state.localSettings.currentPassword) {
if (needsPasswordConfirmation) { if (needsPasswordConfirmation) {
updates.email = state.localSettings.email; updates.email = state.localSettings.email || '';
// If we don't have a password change, we still need to include the current password for email change // If we don't have a password change, we still need to include the current password for email change
if (!updates.currentPassword) { if (!updates.currentPassword) {
updates.currentPassword = state.localSettings.currentPassword; updates.currentPassword = state.localSettings.currentPassword || '';
} }
} }

View File

@@ -4,12 +4,10 @@ import { useWorkspace } from '../../../contexts/WorkspaceContext';
import { Theme } from '@/types/theme'; import { Theme } from '@/types/theme';
interface AppearanceSettingsProps { interface AppearanceSettingsProps {
themeSettings?: Theme;
onThemeChange: (newTheme: Theme) => void; onThemeChange: (newTheme: Theme) => void;
} }
const AppearanceSettings: React.FC<AppearanceSettingsProps> = ({ const AppearanceSettings: React.FC<AppearanceSettingsProps> = ({
themeSettings,
onThemeChange, onThemeChange,
}) => { }) => {
const { colorScheme, updateColorScheme } = useWorkspace(); const { colorScheme, updateColorScheme } = useWorkspace();

View File

@@ -1,5 +1,5 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { Box, Button, Title } from '@mantine/core'; import { Box, Button } from '@mantine/core';
import DeleteWorkspaceModal from '../../modals/workspace/DeleteWorkspaceModal'; import DeleteWorkspaceModal from '../../modals/workspace/DeleteWorkspaceModal';
import { useWorkspace } from '../../../contexts/WorkspaceContext'; import { useWorkspace } from '../../../contexts/WorkspaceContext';
import { useModalContext } from '../../../contexts/ModalContext'; import { useModalContext } from '../../../contexts/ModalContext';

View File

@@ -192,7 +192,6 @@ const WorkspaceSettings: React.FC = () => {
<AccordionControl>Appearance</AccordionControl> <AccordionControl>Appearance</AccordionControl>
<Accordion.Panel> <Accordion.Panel>
<AppearanceSettings <AppearanceSettings
themeSettings={state.localSettings.theme}
onThemeChange={(newTheme: string) => onThemeChange={(newTheme: string) =>
handleInputChange('theme', newTheme) handleInputChange('theme', newTheme)
} }

View File

@@ -16,11 +16,7 @@ import {
deleteWorkspace, deleteWorkspace,
listWorkspaces, listWorkspaces,
} from '@/api/workspace'; } from '@/api/workspace';
import { import { Workspace, DEFAULT_WORKSPACE_SETTINGS } from '@/types/workspace';
Workspace,
DEFAULT_WORKSPACE_SETTINGS,
WorkspaceSettings,
} from '@/types/workspace';
interface WorkspaceContextType { interface WorkspaceContextType {
currentWorkspace: Workspace | null; currentWorkspace: Workspace | null;
@@ -89,6 +85,7 @@ export const WorkspaceProvider: React.FC<WorkspaceProviderProps> = ({
const allWorkspaces = await listWorkspaces(); const allWorkspaces = await listWorkspaces();
if (allWorkspaces.length > 0) { if (allWorkspaces.length > 0) {
const firstWorkspace = allWorkspaces[0]; const firstWorkspace = allWorkspaces[0];
if (!firstWorkspace) throw new Error('No workspaces available');
await updateLastWorkspaceName(firstWorkspace.name); await updateLastWorkspaceName(firstWorkspace.name);
await loadWorkspaceData(firstWorkspace.name); await loadWorkspaceData(firstWorkspace.name);
} }

View File

@@ -1,7 +1,8 @@
import { useState, useEffect } from 'react'; import { useState, useEffect } from 'react';
import { notifications } from '@mantine/notifications'; import { notifications } from '@mantine/notifications';
import { getUsers, getWorkspaces, getSystemStats } from '@/api/admin'; import { getUsers, getWorkspaces, getSystemStats } from '@/api/admin';
import { SystemStats, UserStats, WorkspaceStats } from '@/types/adminApi'; import { SystemStats, WorkspaceStats } from '@/types/adminApi';
import { User } from '@/types/authApi';
// Possible types of admin data // Possible types of admin data
type AdminDataType = 'stats' | 'workspaces' | 'users'; type AdminDataType = 'stats' | 'workspaces' | 'users';
@@ -12,7 +13,7 @@ type AdminData<T extends AdminDataType> = T extends 'stats'
: T extends 'workspaces' : T extends 'workspaces'
? WorkspaceStats[] ? WorkspaceStats[]
: T extends 'users' : T extends 'users'
? UserStats[] ? User[]
: never; : never;
// Define the return type of the hook // Define the return type of the hook
@@ -34,10 +35,8 @@ export const useAdminData = <T extends AdminDataType>(
} else if (type === 'workspaces') { } else if (type === 'workspaces') {
return [] as WorkspaceStats[] as AdminData<T>; return [] as WorkspaceStats[] as AdminData<T>;
} else if (type === 'users') { } else if (type === 'users') {
return [] as UserStats[] as AdminData<T>; return [] as User[] as AdminData<T>;
} else { } else {
// This case should never happen due to type constraints,
// but TypeScript requires us to handle it
return [] as unknown as AdminData<T>; return [] as unknown as AdminData<T>;
} }
}; };

View File

@@ -37,15 +37,14 @@ export const useGitOperations = (): UseGitOperationsResult => {
const handleCommitAndPush = useCallback( const handleCommitAndPush = useCallback(
async (message: string): Promise<void> => { async (message: string): Promise<void> => {
if (!currentWorkspace || !settings.gitEnabled) return; if (!currentWorkspace || !settings.gitEnabled) return;
const commitHash: CommitHash = await commitAndPush(
currentWorkspace.name,
message
);
try { try {
const commitHash: CommitHash = await commitAndPush(
currentWorkspace.name,
message
);
notifications.show({ notifications.show({
title: 'Success', title: 'Success',
message: 'Successfully committed and pushed changes', message: 'Successfully committed and pushed changes ' + commitHash,
color: 'green', color: 'green',
}); });
return; return;

View File

@@ -1,19 +1,20 @@
import { visit } from 'unist-util-visit'; import { visit } from 'unist-util-visit';
import { lookupFileByName, getFileUrl } from '../api/git';
import { InlineContainerType, MARKDOWN_REGEX } from '../types/markdown'; import { InlineContainerType, MARKDOWN_REGEX } from '../types/markdown';
import { Node } from 'unist'; import { Node } from 'unist';
import { Parent } from 'unist'; import { Parent } from 'unist';
import { Text } from 'mdast'; import { Text } from 'mdast';
import { lookupFileByName } from '@/api/file';
import { getFileUrl } from './fileHelpers';
/** /**
* Represents a wiki link match from the regex * Represents a wiki link match from the regex
*/ */
interface WikiLinkMatch { interface WikiLinkMatch {
fullMatch: string; fullMatch: string;
isImage: string; isImage: boolean; // Changed from string to boolean
fileName: string; fileName: string;
displayText: string; displayText: string;
heading?: string; heading?: string | undefined;
index: number; index: number;
} }
@@ -171,11 +172,22 @@ export function remarkWikiLinks(workspaceName: string) {
const matches: WikiLinkMatch[] = []; const matches: WikiLinkMatch[] = [];
while ((match = regex.exec(node.value)) !== null) { while ((match = regex.exec(node.value)) !== null) {
const [fullMatch, isImage, innerContent] = match; // Provide default values during destructuring to handle potential undefined values
const [fullMatch = '', isImageMark = '', innerContent = ''] = match;
// Skip if we somehow got a match without the expected content
if (!innerContent) {
console.warn('Matched wiki link without inner content:', fullMatch);
continue;
}
let fileName: string; let fileName: string;
let displayText: string; let displayText: string;
let heading: string | undefined; let heading: string | undefined;
// Convert isImageMark string to boolean
const isImage: boolean = isImageMark === '!';
const pipeIndex: number = innerContent.indexOf('|'); const pipeIndex: number = innerContent.indexOf('|');
const hashIndex: number = innerContent.indexOf('#'); const hashIndex: number = innerContent.indexOf('#');
@@ -231,7 +243,7 @@ export function remarkWikiLinks(workspaceName: string) {
lookupFileName lookupFileName
); );
if (paths && paths.length > 0) { if (paths && paths.length > 0 && paths[0]) {
const filePath: string = paths[0]; const filePath: string = paths[0];
if (match.isImage) { if (match.isImage) {
newNodes.push( newNodes.push(